/* ======= OPTIONS ======== */ // BULLET let scale = 2; let bulletColor = '#E4564A'; // LINES let showLines = true; let lineWidth = 2; let lineColor = bulletColor; let borderRadius = 3; // HIGHLIGHT REFS let highlightRefs = true; let refColor = bulletColor; /* ======= LIBRARIES ======== */ /* * arrive.js * v2.4.1 * https://github.com/uzairfarooq/arrive * MIT licensed * * Copyright (c) 2014-2017 Uzair Farooq */ var Arrive=function(e,t,n){"use strict";function r(e,t,n){l.addMethod(t,n,e.unbindEvent),l.addMethod(t,n,e.unbindEventWithSelectorOrCallback),l.addMethod(t,n,e.unbindEventWithSelectorAndCallback)}function i(e){e.arrive=f.bindEvent,r(f,e,"unbindArrive"),e.leave=d.bindEvent,r(d,e,"unbindLeave")}if(e.MutationObserver&&"undefined"!=typeof HTMLElement){var o=0,l=function(){var t=HTMLElement.prototype.matches||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector;return{matchesSelector:function(e,n){return e instanceof HTMLElement&&t.call(e,n)},addMethod:function(e,t,r){var i=e[t];e[t]=function(){return r.length==arguments.length?r.apply(this,arguments):"function"==typeof i?i.apply(this,arguments):n}},callCallbacks:function(e,t){t&&t.options.onceOnly&&1==t.firedElems.length&&(e=[e[0]]);for(var n,r=0;n=e[r];r++)n&&n.callback&&n.callback.call(n.elem,n.elem);t&&t.options.onceOnly&&1==t.firedElems.length&&t.me.unbindEventWithSelectorAndCallback.call(t.target,t.selector,t.callback)},checkChildNodesRecursively:function(e,t,n,r){for(var i,o=0;i=e[o];o++)n(i,t,r)&&r.push({callback:t.callback,elem:i}),i.childNodes.length>0&&l.checkChildNodesRecursively(i.childNodes,t,n,r)},mergeArrays:function(e,t){var n,r={};for(n in e)e.hasOwnProperty(n)&&(r[n]=e[n]);for(n in t)t.hasOwnProperty(n)&&(r[n]=t[n]);return r},toElementsArray:function(t){return n===t||"number"==typeof t.length&&t!==e||(t=[t]),t}}}(),c=function(){var e=function(){this._eventsBucket=[],this._beforeAdding=null,this._beforeRemoving=null};return e.prototype.addEvent=function(e,t,n,r){var i={target:e,selector:t,options:n,callback:r,firedElems:[]};return this._beforeAdding&&this._beforeAdding(i),this._eventsBucket.push(i),i},e.prototype.removeEvent=function(e){for(var t,n=this._eventsBucket.length-1;t=this._eventsBucket[n];n--)if(e(t)){this._beforeRemoving&&this._beforeRemoving(t);var r=this._eventsBucket.splice(n,1);r&&r.length&&(r[0].callback=null)}},e.prototype.beforeAdding=function(e){this._beforeAdding=e},e.prototype.beforeRemoving=function(e){this._beforeRemoving=e},e}(),a=function(t,r){var i=new c,o=this,a={fireOnAttributesModification:!1};return i.beforeAdding(function(n){var i,l=n.target;(l===e.document||l===e)&&(l=document.getElementsByTagName("html")[0]),i=new MutationObserver(function(e){r.call(this,e,n)});var c=t(n.options);i.observe(l,c),n.observer=i,n.me=o}),i.beforeRemoving(function(e){e.observer.disconnect()}),this.bindEvent=function(e,t,n){t=l.mergeArrays(a,t);for(var r=l.toElementsArray(this),o=0;o0?l.checkChildNodesRecursively(n,t,r,o):"attributes"===e.type&&r(i,t,o)&&o.push({callback:t.callback,elem:i}),l.callCallbacks(o,t)})}function r(e,t){return l.matchesSelector(e,t.selector)&&(e._id===n&&(e._id=o++),-1==t.firedElems.indexOf(e._id))?(t.firedElems.push(e._id),!0):!1}var i={fireOnAttributesModification:!1,onceOnly:!1,existing:!1};f=new a(e,t);var c=f.bindEvent;return f.bindEvent=function(e,t,r){n===r?(r=t,t=i):t=l.mergeArrays(i,t);var o=l.toElementsArray(this);if(t.existing){for(var a=[],s=0;s0&&l.checkChildNodesRecursively(n,t,r,i),l.callCallbacks(i,t)})}function r(e,t){return l.matchesSelector(e,t.selector)}var i={};d=new a(e,t);var o=d.bindEvent;return d.bindEvent=function(e,t,r){n===r?(r=t,t=i):t=l.mergeArrays(i,t),o.call(this,e,t,r)},d},f=new s,d=new u;t&&i(t.fn),i(HTMLElement.prototype),i(NodeList.prototype),i(HTMLCollection.prototype),i(HTMLDocument.prototype),i(Window.prototype);var h={};return r(f,h,"unbindAllArrive"),r(d,h,"unbindAllLeave"),h}}(window,"undefined"==typeof jQuery?null:jQuery,void 0); /* ======= CODE ======== */ // Add custom style tag to document for CSS customization let style = document.createElement('style'); let baseStyle = ` .path-highlighted .rm-bullet .rm-bullet__inner, .path-highlighted .rm-bullet .rm-bullet__inner--user-icon { background-color: ${bulletColor} !important; transform: scale(${scale}); } ` if (highlightRefs) { baseStyle += ` .path-highlighted + .roam-block .rm-page-ref, .path-highlighted + .roam-block .rm-alias { color: ${refColor} !important; } .path-highlighted + .roam-block .rm-block-ref { border-bottom-color: ${refColor} !important; } ` } style.textContent = baseStyle document.body.appendChild(style); /* Toggle with Ctrl+i */ var pptoggle = true; let pathid = 0; // define a handler function ppkeypress(e) { if (e.ctrlKey && e.key === 'i') { pptoggle = !pptoggle; if (pptoggle) { let bullets = [].slice.call(document.querySelectorAll('.path-highlighted')); bullets.forEach(function(bullet) { bullet.classList.remove('path-highlighted'); }) } else { // Show highlighted bullets + path when block is focused let bullets = []; let elt = document.querySelectorAll('textarea.rm-block-input'); let block = elt[0].closest('.roam-block-container'); // iterate through parents and get bullet elements while (block) { bullets.push(block.querySelector('.controls')); block = block.parentElement.closest('.roam-block-container'); } // bullet styles cannot be applied directly to the element because they are pseudotags // so we'll create a style string and add it to the style tag we created earlier let bulletStyle = '' bullets.forEach(function(bullet, i) { let lastBullet = i > 0 ? bullets[i - 1] : null // give each bullet a special path identifier so that we can target it directly if (!bullet.dataset.pathidentifier) { bullet.dataset.pathidentifier = pathid++ } if (lastBullet != null && showLines == true) { let bboxA = lastBullet.getBoundingClientRect() let bboxB = bullet.getBoundingClientRect() bulletStyle += ` .path-highlighted[data-pathidentifier="${bullet.dataset.pathidentifier}"] .bp3-popover-target::before { content: ""; position: absolute; top: 10px; left: 6px; width: ${bboxA.x-bboxB.x}px; height: ${bboxA.y-bboxB.y}px; border: ${lineWidth}px solid ${lineColor}; border-right: none; border-top: none; border-bottom-left-radius: ${borderRadius}px; pointer-events: none; z-index: 11 !important; } ` } // highlight bullet bullet.classList.add('path-highlighted') }) // set content of style tag to include both the base styles from before and the bullet styles we just generated style.textContent = baseStyle + bulletStyle; } } } // register the handler document.addEventListener('keypress', ppkeypress, false); // Remove classes when block is unfocused document.leave('textarea.rm-block-input', function(el) { let bullets = [].slice.call(document.querySelectorAll('.path-highlighted')); bullets.forEach(function(bullet) { bullet.classList.remove('path-highlighted'); }) }) // Show highlighted bullets + path when block is focused document.arrive('textarea.rm-block-input', function(el) { if (!pptoggle) { let bullets = []; let block = el.closest('.roam-block-container'); // iterate through parents and get bullet elements while (block) { bullets.push(block.querySelector('.controls')); block = block.parentElement.closest('.roam-block-container') } // bullet styles cannot be applied directly to the element because they are pseudotags // so we'll create a style string and add it to the style tag we created earlier let bulletStyle = '' bullets.forEach(function(bullet, i) { let lastBullet = i > 0 ? bullets[i - 1] : null // give each bullet a special path identifier so that we can target it directly if (!bullet.dataset.pathidentifier) { bullet.dataset.pathidentifier = pathid++ } if (lastBullet != null && showLines == true) { let bboxA = lastBullet.getBoundingClientRect() let bboxB = bullet.getBoundingClientRect() bulletStyle += ` .path-highlighted[data-pathidentifier="${bullet.dataset.pathidentifier}"] .bp3-popover-target::before { content: ""; position: absolute; top: 10px; left: 6px; width: ${bboxA.x-bboxB.x}px; height: ${bboxA.y-bboxB.y}px; border: ${lineWidth}px solid ${lineColor}; border-right: none; border-top: none; border-bottom-left-radius: ${borderRadius}px; pointer-events: none; z-index: 11 !important; } ` } // highlight bullet bullet.classList.add('path-highlighted') }) // set content of style tag to include both the base styles from before and the bullet styles we just generated style.textContent = baseStyle + bulletStyle; } })