From 5d7c2b26bede733fbf466101ac85f3ebbd819f77 Mon Sep 17 00:00:00 2001 From: Khushi Patel Date: Mon, 13 Mar 2023 18:53:01 +0530 Subject: [PATCH 1/6] [ADD] JS-workshop: Guess number, Fetch API Data --- Api_Activity.html | 83 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 Api_Activity.html diff --git a/Api_Activity.html b/Api_Activity.html new file mode 100644 index 0000000..9e9f129 --- /dev/null +++ b/Api_Activity.html @@ -0,0 +1,83 @@ + + + + Display API Data + + + + +
+
+ Loading... +
+
+

Registered Products

+ +
+ + \ No newline at end of file From 53cb6abafa2721237d3c77340c371ae6add3ce9b Mon Sep 17 00:00:00 2001 From: Khushi Patel Date: Mon, 13 Mar 2023 19:18:32 +0530 Subject: [PATCH 2/6] [ADD] JS-workshop: Guess number --- Activity.html | 12 ++++++++++++ Activity.js | 31 +++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 Activity.html create mode 100644 Activity.js diff --git a/Activity.html b/Activity.html new file mode 100644 index 0000000..d518c48 --- /dev/null +++ b/Activity.html @@ -0,0 +1,12 @@ + + + JS Activity + + + + +

+
+ + + \ No newline at end of file diff --git a/Activity.js b/Activity.js new file mode 100644 index 0000000..f4d6251 --- /dev/null +++ b/Activity.js @@ -0,0 +1,31 @@ +btn = document.getElementById("check"); +input = document.getElementById("data"); +output = document.getElementById("result"); +trials = document.getElementById("trials"); + +let count = 5; +const comp = Math.floor(Math.random()*10)+1; +console.log(comp); + +btn.addEventListener('click', () => { + trials.innerHTML = "No. of trials remaining : " + (count-1); + + if(comp == input.value){ + output.innerHTML = "CORRECT!"; + trials.innerHTML = ''; + } + else if(comp > input.value){ + output.innerHTML = "LOW"; + count--; + } + else{ + output.innerHTML = "HIGH"; + count--; + } + + input.value = ''; + if(count<1){ + btn.style.display = 'none'; + trials.innerHTML += "

Correct answer was : " + comp; + } +}) \ No newline at end of file From e0328726c8e3cf0ccc04c5813a932394e397c00c Mon Sep 17 00:00:00 2001 From: Khushi Patel Date: Tue, 14 Mar 2023 16:04:24 +0530 Subject: [PATCH 3/6] Update --- js-day-1/Activity.html | 12 ++++++ js-day-1/Activity.js | 31 +++++++++++++++ js-day-1/Api_Activity.html | 78 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 js-day-1/Activity.html create mode 100644 js-day-1/Activity.js create mode 100644 js-day-1/Api_Activity.html diff --git a/js-day-1/Activity.html b/js-day-1/Activity.html new file mode 100644 index 0000000..d518c48 --- /dev/null +++ b/js-day-1/Activity.html @@ -0,0 +1,12 @@ + + + JS Activity + + + + +

+
+ + + \ No newline at end of file diff --git a/js-day-1/Activity.js b/js-day-1/Activity.js new file mode 100644 index 0000000..f4d6251 --- /dev/null +++ b/js-day-1/Activity.js @@ -0,0 +1,31 @@ +btn = document.getElementById("check"); +input = document.getElementById("data"); +output = document.getElementById("result"); +trials = document.getElementById("trials"); + +let count = 5; +const comp = Math.floor(Math.random()*10)+1; +console.log(comp); + +btn.addEventListener('click', () => { + trials.innerHTML = "No. of trials remaining : " + (count-1); + + if(comp == input.value){ + output.innerHTML = "CORRECT!"; + trials.innerHTML = ''; + } + else if(comp > input.value){ + output.innerHTML = "LOW"; + count--; + } + else{ + output.innerHTML = "HIGH"; + count--; + } + + input.value = ''; + if(count<1){ + btn.style.display = 'none'; + trials.innerHTML += "

Correct answer was : " + comp; + } +}) \ No newline at end of file diff --git a/js-day-1/Api_Activity.html b/js-day-1/Api_Activity.html new file mode 100644 index 0000000..6489a8c --- /dev/null +++ b/js-day-1/Api_Activity.html @@ -0,0 +1,78 @@ + + + + Display API Data + + + + +
+
+ Loading... +
+
+

Registered Products

+ +
+ + \ No newline at end of file From 9fe11fc7d74461d1ec1a25fbd8435111e482aa2a Mon Sep 17 00:00:00 2001 From: Khushi Patel Date: Tue, 14 Mar 2023 16:07:18 +0530 Subject: [PATCH 4/6] [ADD]OWL Lifecycle,useState,useEnv,day1 task using OWL --- Activity.html | 12 - Activity.js | 31 - Api_Activity.html | 83 - js-day-2/day2.html | 6 + js-day-2/day2.js | 66 + js-day-2/guess_game.html | 6 + js-day-2/guess_game.js | 102 + js-day-2/owl.js | 5938 ++++++++++++++++++++++++++++++++++++++ 8 files changed, 6118 insertions(+), 126 deletions(-) delete mode 100644 Activity.html delete mode 100644 Activity.js delete mode 100644 Api_Activity.html create mode 100644 js-day-2/day2.html create mode 100644 js-day-2/day2.js create mode 100644 js-day-2/guess_game.html create mode 100644 js-day-2/guess_game.js create mode 100644 js-day-2/owl.js diff --git a/Activity.html b/Activity.html deleted file mode 100644 index d518c48..0000000 --- a/Activity.html +++ /dev/null @@ -1,12 +0,0 @@ - - - JS Activity - - - - -

-
- - - \ No newline at end of file diff --git a/Activity.js b/Activity.js deleted file mode 100644 index f4d6251..0000000 --- a/Activity.js +++ /dev/null @@ -1,31 +0,0 @@ -btn = document.getElementById("check"); -input = document.getElementById("data"); -output = document.getElementById("result"); -trials = document.getElementById("trials"); - -let count = 5; -const comp = Math.floor(Math.random()*10)+1; -console.log(comp); - -btn.addEventListener('click', () => { - trials.innerHTML = "No. of trials remaining : " + (count-1); - - if(comp == input.value){ - output.innerHTML = "CORRECT!"; - trials.innerHTML = ''; - } - else if(comp > input.value){ - output.innerHTML = "LOW"; - count--; - } - else{ - output.innerHTML = "HIGH"; - count--; - } - - input.value = ''; - if(count<1){ - btn.style.display = 'none'; - trials.innerHTML += "

Correct answer was : " + comp; - } -}) \ No newline at end of file diff --git a/Api_Activity.html b/Api_Activity.html deleted file mode 100644 index 9e9f129..0000000 --- a/Api_Activity.html +++ /dev/null @@ -1,83 +0,0 @@ - - - - Display API Data - - - - -
-
- Loading... -
-
-

Registered Products

- -
- - \ No newline at end of file diff --git a/js-day-2/day2.html b/js-day-2/day2.html new file mode 100644 index 0000000..380ed64 --- /dev/null +++ b/js-day-2/day2.html @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/js-day-2/day2.js b/js-day-2/day2.js new file mode 100644 index 0000000..97f13d5 --- /dev/null +++ b/js-day-2/day2.js @@ -0,0 +1,66 @@ +const {Component , mount , xml , useState, reactive, useEnv, onWillRender , onWillStart , onMounted , onWillPatch , onPatched , onRendered , onWillUnmount , onWillDestroy , onError} = owl; + +const finalData = () => { + const apple = useEnv(); + return useState(apple.store); +} + +class Datalist{ + count = 0; + updateCount(){this.count++;} + getCount(){return this.count;} +} + +class Second extends Component { + static template = xml` + Second + + + + `; + + static props = ["fruit","drink"]; + + setup(){ + this.bottle = finalData(); + } +} + +class Root extends Component { + static template = xml` + Hello
+
+ + `; + + abc = "apple"; + static components = { Second }; + + setup(){ + onWillStart(() => console.log("onWillStart Called...")); + onWillRender(() => console.log("onWillRender Called...")); + onMounted(() => console.log("onMounted Called...")); + onRendered(() => console.log("onRendered Called...")); + onWillPatch(() => console.log("onWillPatch Called...")); + onPatched(() => console.log("onPatched Called...")); + // onWillUnmount(() => console.log("onWillUnmount Called...")); + // onWillDestroy(() => console.log("onWillDestroy Called...")); + // onError(() => console.log("onError Called...")); + + this.cafe = useState({tea: 3,coffee: 4}); + this.cap = finalData(); + } + + clickMe(){ + this.cap.updateCount(); + console.log("Button is clicked!"); + } +} + +const createData = () => { + return reactive(new Datalist); +} + +const env = {store : createData()}; + +mount(Root,document.body,{dev: true,env}); \ No newline at end of file diff --git a/js-day-2/guess_game.html b/js-day-2/guess_game.html new file mode 100644 index 0000000..2c33f32 --- /dev/null +++ b/js-day-2/guess_game.html @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/js-day-2/guess_game.js b/js-day-2/guess_game.js new file mode 100644 index 0000000..2a43f26 --- /dev/null +++ b/js-day-2/guess_game.js @@ -0,0 +1,102 @@ +const {Component , mount , xml , useState, useEnv, reactive} = owl; + +const comp = Math.floor(Math.random()*10)+1; +let count = 2; + +const finalData = () => { + const guess = useEnv(); + return useState(guess.store); +} + +class Input extends Component { + static template = xml` + + `; + + getInput(){ + let input = document.getElementById("data"); + return input; + } +} + +class Root extends Component { + static template = xml` + +

+ +

+
+ `; + + static components = { Input }; + + setup(){ + this.user = finalData(); + } + + check(){ + console.log(comp); + const display = document.getElementById("display"); + let userData = this.user.getInput(); + + if(comp == userData.value){ + display.innerHTML = "Correct"; + } + else if(comp > userData.value){ + display.innerHTML = "Low"; + count--; + } + else{ + display.innerHTML = "High"; + count--; + } + + display.innerHTML += "

No. of trials remaining : " + (count); + userData.value = ''; + + if(count<1) { + display.innerHTML += "

Correct answer was : " + (comp); + document.getElementById("btn").style.display='none'; + } + } +} + +const createData = () => { + return reactive(new Input); +} + +const env = {store : createData()}; + +mount(Root,document.body,{dev: true,env}); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/js-day-2/owl.js b/js-day-2/owl.js new file mode 100644 index 0000000..b07d8c8 --- /dev/null +++ b/js-day-2/owl.js @@ -0,0 +1,5938 @@ +(function (exports) { + 'use strict'; + + function filterOutModifiersFromData(dataList) { + dataList = dataList.slice(); + const modifiers = []; + let elm; + while ((elm = dataList[0]) && typeof elm === "string") { + modifiers.push(dataList.shift()); + } + return { modifiers, data: dataList }; + } + const config = { + // whether or not blockdom should normalize DOM whenever a block is created. + // Normalizing dom mean removing empty text nodes (or containing only spaces) + shouldNormalizeDom: true, + // this is the main event handler. Every event handler registered with blockdom + // will go through this function, giving it the data registered in the block + // and the event + mainEventHandler: (data, ev, currentTarget) => { + if (typeof data === "function") { + data(ev); + } + else if (Array.isArray(data)) { + data = filterOutModifiersFromData(data).data; + data[0](data[1], ev); + } + return false; + }, + }; + + // ----------------------------------------------------------------------------- + // Toggler node + // ----------------------------------------------------------------------------- + class VToggler { + constructor(key, child) { + this.key = key; + this.child = child; + } + mount(parent, afterNode) { + this.parentEl = parent; + this.child.mount(parent, afterNode); + } + moveBeforeDOMNode(node, parent) { + this.child.moveBeforeDOMNode(node, parent); + } + moveBeforeVNode(other, afterNode) { + this.moveBeforeDOMNode((other && other.firstNode()) || afterNode); + } + patch(other, withBeforeRemove) { + if (this === other) { + return; + } + let child1 = this.child; + let child2 = other.child; + if (this.key === other.key) { + child1.patch(child2, withBeforeRemove); + } + else { + child2.mount(this.parentEl, child1.firstNode()); + if (withBeforeRemove) { + child1.beforeRemove(); + } + child1.remove(); + this.child = child2; + this.key = other.key; + } + } + beforeRemove() { + this.child.beforeRemove(); + } + remove() { + this.child.remove(); + } + firstNode() { + return this.child.firstNode(); + } + toString() { + return this.child.toString(); + } + } + function toggler(key, child) { + return new VToggler(key, child); + } + + // Custom error class that wraps error that happen in the owl lifecycle + class OwlError extends Error { + } + // Maps fibers to thrown errors + const fibersInError = new WeakMap(); + const nodeErrorHandlers = new WeakMap(); + function _handleError(node, error) { + if (!node) { + return false; + } + const fiber = node.fiber; + if (fiber) { + fibersInError.set(fiber, error); + } + const errorHandlers = nodeErrorHandlers.get(node); + if (errorHandlers) { + let handled = false; + // execute in the opposite order + for (let i = errorHandlers.length - 1; i >= 0; i--) { + try { + errorHandlers[i](error); + handled = true; + break; + } + catch (e) { + error = e; + } + } + if (handled) { + return true; + } + } + return _handleError(node.parent, error); + } + function handleError(params) { + let { error } = params; + // Wrap error if it wasn't wrapped by wrapError (ie when not in dev mode) + if (!(error instanceof OwlError)) { + error = Object.assign(new OwlError(`An error occured in the owl lifecycle (see this Error's "cause" property)`), { cause: error }); + } + const node = "node" in params ? params.node : params.fiber.node; + const fiber = "fiber" in params ? params.fiber : node.fiber; + // resets the fibers on components if possible. This is important so that + // new renderings can be properly included in the initial one, if any. + let current = fiber; + do { + current.node.fiber = current; + current = current.parent; + } while (current); + fibersInError.set(fiber.root, error); + const handled = _handleError(node, error); + if (!handled) { + console.warn(`[Owl] Unhandled error. Destroying the root component`); + try { + node.app.destroy(); + } + catch (e) { + console.error(e); + } + throw error; + } + } + + const { setAttribute: elemSetAttribute, removeAttribute } = Element.prototype; + const tokenList = DOMTokenList.prototype; + const tokenListAdd = tokenList.add; + const tokenListRemove = tokenList.remove; + const isArray = Array.isArray; + const { split, trim } = String.prototype; + const wordRegexp = /\s+/; + /** + * We regroup here all code related to updating attributes in a very loose sense: + * attributes, properties and classs are all managed by the functions in this + * file. + */ + function setAttribute(key, value) { + switch (value) { + case false: + case undefined: + removeAttribute.call(this, key); + break; + case true: + elemSetAttribute.call(this, key, ""); + break; + default: + elemSetAttribute.call(this, key, value); + } + } + function createAttrUpdater(attr) { + return function (value) { + setAttribute.call(this, attr, value); + }; + } + function attrsSetter(attrs) { + if (isArray(attrs)) { + setAttribute.call(this, attrs[0], attrs[1]); + } + else { + for (let k in attrs) { + setAttribute.call(this, k, attrs[k]); + } + } + } + function attrsUpdater(attrs, oldAttrs) { + if (isArray(attrs)) { + const name = attrs[0]; + const val = attrs[1]; + if (name === oldAttrs[0]) { + if (val === oldAttrs[1]) { + return; + } + setAttribute.call(this, name, val); + } + else { + removeAttribute.call(this, oldAttrs[0]); + setAttribute.call(this, name, val); + } + } + else { + for (let k in oldAttrs) { + if (!(k in attrs)) { + removeAttribute.call(this, k); + } + } + for (let k in attrs) { + const val = attrs[k]; + if (val !== oldAttrs[k]) { + setAttribute.call(this, k, val); + } + } + } + } + function toClassObj(expr) { + const result = {}; + switch (typeof expr) { + case "string": + // we transform here a list of classes into an object: + // 'hey you' becomes {hey: true, you: true} + const str = trim.call(expr); + if (!str) { + return {}; + } + let words = split.call(str, wordRegexp); + for (let i = 0, l = words.length; i < l; i++) { + result[words[i]] = true; + } + return result; + case "object": + // this is already an object but we may need to split keys: + // {'a': true, 'b c': true} should become {a: true, b: true, c: true} + for (let key in expr) { + const value = expr[key]; + if (value) { + key = trim.call(key); + if (!key) { + continue; + } + const words = split.call(key, wordRegexp); + for (let word of words) { + result[word] = value; + } + } + } + return result; + case "undefined": + return {}; + case "number": + return { [expr]: true }; + default: + return { [expr]: true }; + } + } + function setClass(val) { + val = val === "" ? {} : toClassObj(val); + // add classes + const cl = this.classList; + for (let c in val) { + tokenListAdd.call(cl, c); + } + } + function updateClass(val, oldVal) { + oldVal = oldVal === "" ? {} : toClassObj(oldVal); + val = val === "" ? {} : toClassObj(val); + const cl = this.classList; + // remove classes + for (let c in oldVal) { + if (!(c in val)) { + tokenListRemove.call(cl, c); + } + } + // add classes + for (let c in val) { + if (!(c in oldVal)) { + tokenListAdd.call(cl, c); + } + } + } + + function createEventHandler(rawEvent) { + const eventName = rawEvent.split(".")[0]; + const capture = rawEvent.includes(".capture"); + if (rawEvent.includes(".synthetic")) { + return createSyntheticHandler(eventName, capture); + } + else { + return createElementHandler(eventName, capture); + } + } + // Native listener + let nextNativeEventId = 1; + function createElementHandler(evName, capture = false) { + let eventKey = `__event__${evName}_${nextNativeEventId++}`; + if (capture) { + eventKey = `${eventKey}_capture`; + } + function listener(ev) { + const currentTarget = ev.currentTarget; + if (!currentTarget || !currentTarget.ownerDocument.contains(currentTarget)) + return; + const data = currentTarget[eventKey]; + if (!data) + return; + config.mainEventHandler(data, ev, currentTarget); + } + function setup(data) { + this[eventKey] = data; + this.addEventListener(evName, listener, { capture }); + } + function remove() { + delete this[eventKey]; + this.removeEventListener(evName, listener, { capture }); + } + function update(data) { + this[eventKey] = data; + } + return { setup, update, remove }; + } + // Synthetic handler: a form of event delegation that allows placing only one + // listener per event type. + let nextSyntheticEventId = 1; + function createSyntheticHandler(evName, capture = false) { + let eventKey = `__event__synthetic_${evName}`; + if (capture) { + eventKey = `${eventKey}_capture`; + } + setupSyntheticEvent(evName, eventKey, capture); + const currentId = nextSyntheticEventId++; + function setup(data) { + const _data = this[eventKey] || {}; + _data[currentId] = data; + this[eventKey] = _data; + } + function remove() { + delete this[eventKey]; + } + return { setup, update: setup, remove }; + } + function nativeToSyntheticEvent(eventKey, event) { + let dom = event.target; + while (dom !== null) { + const _data = dom[eventKey]; + if (_data) { + for (const data of Object.values(_data)) { + const stopped = config.mainEventHandler(data, event, dom); + if (stopped) + return; + } + } + dom = dom.parentNode; + } + } + const CONFIGURED_SYNTHETIC_EVENTS = {}; + function setupSyntheticEvent(evName, eventKey, capture = false) { + if (CONFIGURED_SYNTHETIC_EVENTS[eventKey]) { + return; + } + document.addEventListener(evName, (event) => nativeToSyntheticEvent(eventKey, event), { + capture, + }); + CONFIGURED_SYNTHETIC_EVENTS[eventKey] = true; + } + + const getDescriptor$3 = (o, p) => Object.getOwnPropertyDescriptor(o, p); + const nodeProto$4 = Node.prototype; + const nodeInsertBefore$3 = nodeProto$4.insertBefore; + const nodeSetTextContent$1 = getDescriptor$3(nodeProto$4, "textContent").set; + const nodeRemoveChild$3 = nodeProto$4.removeChild; + // ----------------------------------------------------------------------------- + // Multi NODE + // ----------------------------------------------------------------------------- + class VMulti { + constructor(children) { + this.children = children; + } + mount(parent, afterNode) { + const children = this.children; + const l = children.length; + const anchors = new Array(l); + for (let i = 0; i < l; i++) { + let child = children[i]; + if (child) { + child.mount(parent, afterNode); + } + else { + const childAnchor = document.createTextNode(""); + anchors[i] = childAnchor; + nodeInsertBefore$3.call(parent, childAnchor, afterNode); + } + } + this.anchors = anchors; + this.parentEl = parent; + } + moveBeforeDOMNode(node, parent = this.parentEl) { + this.parentEl = parent; + const children = this.children; + const anchors = this.anchors; + for (let i = 0, l = children.length; i < l; i++) { + let child = children[i]; + if (child) { + child.moveBeforeDOMNode(node, parent); + } + else { + const anchor = anchors[i]; + nodeInsertBefore$3.call(parent, anchor, node); + } + } + } + moveBeforeVNode(other, afterNode) { + if (other) { + const next = other.children[0]; + afterNode = (next ? next.firstNode() : other.anchors[0]) || null; + } + const children = this.children; + const parent = this.parentEl; + const anchors = this.anchors; + for (let i = 0, l = children.length; i < l; i++) { + let child = children[i]; + if (child) { + child.moveBeforeVNode(null, afterNode); + } + else { + const anchor = anchors[i]; + nodeInsertBefore$3.call(parent, anchor, afterNode); + } + } + } + patch(other, withBeforeRemove) { + if (this === other) { + return; + } + const children1 = this.children; + const children2 = other.children; + const anchors = this.anchors; + const parentEl = this.parentEl; + for (let i = 0, l = children1.length; i < l; i++) { + const vn1 = children1[i]; + const vn2 = children2[i]; + if (vn1) { + if (vn2) { + vn1.patch(vn2, withBeforeRemove); + } + else { + const afterNode = vn1.firstNode(); + const anchor = document.createTextNode(""); + anchors[i] = anchor; + nodeInsertBefore$3.call(parentEl, anchor, afterNode); + if (withBeforeRemove) { + vn1.beforeRemove(); + } + vn1.remove(); + children1[i] = undefined; + } + } + else if (vn2) { + children1[i] = vn2; + const anchor = anchors[i]; + vn2.mount(parentEl, anchor); + nodeRemoveChild$3.call(parentEl, anchor); + } + } + } + beforeRemove() { + const children = this.children; + for (let i = 0, l = children.length; i < l; i++) { + const child = children[i]; + if (child) { + child.beforeRemove(); + } + } + } + remove() { + const parentEl = this.parentEl; + if (this.isOnlyChild) { + nodeSetTextContent$1.call(parentEl, ""); + } + else { + const children = this.children; + const anchors = this.anchors; + for (let i = 0, l = children.length; i < l; i++) { + const child = children[i]; + if (child) { + child.remove(); + } + else { + nodeRemoveChild$3.call(parentEl, anchors[i]); + } + } + } + } + firstNode() { + const child = this.children[0]; + return child ? child.firstNode() : this.anchors[0]; + } + toString() { + return this.children.map((c) => (c ? c.toString() : "")).join(""); + } + } + function multi(children) { + return new VMulti(children); + } + + const getDescriptor$2 = (o, p) => Object.getOwnPropertyDescriptor(o, p); + const nodeProto$3 = Node.prototype; + const characterDataProto$1 = CharacterData.prototype; + const nodeInsertBefore$2 = nodeProto$3.insertBefore; + const characterDataSetData$1 = getDescriptor$2(characterDataProto$1, "data").set; + const nodeRemoveChild$2 = nodeProto$3.removeChild; + class VSimpleNode { + constructor(text) { + this.text = text; + } + mountNode(node, parent, afterNode) { + this.parentEl = parent; + nodeInsertBefore$2.call(parent, node, afterNode); + this.el = node; + } + moveBeforeDOMNode(node, parent = this.parentEl) { + this.parentEl = parent; + nodeInsertBefore$2.call(parent, this.el, node); + } + moveBeforeVNode(other, afterNode) { + nodeInsertBefore$2.call(this.parentEl, this.el, other ? other.el : afterNode); + } + beforeRemove() { } + remove() { + nodeRemoveChild$2.call(this.parentEl, this.el); + } + firstNode() { + return this.el; + } + toString() { + return this.text; + } + } + class VText$1 extends VSimpleNode { + mount(parent, afterNode) { + this.mountNode(document.createTextNode(toText(this.text)), parent, afterNode); + } + patch(other) { + const text2 = other.text; + if (this.text !== text2) { + characterDataSetData$1.call(this.el, toText(text2)); + this.text = text2; + } + } + } + class VComment extends VSimpleNode { + mount(parent, afterNode) { + this.mountNode(document.createComment(toText(this.text)), parent, afterNode); + } + patch() { } + } + function text(str) { + return new VText$1(str); + } + function comment(str) { + return new VComment(str); + } + function toText(value) { + switch (typeof value) { + case "string": + return value; + case "number": + return String(value); + case "boolean": + return value ? "true" : "false"; + default: + return value || ""; + } + } + + const getDescriptor$1 = (o, p) => Object.getOwnPropertyDescriptor(o, p); + const nodeProto$2 = Node.prototype; + const elementProto = Element.prototype; + const characterDataProto = CharacterData.prototype; + const characterDataSetData = getDescriptor$1(characterDataProto, "data").set; + const nodeGetFirstChild = getDescriptor$1(nodeProto$2, "firstChild").get; + const nodeGetNextSibling = getDescriptor$1(nodeProto$2, "nextSibling").get; + const NO_OP = () => { }; + function makePropSetter(name) { + return function setProp(value) { + // support 0, fallback to empty string for other falsy values + this[name] = value === 0 ? 0 : value ? value.valueOf() : ""; + }; + } + const cache$1 = {}; + /** + * Compiling blocks is a multi-step process: + * + * 1. build an IntermediateTree from the HTML element. This intermediate tree + * is a binary tree structure that encode dynamic info sub nodes, and the + * path required to reach them + * 2. process the tree to build a block context, which is an object that aggregate + * all dynamic info in a list, and also, all ref indexes. + * 3. process the context to build appropriate builder/setter functions + * 4. make a dynamic block class, which will efficiently collect references and + * create/update dynamic locations/children + * + * @param str + * @returns a new block type, that can build concrete blocks + */ + function createBlock(str) { + if (str in cache$1) { + return cache$1[str]; + } + // step 0: prepare html base element + const doc = new DOMParser().parseFromString(`${str}`, "text/xml"); + const node = doc.firstChild.firstChild; + if (config.shouldNormalizeDom) { + normalizeNode(node); + } + // step 1: prepare intermediate tree + const tree = buildTree(node); + // step 2: prepare block context + const context = buildContext(tree); + // step 3: build the final block class + const template = tree.el; + const Block = buildBlock(template, context); + cache$1[str] = Block; + return Block; + } + // ----------------------------------------------------------------------------- + // Helper + // ----------------------------------------------------------------------------- + function normalizeNode(node) { + if (node.nodeType === Node.TEXT_NODE) { + if (!/\S/.test(node.textContent)) { + node.remove(); + return; + } + } + if (node.nodeType === Node.ELEMENT_NODE) { + if (node.tagName === "pre") { + return; + } + } + for (let i = node.childNodes.length - 1; i >= 0; --i) { + normalizeNode(node.childNodes.item(i)); + } + } + function buildTree(node, parent = null, domParentTree = null) { + switch (node.nodeType) { + case Node.ELEMENT_NODE: { + // HTMLElement + let currentNS = domParentTree && domParentTree.currentNS; + const tagName = node.tagName; + let el = undefined; + const info = []; + if (tagName.startsWith("block-text-")) { + const index = parseInt(tagName.slice(11), 10); + info.push({ type: "text", idx: index }); + el = document.createTextNode(""); + } + if (tagName.startsWith("block-child-")) { + if (!domParentTree.isRef) { + addRef(domParentTree); + } + const index = parseInt(tagName.slice(12), 10); + info.push({ type: "child", idx: index }); + el = document.createTextNode(""); + } + const attrs = node.attributes; + const ns = attrs.getNamedItem("block-ns"); + if (ns) { + attrs.removeNamedItem("block-ns"); + currentNS = ns.value; + } + if (!el) { + el = currentNS + ? document.createElementNS(currentNS, tagName) + : document.createElement(tagName); + } + if (el instanceof Element) { + if (!domParentTree) { + // some html elements may have side effects when setting their attributes. + // For example, setting the src attribute of an will trigger a + // request to get the corresponding image. This is something that we + // don't want at compile time. We avoid that by putting the content of + // the block in a