Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Saving playground code state #1917

Merged
merged 17 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion book.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ urlcolor = "red"

[output.html]
curly-quotes = true
additional-js = ["theme/speaker-notes.js", "theme/redbox.js"]
additional-js = [
"theme/speaker-notes.js",
"theme/redbox.js",
"theme/save-playgrounds.js",
]
additional-css = [
"theme/css/svgbob.css",
"theme/css/redbox.css",
Expand Down
137 changes: 100 additions & 37 deletions theme/redbox.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,101 @@
(function redBoxButton() {
// Create a new div element
var newDiv = document.createElement("div");
// Set the id attribute of the new div
newDiv.id = "aspect-ratio-helper";
// Create a nested div inside the new div
var nestedDiv = document.createElement("div");
// Append the nested div to the new div
newDiv.appendChild(nestedDiv, newDiv.firstChild);
// Get the parent element where you want to append the new div
var parentElement = document.body; // Change this to your desired parent element
// Append the new div to the parent element
parentElement.insertBefore(newDiv, parentElement.firstChild);
// Create the button element
var hideShowButton = document.createElement("button");
hideShowButton.innerHTML = '<i class="fa fa-square-o"></i>';
hideShowButton.className = "icon-button";
hideShowButton.type = "button";
hideShowButton.title =
"Outline the area that fits on one screen while teaching the course.";
hideShowButton.id = "Dev";
var navbarButtons = document.getElementsByClassName("left-buttons");
navbarButtons[0].insertBefore(hideShowButton, navbarButtons.firstChild);
//Default hiding the redbox
document.getElementById("aspect-ratio-helper").style.display = "none";
//Add Event listener to button to perform on click action.
hideShowButton.addEventListener("click", function () {
if (
document.getElementById("aspect-ratio-helper").style.display === "none"
) {
document.getElementById("aspect-ratio-helper").style.display = "block";
hideShowButton.innerHTML = '<i class="fa fa-square"></i>';
} else {
document.getElementById("aspect-ratio-helper").style.display = "none";
hideShowButton.innerHTML = '<i class="fa fa-square-o"></i>';
}
});
(function handleInstructor(params) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this function needs params!

It probably makes sense to move this to yet another .js file, maybe instructor-menu?

For JS symbols that need to be reachable from other .js files, I think attaching them to window will work, even if it's a bit of a hack:

(function savePlaygrounds() {
  ...
  window.resetAllPlaygrounds = function() { .. }
})()
(function instructorMenu() {
    playgroundStateButton.addEventListener("click", () => {
      ...
      window.resetAllPlaygrounds();
    });
})()

function handleInstructorMenu() {
let leftButtons = document.getElementsByClassName("left-buttons")[0];
let instructorMenu = document.createElement("button");
let instructorMenuList = document.createElement("ul");
let redBoxItem = document.createElement("li");
let redBoxButton = document.createElement("button");
let playgroundStateItem = document.createElement("li");
let playgroundStateButton = document.createElement("button");

leftButtons.insertBefore(instructorMenu, leftButtons.lastChild);
leftButtons.insertBefore(instructorMenuList, leftButtons.lastChild);
instructorMenuList.insertBefore(redBoxItem, instructorMenuList.lastChild);
instructorMenuList.insertBefore(
playgroundStateItem,
instructorMenuList.lastChild
);
redBoxItem.insertBefore(redBoxButton, redBoxItem.lastChild);
playgroundStateItem.insertBefore(
playgroundStateButton,
playgroundStateItem.lastChild
);

instructorMenu.innerHTML =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
instructorMenu.innerHTML =
instructorMenu.title = "Utilities for course instructors";
instructorMenu.innerHTML =

'<i class="fa fa-ellipsis-v" aria-hidden="true"></i>';
redBoxButton.innerHTML = "redbox";
playgroundStateButton.innerHTML = "reset code";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's be more specific about what is reset, and also include a title:

Suggested change
redBoxButton.innerHTML = "redbox";
playgroundStateButton.innerHTML = "reset code";
redBoxButton.innerHTML = "aspect-ratio box";
redBoxButton.title = "Outline the area that fits on one screen while teaching the course.";
playgroundStateButton.innerHTML = "reset all playgrounds";
playgroundStateButton.title = "Reset code in all playgrounds to its original value.";


instructorMenu.className = "icon-button";
instructorMenuList.className = "theme-popup";
redBoxButton.className = "theme";
playgroundStateButton.className = "theme";
instructorMenuList.style.display = "none";

instructorMenuList.role = "menu";
redBoxItem.role = "none";
playgroundStateItem.role = "none";
redBoxButton.role = "menuitem";
playgroundStateButton.role = "menuitem";

redBoxButton.id = "redbox";

instructorMenuList.style.marginLeft = "55px";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor detail: I think this would be easier to read if each item was grouped together, and all its properties set in the same place.


instructorMenu.addEventListener("click", () => {
if (instructorMenuList.style.display === "none") {
instructorMenuList.style.display = "block";
} else {
instructorMenuList.style.display = "none";
}
});

playgroundStateButton.addEventListener("click", () => {
let keys = [];
for (var i = 0, len = localStorage.length; i < len; i++) {
if (localStorage.key(i).includes("₹code")) {
keys.push(localStorage.key(i));
}
}
for (let j = 0; j < keys.length; j++) {
localStorage.removeItem(keys[j]);
}
});
}

function redBoxButton() {
// Create a new div element
var newDiv = document.createElement("div");
// Set the id attribute of the new div
newDiv.id = "aspect-ratio-helper";
// Create a nested div inside the new div
var nestedDiv = document.createElement("div");
// Append the nested div to the new div
newDiv.appendChild(nestedDiv, newDiv.firstChild);
// Get the parent element where you want to append the new div
var parentElement = document.body; // Change this to your desired parent element
// Append the new div to the parent element
parentElement.insertBefore(newDiv, parentElement.firstChild);
// Create the button element
var hideShowButton = document.getElementById("redbox");
hideShowButton.title =
"Outline the area that fits on one screen while teaching the course.";
//Default hiding the redbox
document.getElementById("aspect-ratio-helper").style.display = "none";
//Add Event listener to button to perform on click action.
hideShowButton.addEventListener("click", function () {
if (
document.getElementById("aspect-ratio-helper").style.display === "none"
) {
document.getElementById("aspect-ratio-helper").style.display = "block";
hideShowButton.innerHTML = "redbox";
} else {
document.getElementById("aspect-ratio-helper").style.display = "none";
hideShowButton.innerHTML = "redbox";
}
});
}

handleInstructorMenu();
redBoxButton();
})();
33 changes: 33 additions & 0 deletions theme/save-playgrounds.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
(function savePlaygrounds() {
function setCodeToPlayground() {
var codes = JSON.parse(
localStorage.getItem(`${window.location.href}₹code`)
djmitche marked this conversation as resolved.
Show resolved Hide resolved
);
if (codes) {
var i = 0;
Array.from(document.querySelectorAll(".playground")).forEach(function (
pre_block
) {
let code_block = pre_block.querySelector("code");
let editor = window.ace.edit(code_block);
editor.setValue(codes[i]);
editor.clearSelection();
i += 1;
});
}
}
function getCodeFromPlayground() {
var codes = [];
Array.from(document.querySelectorAll(".playground")).forEach(function (
pre_block
) {
let code_block = pre_block.querySelector("code");
let editor = window.ace.edit(code_block);
let code = editor.getValue();
codes.push(code);
});
localStorage.setItem(`${window.location.href}₹code`, JSON.stringify(codes));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has it already been discussed what the character is doing here? It looks a bit strange to me 😄

Have you considered using just the pathname instead of the full URL? Since local storage is different for different hosts, I don't think we need the full URL here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, if the is necessary somehow, then I would suggest creating a new function to construct the key. You can then document the use there — and also call it from both places that need this key.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, if the is necessary somehow, then I would suggest creating a new function to construct the key. You can then document the use there — and also call it from both places that need this key.

Sorry, I didn't understand creating of "another function for key creating".

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @mani-chand, I'm suggesting creating a one-line function which returns the correct key for the current page. Something like

function localStorageKey() {
  // The '₹' here is used for ...
  return `${window.location.href}₹code`
}

You should then explain what does here 🙂

}
setCodeToPlayground();
addEventListener("pagehide", getCodeFromPlayground);
})();