diff --git a/1 - Blockcode/index.html b/1 - Blockcode/index.html
new file mode 100644
index 0000000..0a532ea
--- /dev/null
+++ b/1 - Blockcode/index.html
@@ -0,0 +1,46 @@
+
+
+
+
+ Ch 1. Blockcode
+
+
+
+
+
+
+
+
Menu
+
+
+
+
+ Script:
+ Clear
+ Save
+ Load
+ Run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/1 - Blockcode/resources/css/base.css b/1 - Blockcode/resources/css/base.css
new file mode 100644
index 0000000..2728d36
--- /dev/null
+++ b/1 - Blockcode/resources/css/base.css
@@ -0,0 +1,44 @@
+ul, li {
+ list-style: none;
+ margin: 0em;
+ padding: 0em;
+}
+
+div { padding: 0.5em; }
+
+#header { max-height: 4em; }
+#menu { background-color: #FFDAB9; height: -webkit-fill-available; }
+#script { background-color: #B0C4DE; height: -webkit-fill-available; }
+#menu > .script-block { background-color: #FF7F4F !important; }
+#script > .script-block,
+.script-nest > .script-block { background-color: #1E90FF !important; }
+#script .script-nest { background-color: #B0C4DE !important; }
+
+.flex-parent {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-evenly;
+ gap: 2em;
+}
+
+.flex-child {
+ min-height: 12em;
+ width: auto;
+}
+
+.script-block,
+.script-nest,
+.border {
+ border: 0.15em solid #000000;
+ border-radius: 0.6em;
+}
+
+.script-block,
+.script-nest {
+ display: block;
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+ padding: 0.5em;
+}
+
+.script-nest { background-color: #FFDAB9; }
diff --git a/1 - Blockcode/resources/js/elements.js b/1 - Blockcode/resources/js/elements.js
new file mode 100644
index 0000000..6819364
--- /dev/null
+++ b/1 - Blockcode/resources/js/elements.js
@@ -0,0 +1,168 @@
+class BaseScriptElement extends HTMLElement {
+ get prefix() { return 'BaseScriptElement'; }
+ constructor() { super(); }
+
+ connectedCallback() {
+ this.innerHTML = `
+
+ ${this.prefix}
+
+ `;
+ }
+
+ action(...args) { console.log("Hello, World!"); }
+}
+
+class BaseInputScriptElement extends BaseScriptElement {
+ get prefix() { return 'BaseInputScriptElement'; }
+ get defaultValue() { return '1'; }
+ get postfix() { return ''; }
+ get value() { return this.getElementsByClassName("script-input")[0].value; }
+ constructor() { super(); }
+
+ connectedCallback() {
+ this.innerHTML = `
+
+ ${this.prefix}
+
+ ${this.postfix}
+
+ `;
+ }
+
+ action() { console.log( this.value ); }
+}
+
+class RepeatElement extends BaseInputScriptElement {
+ get prefix() { return 'Repeat'; }
+ get defaultValue() { return '10'; }
+ get children() {
+ return this.getElementsByClassName("script-nest")[0].children;
+ }
+
+ connectedCallback() {
+ this.innerHTML = `
+
+ ${this.prefix}
+
+ ${this.postfix}
+
+
+ `;
+ }
+
+ action(Painter) {
+ for (let i = 0; i < this.value; i++) {
+ console.log(Painter.rotation)
+ for (const elm of this.children) {
+ elm.action(Painter);
+ }
+ }
+ }
+}
+
+class LeftElement extends BaseInputScriptElement {
+ get prefix() { return 'Left'; }
+ get defaultValue() { return '5'; }
+ get postfix() { return 'degrees'; }
+ constructor() { super(); }
+ action(Painter) { Painter.rotation -= this.value; }
+}
+
+class RightElement extends BaseInputScriptElement {
+ get prefix() { return 'Right'; }
+ get defaultValue() { return '5'; }
+ get postfix() { return 'degrees'; }
+ constructor() { super(); }
+ action(Painter) { Painter.rotation += this.value; }
+}
+
+class ForwardElement extends BaseInputScriptElement {
+ get prefix() { return 'Forward'; }
+ get defaultValue() { return '10'; }
+ get postfix() { return 'steps'; }
+ constructor() { super(); }
+ action(Painter) {
+ let magnitude = this.value
+ let radians = Painter.rotation * (Math.PI / 180);
+ const x2 = Painter.x1 + magnitude * Math.cos(radians);
+ const y2 = Painter.y1 + magnitude * Math.sin(radians);
+ Painter.x1 = x2
+ Painter.y1 = y2
+
+ if (Painter.isPenLifted) {
+ Painter.canvasContext.moveTo(x2, y2);
+ return;
+ }
+
+ Painter.canvasContext.lineTo(x2, y2);
+ Painter.canvasContext.stroke();
+ Painter.canvasContext.moveTo(x2, y2);
+ }
+}
+
+class BackElement extends BaseInputScriptElement {
+ get prefix() { return 'Back'; }
+ get defaultValue() { return '10'; }
+ get postfix() { return 'steps'; }
+ constructor() { super(); }
+ action(Painter) {
+ let magnitude = this.value
+ let radians = (Painter.rotation + 180) % 360;
+ const x2 = Painter.x1 + magnitude * Math.cos(radians);
+ const y2 = Painter.y1 + magnitude * Math.sin(radians);
+ Painter.x1 = x2
+ Painter.y1 = y2
+
+ if (Painter.isPenLifted) {
+ Painter.canvasContext.moveTo(x2, y2);
+ return;
+ }
+
+ Painter.canvasContext.lineTo(x2, y2);
+ Painter.canvasContext.stroke();
+ Painter.canvasContext.moveTo(x2, y2);
+ }
+}
+
+class CircleElement extends BaseInputScriptElement {
+ get prefix() { return 'Circle'; }
+ get defaultValue() { return '20'; }
+ get postfix() { return 'radius'; }
+ constructor() { super(); }
+ action(Painter) {
+ Painter.canvasContext.beginPath();
+ Painter.canvasContext.arc(95, 50, 40, 0, 2 * Math.PI);
+ Painter.canvasContext.stroke();
+ }
+}
+
+class PenUpElement extends BaseScriptElement {
+ get prefix() { return 'Pen Up'; }
+ constructor() { super(); }
+ action(Painter) { Painter.isPenLifted = true; }
+}
+
+class PenDownElement extends BaseScriptElement {
+ get prefix() { return 'Pen Down'; }
+ constructor() { super(); }
+ action(Painter) { Painter.isPenLifted = false; }
+}
+
+class BackToCenterElement extends BaseScriptElement {
+ get prefix() { return 'Back to Center'; }
+ constructor() { super(); }
+ action(Painter) {
+ Painter.x1 = Painter.canvas.width / 2
+ Painter.y1 = Painter.canvas.height / 2
+ Painter.canvasContext.moveTo( Painter.x1, Painter.y1 );
+ }
+}
+
+class HideTurtleElement extends BaseScriptElement {
+ get prefix() { return 'Hide Turtle'; }
+ constructor() { super(); }
+}
diff --git a/1 - Blockcode/resources/js/events.js b/1 - Blockcode/resources/js/events.js
new file mode 100644
index 0000000..8faecdf
--- /dev/null
+++ b/1 - Blockcode/resources/js/events.js
@@ -0,0 +1,24 @@
+window.onload = (eve) => {
+ setupMenuBlocks();
+ setupDragAndDrop();
+ setupScriptRunner();
+}
+
+clearBttn.onclick = (eve) => {
+ console.log("Clear");
+}
+
+saveBttn.onclick = (eve) => {
+ console.log("Save");
+}
+
+loadBttn.onclick = (eve) => {
+ console.log("Load");
+}
+
+runBttn.onclick = (eve) => {
+ console.log("Run");
+ runScript();
+}
+
+
diff --git a/1 - Blockcode/resources/js/globals.js b/1 - Blockcode/resources/js/globals.js
new file mode 100644
index 0000000..311114d
--- /dev/null
+++ b/1 - Blockcode/resources/js/globals.js
@@ -0,0 +1,24 @@
+const ScriptElms = {
+ "repeat-element": RepeatElement,
+ "left-element": LeftElement,
+ "right-element": RightElement,
+ "forward-element": ForwardElement,
+ "back-element": BackElement,
+ "circle-element": CircleElement,
+ "pen-up-element": PenUpElement,
+ "pen-down-element": PenDownElement,
+ "back-to-center-element": BackToCenterElement,
+ "hider-turtle-element": HideTurtleElement
+};
+
+let Painter = {
+ canvas: null,
+ canvasContext: null,
+ rotation: 0,
+ x1: 0,
+ y1: 0,
+ isPenLifted: false
+}
+
+let draggedElm = null;
+
diff --git a/1 - Blockcode/resources/js/script-runner.js b/1 - Blockcode/resources/js/script-runner.js
new file mode 100644
index 0000000..b631f1e
--- /dev/null
+++ b/1 - Blockcode/resources/js/script-runner.js
@@ -0,0 +1,29 @@
+const setupScriptRunner = () => {
+ canvasContext = canvas.getContext("2d");
+ Painter.canvas = canvas;
+ Painter.canvasContext = canvasContext;
+}
+
+const runScript = () => {
+ setToCenter();
+ resetRotation();
+ clearCanvas();
+
+ for (const elm of script.children) {
+ elm.action(Painter);
+ }
+}
+
+const setToCenter = () => {
+ Painter.x1 = Painter.canvas.width / 2
+ Painter.y1 = Painter.canvas.height / 2
+ Painter.canvasContext.moveTo( Painter.x1, Painter.y1 );
+}
+
+const clearCanvas = () => {
+ Painter.canvasContext.clearRect(0, 0, canvas.width, canvas.height);
+}
+
+const resetRotation = () => {
+ Painter.rotation = 0;
+}
diff --git a/1 - Blockcode/resources/js/ui.js b/1 - Blockcode/resources/js/ui.js
new file mode 100644
index 0000000..aa860be
--- /dev/null
+++ b/1 - Blockcode/resources/js/ui.js
@@ -0,0 +1,61 @@
+const setupMenuBlocks = () => {
+ for (const [key, value] of Object.entries(ScriptElms)) {
+ customElements.define(key, value);
+ const elm = document.createElement(key);
+ elm.className = "script-block";
+ elm.draggable = true
+ elm.ondragstart = dragStartHandler
+ menu.append(elm);
+ }
+}
+
+const setupDragAndDrop = () => {
+ script.ondrop = dragDropHandler
+ script.ondragover = dragOverHandler
+ header.ondrop = dragDropHandler
+ header.ondragover = dragOverHandler
+
+ const flexParents = document.getElementsByClassName("flex-parent");
+ for (let i = 0; i < flexParents.length; i++) {
+ flexParents[i].ondrop = dragDropHandler
+ flexParents[i].ondragover = dragOverHandler
+ }
+}
+
+const dragStartHandler = (eve) => {
+ draggedElm = eve.target;
+ console.debug("Node: ", draggedElm);
+ eve.dataTransfer.setData("text", eve.target.tagName.toLowerCase());
+}
+
+const dragOverHandler = (eve) => { eve.preventDefault(); }
+
+const dragDropHandler = (eve) => {
+ eve.preventDefault();
+ eve.stopPropagation();
+
+ const tagTarget = eve.currentTarget;
+
+ if (
+ eve.currentTarget.id.toLowerCase() === "header" ||
+ eve.currentTarget.classList.contains("flex-parent")
+ ) {
+ if ( draggedElm.parentNode.id.toLowerCase() !== "menu" ) {
+ destroyScriptBlock(draggedElm, tagTarget);
+ }
+
+ return;
+ }
+
+ addBlockToScript(draggedElm, tagTarget);
+}
+
+const addBlockToScript = (draggedTarget, tagTarget) => {
+ const elm = draggedTarget.cloneNode(true);
+ elm.ondragstart = dragStartHandler
+ tagTarget.appendChild(elm);
+}
+
+const destroyScriptBlock = (draggedTarget, tagTarget) => {
+ draggedTarget.remove();
+}
diff --git a/Independent/pixilate/pixilate.html b/Independent/pixilate/pixilate.html
new file mode 100644
index 0000000..a3e4732
--- /dev/null
+++ b/Independent/pixilate/pixilate.html
@@ -0,0 +1,507 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ H-Mirror
+ V-Mirror
+ Bucket
+ Erase
+ Save
+
+
+
+
+
+
+
+
+
+
+
+
+
Color Palette
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Independent/pixilate/pixilate_image.png b/Independent/pixilate/pixilate_image.png
new file mode 100644
index 0000000..8c1bcbb
Binary files /dev/null and b/Independent/pixilate/pixilate_image.png differ
diff --git a/README.md b/README.md
index a1e6432..8229303 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,7 @@
# 500-Lines-or-Less
+[500 Lines or Less](https://aosabook.org/en/500L/introduction.html)
+> 500 Lines or Less focuses on the design decisions that programmers make in the small when they are building something new.
+
+# Notes
+This repo constitutes my efforts to try to implement the respective chapter topic before reading how that chapter author achieved theirs.