Skip to content

Instantly share code, notes, and snippets.

@musicq
Last active May 24, 2021 09:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save musicq/b3fd8ac65b5e8a50d3f6c065c5a8a9bb to your computer and use it in GitHub Desktop.
Save musicq/b3fd8ac65b5e8a50d3f6c065c5a8a9bb to your computer and use it in GitHub Desktop.
/**
* Given a DOM data structure in JSON
* write a function that can render JSON DOM
* onto an existing DOM node
* It is totally acceptable to google for javascript or dom
* manipulation related functions
*/
const vDom = {
name: "form",
tag: "form",
children: [
{
tag: "h2",
text: "My form",
name: "my-form"
},
{
tag: "label",
text: "First name: "
},
{
tag: "input",
type: "text",
name: "firstName"
},
{
tag: "label",
text: "Last name: "
},
{
tag: "input",
type: "text",
name: "lastName"
},
{
tag: "label",
text: "male",
children: [
{
tag: "input",
type: "radio",
name: "gender"
}
]
},
{
tag: "label",
text: "female",
children: [
{
tag: "input",
type: "radio",
name: "gender"
}
]
}
]
};
/**
* Answer------------------------------------------------
* function signature
* vDom and actual dom are always
* passed in pair
* @param vDom - Current vDom node
* @param element - Current Dom node
*/
const render = (vDom, element) => {
const dom = createElement(vDom);
element.appendChild(dom);
};
function createElement(vnode) {
const { tag, text, children, ...attrs } = vnode;
const el = document.createElement(tag);
if (text) {
el.appendChild(document.createTextNode(text));
}
for (const attr in attrs) {
el.setAttribute(attr, attrs[attr]);
}
if (children) {
for (const c of children) {
el.appendChild(createElement(c));
}
}
return el;
}
// convert data structure
let output = { name: "page", tag: "div", children: [1, 2] };
let cache = {};
function genKey() {
const seed = Math.random() * 1000;
let id = seed.toString(16).substr(4);
while (cache[id]) id = genKey();
return id;
}
function convertData(data, r) {
const { children, ...props } = data;
let node = {
id: genKey(),
...props
};
if (children) {
for (const c of children) {
let n = convertData(c, r);
node.children = [...(node.children || []), n.id];
}
}
r.push(node);
return node;
}
// let r = [];
// convertData(vDom, r);
// console.log(r);
/* EOF Answer------------------------------------------------ */
/**
* Hint!
* The whole program can start off with this call
* render(vDom, document.getElementById("main"));
*/
render(vDom, document.getElementById("main"));
/**
* Bonus Question
* Given a JSON structure
* of pagenation content
*/
const pages = {
page1: {
content: "hello",
next: "page2"
},
page2: {
content: "world",
next: "page3"
},
page3: {
content: "!!!!!",
next: "page4"
},
page4: {
content: "!!!!!",
next: "page5"
},
page5: {
content: "!!!!!"
}
};
/**
* Give this function
* for simulating async page load
* @param pageName - the page key in JSON structure
*/
const fetchPage = (pageName) =>
new Promise((resolve) => setTimeout(() => resolve(pages[pageName]), 1000));
/**
* Expect a promise return array of pages
* after all page load complete
*
* Execution:
* yourSolution.then(res=>console.log(res))
*
* Expected:
* [ {content: "hello", next: "page2"},
* {content: "world", next: "page3"},
* {content: "!!!!!"} ]
*/
const getPage = async (next) => {
const content = [];
const r = await fetchPage(next);
content.push(r);
if (r.next) content.push(...(await getPage(r.next)));
return content;
};
getPage("page1").then(console.log);
/* EOF Answer------------------------------------------------ */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment