Cleaned up code and fixed an issue with the gulp file where dev was still minifying js. Added reflected properties support and fixed a few other issues.

This commit is contained in:
Matt Mo 2020-08-23 11:50:31 -07:00
parent d4df41e427
commit f4ac568976
7 changed files with 151 additions and 45 deletions

View File

@ -79,14 +79,6 @@ function jsTask() {
'src/**/*.js',
'src/*.js'])
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(minify({
mangle: false,
compress: true,
noSource: true,
ext: {
min: '.js'
}
}))
.pipe(sourcemaps.write())
.pipe(lineec())
.pipe(gulp.dest(`${outputDirectory}/`));

View File

@ -1,3 +1,4 @@
SET BUILD_OPTIMIZE=false
SET BUILD_OUTPUT_DIR=dev
call gulp run
pause

View File

@ -106,7 +106,7 @@ class IgniteElement extends HTMLElement {
if (renderTemplate !== this.template && renderTemplate) {
this.template.child(renderTemplate);
} else if (!renderTemplate) {
console.warn(`RenderTemplate was null for element: ${this.tagName}, is render() returning null or not returning anything?`);
throw `RenderTemplate was null for template: ${this.tagName}. Is render() returning null or not returning a template?`;
}
//Construct our template.

View File

@ -7,11 +7,13 @@ class IgniteProperty {
this.onChangeCallbacks = [];
this.onPushCallbacks = [];
this.onPopCallbacks = [];
this.callbacks = [];
this.arrayCallbacks = [];
this.reflected = [];
this._value = val;
this.ignoreValueChange = false;
//Attempt to patch the value if it's a list.
this.patchList();
this.patchArray();
}
get value() {
@ -19,21 +21,39 @@ class IgniteProperty {
}
set value(val) {
this.setValue(val, true);
}
setValue(val, reflect) {
//If the ignore value change flag is set exit.
if (this.ignoreValueChange) {
return;
}
var old = this._value;
this._value = val;
//Disconnect any existing callbacks
this.callbacks.forEach(callback => callback.disconnect());
this.callbacks = [];
//Attempt to patch the value if it's a list.
this.patchList();
//Attempt to patch the value if it's an array.
this.patchArray();
//Invoke any callbacks letting them know the value changed.
this.invokeOnChange(old, val);
if (reflect) {
this.ignoreValueChange = true; //Ignore changes incase we are connected to any reflected properties.
this.reflected.forEach(reflect => reflect.value = val);
this.ignoreValueChange = false;
}
}
patchList() {
patchArray() {
//Disconnect any existing array callbacks
if (this.arrayCallbacks.length > 0) {
this.arrayCallbacks.forEach(callback => callback.disconnect());
this.arrayCallbacks = [];
}
//If our value is an array and it hasn't been patched, then patch it.
if (Array.isArray(this._value) && this._value.onPushCallbacks == undefined) {
this._value.onPushCallbacks = [];
this._value.onPopCallbacks = [];
@ -70,11 +90,12 @@ class IgniteProperty {
this.onPopCallbacks = this.onPopCallbacks.filter(pop => pop != callback);
}
this.callbacks.push(this._value.attachOnPush(() => this.invokeOnPush()));
this.callbacks.push(this._value.attachOnPop(() => this.invokeOnPop()));
this.arrayCallbacks.push(this._value.attachOnPush(() => this.invokeOnPush()));
this.arrayCallbacks.push(this._value.attachOnPop(() => this.invokeOnPop()));
} else if (Array.isArray(this._value) && this._value.onPushCallbacks) {
this.callbacks.push(this._value.attachOnPush(() => this.invokeOnPush()));
this.callbacks.push(this._value.attachOnPop(() => this.invokeOnPop()));
//This array has already been patched but attach to it so we get callbacks.
this.arrayCallbacks.push(this._value.attachOnPush(() => this.invokeOnPush()));
this.arrayCallbacks.push(this._value.attachOnPop(() => this.invokeOnPop()));
}
}
@ -146,8 +167,6 @@ class IgniteCallback {
}
invoke(...params) {
console.log("Invoke with params:", params);
if (this.callback) {
this.callback(...params);
}
@ -195,5 +214,7 @@ class IgniteRenderingContext {
window.IgniteRenderingContext = IgniteRenderingContext;
export {
IgniteProperty
IgniteProperty,
IgniteRenderingContext,
IgniteCallback
};

View File

@ -1,4 +1,5 @@
import { IgniteProperty } from './ignite-html.js';
import { IgniteElement } from './ignite-element.js';
class IgniteTemplate {
constructor(items) {
@ -25,7 +26,7 @@ class IgniteTemplate {
} else if (items[i] instanceof IgniteTemplate || items[i].prototype instanceof IgniteTemplate) {
this.children.push(items[i]);
} else {
console.warn("Attempted to add a child for template: ", this, " which is not supported. Unsupported child element: ", items[i]);
throw `Attempted to add a child for template: ${this.tagName} which is not supported. Child: ${items[i]}`;
}
}
}
@ -70,12 +71,16 @@ class IgniteTemplate {
* @param {string} name
* @param {any} value
*/
property(name, value) {
property(name, value, reflect = false) {
if (this.properties[name]) {
throw `Attempted to set a property twice on a IgniteTemplate: ${this.tagName}. This is not allowed and should be avoided.`;
}
if (value instanceof IgniteProperty) {
this.callbacks.push(value.attachOnChange((oldValue, newValue) => this.onPropertyChanged(oldValue, newValue, name)));
this.properties[name] = value.value;
this.properties[name] = { value: value.value, reflect: (reflect == true ? value : null) };
} else {
this.properties[name] = value;
this.properties[name] = { value: value, reflect: null };
}
return this;
@ -97,7 +102,7 @@ class IgniteTemplate {
} else if (items[i] instanceof IgniteTemplate || items[i].prototype instanceof IgniteTemplate) {
this.children.push(items[i]);
} else {
console.warn("Attempted to add a child for template: ", this, " which is not supported. Unsupported child element: ", items[i]);
throw `Attempted to add a child for template: ${this.tagName} which is not supported. Child: ${items[i]}`;
}
}
@ -139,12 +144,20 @@ class IgniteTemplate {
return this;
}
/**
* Adds a on click event handler to this template.
* @param {Any} func
*/
onClick(func) {
this.on("click", func);
return this;
}
/**
* Adds a on enter key press event handler to this template.
* @param {Any} func
*/
onEnter(func) {
var eventName = "keydown";
@ -226,8 +239,11 @@ class IgniteTemplate {
if (!this.element) {
this.element = window.document.createElement(this.tagName);
//Pass back our template to the element we are creating.
this.element.template = this;
//Pass back our template to the element we are creating if it's not a ignite element, since
//it will have it's own template automatically.
if (!(this.element instanceof IgniteElement)) {
this.element.template = this;
}
//If the element has a onDisconnected function, attach to it
//(This way if a custom element is removed we can deconstruct and cleanup)
@ -235,7 +251,7 @@ class IgniteTemplate {
this.element.onDisconnected = () => this.deconstruct();
}
//Invoke any refs we have
//Invoke any refs we have and pass back the element reference.
this.refs.forEach((ref) => ref(this.element));
}
@ -274,7 +290,11 @@ class IgniteTemplate {
//Set the properties on this element
var keys = Object.keys(this.properties);
for (var i = 0; i < keys.length; i++) {
this.element[keys[i]] = this.properties[keys[i]];
this.element[keys[i]] = this.properties[keys[i]].value;
if (this.properties[keys[i]].reflect != null) {
this.element[keys[i]].reflected.push(this.properties[keys[i]].reflect);
}
}
//Construct the children under this element
@ -297,8 +317,6 @@ class IgniteTemplate {
* there are no memory leaks.
*/
deconstruct() {
console.log(`Deconstructing ${this.tagName}`);
//Remove and disconnect all events
if (this.element && this.events) {
var keys = Object.keys(this.events);
@ -390,10 +408,12 @@ class IgniteTemplate {
*/
onPropertyChanged(oldValue, newValue, propertyName) {
if (this.element) {
this.element[propertyName] = newValue;
//Use the set value function and don't reflect the change because it came from above which
//would be the reflected property, this reduces some functions being called twice that don't need to be.
this.element[`_${propertyName}`].setValue(newValue, false);
}
this.properties[propertyName] = newValue;
this.properties[propertyName].value = newValue;
}
/**
@ -475,6 +495,70 @@ class input extends IgniteTemplate {
}
}
class h1 extends IgniteTemplate {
constructor(...items) {
super(items);
this.tagName = "h1";
}
}
class h2 extends IgniteTemplate {
constructor(...items) {
super(items);
this.tagName = "h2";
}
}
class h3 extends IgniteTemplate {
constructor(...items) {
super(items);
this.tagName = "h3";
}
}
class h4 extends IgniteTemplate {
constructor(...items) {
super(items);
this.tagName = "h4";
}
}
class h5 extends IgniteTemplate {
constructor(...items) {
super(items);
this.tagName = "h5";
}
}
class p extends IgniteTemplate {
constructor(...items) {
super(items);
this.tagName = "p";
}
}
class span extends IgniteTemplate {
constructor(...items) {
super(items);
this.tagName = "span";
}
}
class i extends IgniteTemplate {
constructor(...items) {
super(items);
this.tagName = "i";
}
}
class html extends IgniteTemplate {
constructor(code) {
super([]);
@ -600,15 +684,15 @@ class list extends IgniteTemplate {
}
onListChanged(oldValue, newValue) {
console.log("On List changed:", newValue);
this.list = newValue;
IgniteRenderingContext.enter();
try {
this.construct(null); //The list changed, reconstruct this template.
} catch (error) { console.error(error); }
} catch (error) {
console.error(error);
}
IgniteRenderingContext.leave();
}
@ -674,5 +758,13 @@ export {
list,
a,
input,
h1,
h2,
h3,
h4,
h5,
p,
span,
i,
slot
};

View File

@ -20,13 +20,12 @@ class MainApp extends IgniteElement {
return this.template
.child(
new Sheet()
.property("name", this.name)
.property("items", this.items)
.property("name", this.name, true)
.property("items", this.items, true)
.ref(this.sheet)
.class(this.sheetClass)
.child(new html(`<h3>Im a child for sheet!</h3>`))
)
.child(new Sheet().property("items", this.items))
.child(
new div(
new html(`<h1>This is a slot!`),

View File

@ -1,5 +1,5 @@
import { IgniteElement } from './ignite-element.js';
import { IgniteTemplate, div, html, list, a, slot, input } from './ignite-template.js';
import { IgniteTemplate, div, html, list, a, slot, input, h1 } from './ignite-template.js';
class Sheet extends IgniteElement {
constructor() {
@ -34,6 +34,7 @@ class Sheet extends IgniteElement {
.child(
new div(
new input().attribute("type", "text").onEnter(this.enter),
new h1(this.name),
new html("<h2>this is before</h2>"),
new div(
new list(this.items, (item) => {