courses_1/Introduction to Gazebo Sim .../2.3 Creating a Mobile Rob.../copy_code_cells.js

128 lines
4.2 KiB
JavaScript

/**
* Initialize variables
*/
// for tracking notebook url
let notebookLocation = window.location.href;
// for tracking the scrollbar position
let scrollPercentage = 0;
let lastWidth = window.innerWidth;
/**
* Helper: Standard Debounce Function
*/
function debounce(func, wait) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
function windowScrolled(_event) {
const maxScroll = document.documentElement.scrollHeight - window.innerHeight;
if (maxScroll > 0) {
scrollPercentage = window.scrollY / maxScroll;
}
}
/**
* windowResized is called when the browser window is resized.
* It adjusts the scroll position to maintain approximately the same visible portion of the page.
*/
const windowResized = debounce(() => {
// console.log('window resized...')
const currentWidth = window.innerWidth;
// Only adjust if the width actually changed
if (currentWidth !== lastWidth) {
lastWidth = currentWidth;
const newMaxScroll = document.documentElement.scrollHeight - window.innerHeight;
const newScrollTop = scrollPercentage * newMaxScroll;
window.scrollTo({
top: newScrollTop,
behavior: 'smooth' // Or 'auto'
});
}
}, 200); // 200ms delay after the last resize event
/**
* clickCallback handles clicks on links to prevent default browser navigation.
* It checks if the clicked link points to the current page or a different one.
* For same page links, it updates window.location.href to navigate.
* For external links, it opens the URL in a new tab/window.
*/
function clickCallback(event) {
// console.log(`Notebook location ${notebookLocation}`);
if (event.target.tagName !== 'A') return;
event.preventDefault();
const link = event.target.href;
if (link.startsWith(notebookLocation)) {
// console.log("same page");
window.location.href = link;
} else {
// console.log("different page");
window.open(link, '_blank');
}
}
/**
* Adds a copy button to code cells to allow copying cell contents.
* Searches for code cells with selectors and inserts a copy button.
*/
function addCopyThisButton() {
// Add a 'copy this' button to every code cell
// The bottons are added just before the code cells with the classes specified in 'selectors'
let selectors = [".hl-ipython2", ".hl-ipython3"];
let html = "<button title='Copy this code' class='copy-code-btn' style='position: absolute; top: 5px; right: 5px;"
html += "color: lightseagreen; font-weight: bold;'><i class='fa fa-clipboard' aria-hidden='true'></i></button>";
let cells;
for (let selector of selectors) {
cells = [];
cells = document.querySelectorAll(selector);
cells.forEach(cell => cell.insertAdjacentHTML("beforebegin", html));
}
}
/**
* domLoaded is called when the DOM has loaded.
* It sets up event listeners and calls addCopyThisButton to add copy buttons.
*/
function domLoaded() {
addCopyThisButton();
notebookLocation = window.location.href;
// Add event listeners
window.addEventListener('scroll', windowScrolled);
window.addEventListener('resize', windowResized);
if (document.addEventListener) document.addEventListener('click', clickCallback, false);
else document.attachEvent('onclick', clickCallback);
// add the logic for copying the content of the code cells to the clipboard
// courtesy of https://clipboardjs.com/
let clipboard = new ClipboardJS('.copy-code-btn', {
target: function(trigger) {
return trigger.nextElementSibling;
}
});
// what do do after the item has been copied to the clipboard
clipboard.on('success', function(e) {
let trigger = e.trigger;
e.clearSelection();
const btnTextBackup = trigger.innerHTML;
trigger.disabled = true;
trigger.innerText = 'Copied!';
setTimeout(() => {
trigger.innerHTML = btnTextBackup;
trigger.disabled = false;
}, 2000);
});
}
// what to do when the DOM has loaded
document.addEventListener("DOMContentLoaded", domLoaded);