Skip to main content

5 posts tagged with "web"

View All Tags

Path-finding Visualization With Just HTML, CSS & JavaScript

Β· 2 min read

Motivation​

Although I did go through a lot of tutorials and courses on the fundamentals of HTML, CSS & JavaScript when I started learning web development last year, my familiarity with the front end essentials is not at the level that I wish to be. I would like to think that with practice it will only get better. And what better to do than building projects that I think is cool.

I have always wanted to build a pathfinding visualizer that animates algorithms (I made a sorting visualizer some time ago). Recently, I have just started my Data structure & Algorithm class as a computer science student. So today, after watching this YouTube video on Dijkstra's algorithm, I decided to wait no longer and just start building a simple version of the pathfinding visualization.

Process​

In the process I was able to revisit the following concepts:

  1. CSS & HTML
  • CSS flexbox (for centering stuff)
  • CSS grid (to create the 10x10 grid)
  1. JavaScript
  • querySelector & querySelectorAll (for selecting DOM elements)
  • setTimeout (to create animation effect)
  • createElement, getAttribute, setAttribute, appendChild (for modifying the DOM)
  1. Algo
  • I wrote the code based on the video explanation of Dijkstra's algorithm, I am not 100% sure it is doing the right thing.

End Product​

After some polishing to make it look better (in fact it took me quite some time πŸ˜‚ to add in relevant CSS for this to be mobile friendly), you can see it in action on Codepen. Feel free to check out the codebase in my Github Repo. Screenshot

Further Improvements​

There are many things to be done for this. Just to name a few:

  • Allow users to pick start/end points.
  • Better visuals to convey the weight/difficulty between two nodes.
  • Add in more algorithms (DFS, BFS, etc). I might do a part two for this when I am done with some of the above.

If you like reading this, please give it a like so that more people can see it.πŸ˜„

Thinking in React Reference

Β· 5 min read

Thinking in React is an article from the official React Doc that talks about the development process for a typical React App

React is, in our opinion, the premier way to build big, fast Web apps with JavaScript. It has scaled very well for us at Facebook and Instagram.

I will be making a simple React App to illustrate the process.

Demo in codepen: A React App that reminds you of the steps in developing a React App...

Step 0: Start With A Mock​

The first thing to do is to have some sort of mental picture of how the App is going to look like. Preferably, have a sketch/mock of the UI.

This is what I came up with: A mock-up of the web app design

Secondly, imagine what data from an API/data source will look like. Given that I already have the steps involved in developing a React App and I have it in the following format:

const data = [
{
heading: "Start With A Mock",
content: "Any input from user. Front-end in its plain form",
},
{
heading: "Break The UI Into A Component Hierarchy",
content:
"Draw Boxes.Identify components(Single Responsibility Principle)
.Arrange into hierarchy",
},
{
heading: "Build A Static Version",
content:
"Don't use state at all, only use Props.Reuse components.
Top down/Bottom up to you.Pass your data model to
the top of the hierarchy",
},
{
heading: "Identify The Minimal Representation of UI State",
content:
"Keep only the absolute minimal and compute
everything else on-demand.Is it passed in from a parent via props?
If so, it probably isn't state.
Does it remain unchanged over time? If so, it probably isn’t state.
Can you compute it based on any other state or props in your component?
If so, it isn’t state",
},
{
heading: "Identify Where Your State Should Live",
content:
"Identify every component that renders something
based on that state.
Find a common owner component(above all other components).
Create a wrapper component above components if necessary",
},
{
heading: "Add Inverse Data Flow",
content:
"Pass state changing callbacks from state owner
to relevant child component",
},
];

Step 1: Break The UI Into A Component Hierarchy​

I started with identifying components from my UI.

  1. ReferenceTable: container
  2. StepNumberBar: reflect the current step number
  3. Explanation: displays the current step details
  4. KeyList: displays a list of bullet points
  5. NavigationRow: contains navigation buttons
  6. MoveStepButton: displays a button

Now that I identified the components in our mock, I arranged them into a hierarchy.

  • ReferenceTable
    • StepNumberBar
    • Explanation
      • KeyList
    • NavigationRow
      • MoveStepButton

Step 2: Build A Static Version in React​

Now I started building components top down. This process was a lot of debugging & frustration. Working with sample data helps. Also, focus on getting the skeleton out before you start polishing the components with CSS. But, do throw in some of the centering/alignment CSS along the way so that the App will start to take its shape. No state management at all at this stage.

Some of the basic functional components as follows:

function StepNumberBar({ total, current }) {
return (
<div className="stepNumberBar">
{Array(total)
.fill(null)
.map((value, index) => (
<span
id={index}
key={index}
className={current === index ? "active" : "inactive"}
>
{index}
</span>
))}
</div>
)
}

function KeyList({ content }) {
var itemsArr = content.split(".")
return (
<ul>
{itemsArr.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
)
}

function Explanation({ heading, content }) {
return (
<div className="explanation">
<h2>{heading}</h2>
<KeyList content={content} />
</div>
)
}
function NavigationRow() {
return (
<div className="buttons">
<MoveStepButton direction="prev" />
<MoveStepButton direction="next" />
</div>
)
}

function MoveStepButton({ direction }) {
return direction === "prev" ? <button>PREV</button> : <button>NEXT</button>
}

function ReferenceTable({ detail }) {
return (
<>
<StepNumberBar total={detail.length} current={currPage} />
<Explanation
heading={detail[currPage].heading}
content={detail[currPage].content}
/>
<NavigationRow />
</>
)
}

Step 3: Identify The Minimal (but complete) Representation Of UI State​

Now, thinking of all of the relevant data, I have:

  • The step number
  • The step detail

Going through the three questions for each piece of data:

  1. The step number changes when users navigate from one step to another. Hence it is probably state.
  2. The step detail is passed as props, does not change over time, so that's probably not state.

I ended up with only one state that I manipulated with the useState hook:

const [currPage, updatePage] = useState(0)

Step 4: Identify Where Your State Should Live​

Given that the step number needs to be displayed in StepNumberBar and also updated by the buttons in NavigationRow, the state needs to live in one component higher: ReferenceTable.

Step 5: Add Inverse Data Flow​

Since components should only update their own state, I passed the update function from ReferenceTable to MoveStepButton that will fire whenever the state should be updated. I used the onClick event to update the state. I also added some cool CSS effect that you can explore here.

Partial code as follows:

function ReferenceTable({ detail }) {
const [currPage, updatePage] = useState(0)
return (
<>
<StepNumberBar total={detail.length} current={currPage} />
<Explanation
heading={detail[currPage].heading}
content={detail[currPage].content}
/>
<NavigationRow updatePage={updatePage} />
</>
)
}
function NavigationRow({ updatePage }) {
return (
<div className="buttons">
<MoveStepButton updatePage={updatePage} direction="prev" />
<MoveStepButton updatePage={updatePage} direction="next" />
</div>
)
}

function MoveStepButton({ updatePage, direction }) {
return direction === "prev" ? (
<button onClick={() => updatePage(curr => (curr === 0 ? 5 : curr - 1))}>
PREV
</button>
) : (
<button onClick={() => updatePage(curr => (curr === 5 ? 0 : curr + 1))}>
NEXT
</button>
)
}

Done​

As always, more CSS + Polishing. Full code can be found at this repo.

Thank you for reading and have a nice day.