Add link previews on hover
This commit is contained in:
		
							parent
							
								
									d8b794908f
								
							
						
					
					
						commit
						b6849b30aa
					
				| @ -1 +1 @@ | |||||||
| This is the footer. Include anything you'd like here, like a link to an <a href="/about">About</a> page. | This is the footer. Include anything you'd like here, like a link to an <a class="internal-link" href="/about">About</a> page. | ||||||
|  | |||||||
							
								
								
									
										119
									
								
								_includes/link-previews.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								_includes/link-previews.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,119 @@ | |||||||
|  | <!-- That file is not particularly elegant. This will need a refactor at some point. --> | ||||||
|  | <style> | ||||||
|  |   content a.internal-link { | ||||||
|  |     border-color: #8b88e6; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   #tooltip-wrapper { | ||||||
|  |     background: white; | ||||||
|  |     padding: 1em; | ||||||
|  |     border: 1px solid #ddd; | ||||||
|  |     border-radius: 4px; | ||||||
|  |     overflow: hidden; | ||||||
|  |     position: absolute; | ||||||
|  |     width: 400px; | ||||||
|  |     height: 250px; | ||||||
|  |     font-size: 0.8em; | ||||||
|  |     box-shadow: 0 5px 10px rgba(0,0,0,0.1); | ||||||
|  |     opacity: 0; | ||||||
|  |     transition: opacity 100ms; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   #tooltip-wrapper:after { | ||||||
|  | 		content: ""; | ||||||
|  | 		position: absolute; | ||||||
|  | 		z-index: 1; | ||||||
|  | 		bottom: 0; | ||||||
|  | 		left: 0; | ||||||
|  | 		pointer-events: none; | ||||||
|  | 		background-image: linear-gradient(to bottom, rgba(255,255,255, 0), rgba(255,255,255, 1) 90%); | ||||||
|  | 		width: 100%; | ||||||
|  | 		height: 75px; | ||||||
|  |   } | ||||||
|  | </style> | ||||||
|  | 
 | ||||||
|  | <div style="opacity: 0; display: none;" id='tooltip-wrapper'> | ||||||
|  |   <div id='tooltip-content'> | ||||||
|  |   </div> | ||||||
|  | </div> | ||||||
|  | 
 | ||||||
|  | <iframe style="display: none; height: 0; width: 0;" id='link-preview-iframe' src=""> | ||||||
|  | </iframe> | ||||||
|  | 
 | ||||||
|  | <script> | ||||||
|  |   var opacityTimeout; | ||||||
|  |   var contentTimeout; | ||||||
|  |   var transitionDurationMs = 100; | ||||||
|  | 
 | ||||||
|  |   var iframe = document.getElementById('link-preview-iframe') | ||||||
|  |   var tooltipWrapper = document.getElementById('tooltip-wrapper') | ||||||
|  |   var tooltipContent = document.getElementById('tooltip-content') | ||||||
|  | 
 | ||||||
|  |   function hideTooltip() { | ||||||
|  |     opacityTimeout = setTimeout(function() { | ||||||
|  |       tooltipWrapper.style.opacity = 0; | ||||||
|  |       contentTimeout = setTimeout(function() { | ||||||
|  |         tooltipContent.innerHTML = ''; | ||||||
|  |         tooltipWrapper.style.display = 'none'; | ||||||
|  |       }, transitionDurationMs + 1); | ||||||
|  |     }, transitionDurationMs) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function showTooltip(event) { | ||||||
|  |     var elem = event.target; | ||||||
|  |     var elem_props = elem.getClientRects()[elem.getClientRects().length - 1]; | ||||||
|  |     var top = window.pageYOffset || document.documentElement.scrollTop | ||||||
|  | 
 | ||||||
|  |     if (event.target.host === window.location.host) { | ||||||
|  |       iframe.src = event.target.href | ||||||
|  |       iframe.onload = function() { | ||||||
|  |         tooltipContentHtml = '' | ||||||
|  |         tooltipContentHtml += '<div style="font-weight: bold;">' + iframe.contentWindow.document.querySelector('h1').innerHTML + '</div>' | ||||||
|  |         tooltipContentHtml += iframe.contentWindow.document.querySelector('content').innerHTML | ||||||
|  | 
 | ||||||
|  |         tooltipContent.innerHTML = tooltipContentHtml | ||||||
|  | 
 | ||||||
|  |         tooltipWrapper.style.display = 'block'; | ||||||
|  |         setTimeout(function() { | ||||||
|  |           tooltipWrapper.style.opacity = 1; | ||||||
|  |         }, 1) | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       tooltipWrapper.style.left = elem_props.left - (tooltipWrapper.offsetWidth / 2) + (elem_props.width / 2) + "px"; | ||||||
|  |       if ((window.innerHeight - elem_props.top) < (tooltipWrapper.offsetHeight)) { | ||||||
|  |           tooltipWrapper.style.top = elem_props.top + top - tooltipWrapper.offsetHeight - 10 + "px"; | ||||||
|  |       } else if ((window.innerHeight - elem_props.top) > (tooltipWrapper.offsetHeight)) { | ||||||
|  |           tooltipWrapper.style.top = elem_props.top + top + 35 + "px"; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if ((elem_props.left + (elem_props.width / 2)) < (tooltipWrapper.offsetWidth / 2)) { | ||||||
|  |           tooltipWrapper.style.left = "10px"; | ||||||
|  |       } else if ((document.body.clientWidth - elem_props.left - (elem_props.width / 2)) < (tooltipWrapper.offsetWidth / 2)) { | ||||||
|  |           tooltipWrapper.style.left = document.body.clientWidth - tooltipWrapper.offsetWidth - 20 + "px"; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function setupListeners(linkElement) { | ||||||
|  |     linkElement.addEventListener('mouseleave', function(_event) { | ||||||
|  |       hideTooltip(); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     tooltipWrapper.addEventListener('mouseleave', function(_event) { | ||||||
|  |       hideTooltip(); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     linkElement.addEventListener('mouseenter', function(event) { | ||||||
|  |       clearTimeout(opacityTimeout); | ||||||
|  |       clearTimeout(contentTimeout); | ||||||
|  |       showTooltip(event); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     tooltipWrapper.addEventListener('mouseenter', function(event) { | ||||||
|  |       clearTimeout(opacityTimeout); | ||||||
|  |       clearTimeout(contentTimeout); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   document.querySelectorAll('{{ include.wrapperQuerySelector }} a').forEach(setupListeners); | ||||||
|  | </script> | ||||||
| @ -1,3 +1,3 @@ | |||||||
| <div> | <div> | ||||||
|     <a href="/"><b>{{ site.title }}</b></a> |     <a class="internal-link" href="/"><b>{{ site.title }}</b></a> | ||||||
| </div> | </div> | ||||||
|  | |||||||
| @ -7,5 +7,7 @@ | |||||||
|       <main>{{ content }}</main> |       <main>{{ content }}</main> | ||||||
|       <footer>{% include footer.html %}</footer> |       <footer>{% include footer.html %}</footer> | ||||||
|     </div> |     </div> | ||||||
|  | 
 | ||||||
|  |     {% include link-previews.html wrapperQuerySelector="content" %} | ||||||
|   </body> |   </body> | ||||||
| </html> | </html> | ||||||
|  | |||||||
| @ -22,7 +22,7 @@ layout: default | |||||||
|       <div style="display: grid; grid-gap: 1em; grid-template-columns: repeat(1fr);"> |       <div style="display: grid; grid-gap: 1em; grid-template-columns: repeat(1fr);"> | ||||||
|       {% for backlink in page.backlinks %} |       {% for backlink in page.backlinks %} | ||||||
|         <div class="backlink-box"> |         <div class="backlink-box"> | ||||||
|         <a href="{{ backlink.url }}">{{ backlink.title }}</a><br> |         <a class="internal-link" href="{{ backlink.url }}">{{ backlink.title }}</a><br> | ||||||
|         <div style="font-size: 0.9em">{{ backlink.excerpt | strip_html | truncatewords: 20 }}</div> |         <div style="font-size: 0.9em">{{ backlink.excerpt | strip_html | truncatewords: 20 }}</div> | ||||||
|         </div> |         </div> | ||||||
|       {% endfor %} |       {% endfor %} | ||||||
| @ -37,5 +37,5 @@ layout: default | |||||||
|       {% endif %} |       {% endif %} | ||||||
|     </side> |     </side> | ||||||
|   </div> |   </div> | ||||||
| 
 |  | ||||||
| </article> | </article> | ||||||
|  | 
 | ||||||
|  | |||||||
							
								
								
									
										7
									
								
								_layouts/page.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								_layouts/page.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | |||||||
|  | --- | ||||||
|  | layout: default | ||||||
|  | --- | ||||||
|  | 
 | ||||||
|  | <content> | ||||||
|  |   {{ content }} | ||||||
|  | </content> | ||||||
| @ -4,4 +4,4 @@ title: Consistency is key | |||||||
| 
 | 
 | ||||||
| Show up. Do the work. Be consistent. | Show up. Do the work. Be consistent. | ||||||
| 
 | 
 | ||||||
| Then go take a look at the [first note](/your-first-note). | Then go take a look at the [first note](/your-first-note){: .internal-link}. | ||||||
|  | |||||||
| @ -3,14 +3,36 @@ title: Your first seed | |||||||
| image: /assets/image.jpg | image: /assets/image.jpg | ||||||
| --- | --- | ||||||
| 
 | 
 | ||||||
| This is your first note. | ### Welcome! | ||||||
| 
 | 
 | ||||||
| To link to another note, use regular Markdown syntax for links, with a relative link to the other note, like this: [this is a link to a note about cats](/cats). | This is your first note. You'll find it in the `notes/` directory. | ||||||
| 
 | 
 | ||||||
| You can also use Roam-style link syntax by wrapping a note's title in double brackets, like this: [[A note about cats]]. If the Roam-style link does not point to a valid note's title, the double brackets will still be shown, like this: [[This note does not exist]]. | ### Link syntax | ||||||
|  | 
 | ||||||
|  | To link to another note, you can use regular [Markdown syntax](https://www.markdownguide.org/getting-started/) for links, with a relative link to the other note, like this: [this is a link to a note about cats](/cats){: .internal-link}. Don't forget to use the `.internal-link` class to make sure the link is styled as an internal link. | ||||||
|  | 
 | ||||||
|  | Since the Web is all about HTML, you can always use plain HTML if you want, like this: <a class="internal-link" href="/cats">This is the same note about cats as above</a>. | ||||||
|  | 
 | ||||||
|  | Of course, you can also link to external websites, like this: [this is a link to Wikipedia](https://wikipedia.org/). Again, you can use plain HTML if you prefer. | ||||||
|  | 
 | ||||||
|  | Additionally, you can use Roam/wiki-style link syntax by wrapping a note's title in double brackets, like this: [[A note about cats]]. If the Roam-style link does not point to a valid note's title, the double brackets will still be shown, like this: [[There is no note with this title]]. | ||||||
|  | 
 | ||||||
|  | ### Automatic bi-directional links | ||||||
| 
 | 
 | ||||||
| Notice in the "Notes mentioning this note" section that there is another note linking to this note. This is a bi-directional link, and those are automatically created when you create links to other notes. | Notice in the "Notes mentioning this note" section that there is another note linking to this note. This is a bi-directional link, and those are automatically created when you create links to other notes. | ||||||
| 
 | 
 | ||||||
| You can display images using Markdown's image tag, like this: | ### Link previews | ||||||
|  | 
 | ||||||
|  | If you're on a device with mouse support, try hovering your mouse on internal links to preview the notes: [[A note about cats]] | ||||||
|  | 
 | ||||||
|  | ### Images | ||||||
|  | 
 | ||||||
|  | Finally, you can display images using Markdown syntax, like this: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | 
 | ||||||
|  | ### Next steps | ||||||
|  | 
 | ||||||
|  | If this template is useful to you in any way, consider [donating](https://github.com/sponsors/maximevaillancourt) to support my work. | ||||||
|  | 
 | ||||||
|  | Go forth, have fun, and learn new something every day! ✌️ | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| --- | --- | ||||||
| layout: default | layout: page | ||||||
| title: About | title: About | ||||||
| permalink: /about | permalink: /about | ||||||
| --- | --- | ||||||
|  | |||||||
| @ -1,11 +1,10 @@ | |||||||
| --- | --- | ||||||
| layout: default | layout: page | ||||||
| title: Home | title: Home | ||||||
| id: home | id: home | ||||||
| permalink: / | permalink: / | ||||||
| --- | --- | ||||||
| 
 | 
 | ||||||
| <div> | # Welcome! 🌱 | ||||||
|   <h1>Welcome! 🌱</h1> | 
 | ||||||
|   <p>This is your digital garden. Here's [[Your first seed]] to get started on your exploration.</p> | This is your digital garden. Here's [[Your first seed]] to get started on your exploration. | ||||||
| </div> |  | ||||||
|  | |||||||
| @ -83,6 +83,16 @@ a { | |||||||
|     color: black !important; |     color: black !important; | ||||||
|     background: #fffaf1; |     background: #fffaf1; | ||||||
|   } |   } | ||||||
|  |   &:after { | ||||||
|  |     position: relative; | ||||||
|  |     top: -0.5em; | ||||||
|  |     font-size: 0.7em; | ||||||
|  |     content: "↗"; | ||||||
|  |     color: #aaaaaa; | ||||||
|  |   } | ||||||
|  |   &.internal-link:after { | ||||||
|  |     content: ""; | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| *:focus { | *:focus { | ||||||
| @ -116,3 +126,9 @@ ul { | |||||||
|   padding: 1em; |   padding: 1em; | ||||||
|   border-radius: $border-radius; |   border-radius: $border-radius; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | code { | ||||||
|  |   background: #f5f5f5; | ||||||
|  |   padding: 0.1em 0.2em; | ||||||
|  |   border-radius: 4px; | ||||||
|  | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Maxime Vaillancourt
						Maxime Vaillancourt