|
|
|
@ -39,6 +39,8 @@ class IgniteTemplate {
|
|
|
|
|
this._attributes = {};
|
|
|
|
|
this._classes = [];
|
|
|
|
|
this._properties = {};
|
|
|
|
|
this._options = [];
|
|
|
|
|
this._optionElements = [];
|
|
|
|
|
this._variables = {};
|
|
|
|
|
this._reflecting = {};
|
|
|
|
|
this._refs = [];
|
|
|
|
@ -259,7 +261,7 @@ class IgniteTemplate {
|
|
|
|
|
/**
|
|
|
|
|
* Sets a property on the element this template will construct.
|
|
|
|
|
* @param {String} name Name of the property to set.
|
|
|
|
|
* @param {Any|IgniteProperty} value Value of the property to use. If a Property is passed the value will auto update.
|
|
|
|
|
* @param {Any|IgniteProperty|IgniteProperty[]} value Value of the property to use. If a Property is passed the value will auto update.
|
|
|
|
|
* @param {Boolean} reflect If true whenever this property is changed it's value will be passed back to the Property that was passed as value if one was passed.
|
|
|
|
|
* @param {Function} converter Optional function that can be used to convert the value if needed.
|
|
|
|
|
* @returns {IgniteTemplate} This ignite template so function calls can be chained.
|
|
|
|
@ -287,6 +289,28 @@ class IgniteTemplate {
|
|
|
|
|
value: (converter != null ? converter(value.value) : value.value),
|
|
|
|
|
reflect: (reflect == true ? value : null)
|
|
|
|
|
};
|
|
|
|
|
} else if (Array.isArray(value) && value.length > 0 && value[0] instanceof IgniteProperty) {
|
|
|
|
|
//There must be a converter for this to work correctly
|
|
|
|
|
if (!converter) {
|
|
|
|
|
throw "Cannot pass an array of properties without using a converter!";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Attack a callback for all the properties
|
|
|
|
|
value.forEach(prop => {
|
|
|
|
|
if (prop instanceof IgniteProperty) {
|
|
|
|
|
this._callbacks.push(prop.attachOnChange((oldValue, newValue) => this.onPropertyChanged(name, converter(...value.getPropertyValues()))));
|
|
|
|
|
this._callbacks.push(prop.attachOnPush((list, items) => this.onPropertyChanged(name, converter(...value.getPropertyValues()))));
|
|
|
|
|
this._callbacks.push(prop.attachOnUnshift((list, items) => this.onPropertyChanged(name, converter(...value.getPropertyValues()))));
|
|
|
|
|
this._callbacks.push(prop.attachOnPop((list) => this.onPropertyChanged(name, converter(...value.getPropertyValues()))));
|
|
|
|
|
this._callbacks.push(prop.attachOnShift((list) => this.onPropertyChanged(name, converter(...value.getPropertyValues()))));
|
|
|
|
|
this._callbacks.push(prop.attachOnSplice((list, start, deleteCount, items) => this.onPropertyChanged(name, converter(...value.getPropertyValues()))));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this._properties[name] = {
|
|
|
|
|
value: converter(...value.getPropertyValues()),
|
|
|
|
|
reflect: (reflect == true ? value : null)
|
|
|
|
|
};
|
|
|
|
|
} else {
|
|
|
|
|
this._properties[name] = {
|
|
|
|
|
value: (converter != null ? converter(value) : value),
|
|
|
|
@ -376,6 +400,17 @@ class IgniteTemplate {
|
|
|
|
|
|
|
|
|
|
Object.getOwnPropertyNames(props).forEach(name => this.property(name, props[name], true));
|
|
|
|
|
}
|
|
|
|
|
else if (props instanceof IgniteProperty) {
|
|
|
|
|
this._callbacks.push(props.attachOnChange((oldValue, newValue) => {
|
|
|
|
|
if (newValue) {
|
|
|
|
|
Object.keys(newValue).forEach(name => this.onPropertyChanged(name, newValue[name]));
|
|
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
if (props.value) {
|
|
|
|
|
Object.keys(props.value).forEach(name => this.property(name, props[name], false, null));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
Object.keys(props).forEach(name => this.property(name, props[name], false, null));
|
|
|
|
|
}
|
|
|
|
@ -383,9 +418,80 @@ class IgniteTemplate {
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets the options elements to be constructed by this template.
|
|
|
|
|
* Valid options can be in this format:
|
|
|
|
|
* [{1: "Option 1"}, {2: "Option 2"}]
|
|
|
|
|
* ["A", "B", "C"]
|
|
|
|
|
* {1: "Option 1", 2: "Option 2"}
|
|
|
|
|
* @param {Array|Object|IgniteProperty|IgniteProperty[]} options The options to be constructed on this template.
|
|
|
|
|
* @param {Function} converter Optional function that can be used to convert the options input if needed.
|
|
|
|
|
* @returns {IgniteTemplate} This ignite template so function calls can be chained.
|
|
|
|
|
*/
|
|
|
|
|
options(options, converter = null) {
|
|
|
|
|
IgniteRendering.push();
|
|
|
|
|
|
|
|
|
|
var converted = null;
|
|
|
|
|
|
|
|
|
|
if (options instanceof IgniteProperty) {
|
|
|
|
|
this._callbacks.push(options.attachOnChange((oldValue, newValue) => this.onOptionsChanged(converter ? converter(newValue) : newValue)));
|
|
|
|
|
this._callbacks.push(options.attachOnPush((list, items) => this.onOptionsChanged(converter ? converter(list) : list)));
|
|
|
|
|
this._callbacks.push(options.attachOnUnshift((list, items) => this.onOptionsChanged(converter ? converter(list) : list)));
|
|
|
|
|
this._callbacks.push(options.attachOnPop((list) => this.onOptionsChanged(converter ? converter(list) : list)));
|
|
|
|
|
this._callbacks.push(options.attachOnShift((list) => this.onOptionsChanged(converter ? converter(list) : list)));
|
|
|
|
|
this._callbacks.push(options.attachOnSplice((list, start, deleteCount, items) => this.onOptionsChanged(converter ? converter(list) : list)));
|
|
|
|
|
|
|
|
|
|
converted = converter ? converter(options.value) : options.value;
|
|
|
|
|
} else if (Array.isArray(options) && options.length > 0 && options[0] instanceof IgniteProperty) {
|
|
|
|
|
//There must be a converter for this to work correctly
|
|
|
|
|
if (!converter) {
|
|
|
|
|
throw "Cannot pass an array of properties without using a converter!";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Attack a callback for all the properties
|
|
|
|
|
options.forEach(option => {
|
|
|
|
|
if (option instanceof IgniteProperty) {
|
|
|
|
|
this._callbacks.push(option.attachOnChange((oldValue, newValue) => this.onOptionsChanged(converter(...options.getPropertyValues()))));
|
|
|
|
|
this._callbacks.push(option.attachOnPush((list, items) => this.onOptionsChanged(converter(...options.getPropertyValues()))));
|
|
|
|
|
this._callbacks.push(option.attachOnUnshift((list, items) => this.onOptionsChanged(converter(...options.getPropertyValues()))));
|
|
|
|
|
this._callbacks.push(option.attachOnPop((list) => this.onOptionsChanged(converter(...options.getPropertyValues()))));
|
|
|
|
|
this._callbacks.push(option.attachOnShift((list) => this.onOptionsChanged(converter(...options.getPropertyValues()))));
|
|
|
|
|
this._callbacks.push(option.attachOnSplice((list, start, deleteCount, items) => this.onOptionsChanged(converter(...options.getPropertyValues()))));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
converted = converter(...options.getPropertyValues());
|
|
|
|
|
} else {
|
|
|
|
|
converted = converter ? converter(options) : options;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Array.isArray(converted)) {
|
|
|
|
|
this._options = converted.map((option, index) => {
|
|
|
|
|
if (option instanceof Object) {
|
|
|
|
|
var keys = Object.keys(option);
|
|
|
|
|
|
|
|
|
|
if (keys.length == 0) {
|
|
|
|
|
return null;
|
|
|
|
|
} else {
|
|
|
|
|
return { value: keys[0], name: option[keys[0]] };
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return { value: index, name: option };
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else if (converted instanceof Object) {
|
|
|
|
|
this._options = Object.keys(converted).map(key => {
|
|
|
|
|
return { value: key, name: converted[key] };
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IgniteRendering.pop();
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets the inner html of the element to be constructed by this template.
|
|
|
|
|
* @param {String|IgniteProperty} value InnerHTML to set for element. If a property is passed the html will auto update.
|
|
|
|
|
* @param {String|IgniteProperty|IgniteProperty[]} value InnerHTML to set for element. If a property is passed the html will auto update.
|
|
|
|
|
* @param {Function} converter Optional function that can be used to convert the value if needed.
|
|
|
|
|
* @returns This ignite template so funciton calls can be chained.
|
|
|
|
|
*/
|
|
|
|
@ -657,6 +763,54 @@ class IgniteTemplate {
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds a on escape key press event handler to this template.
|
|
|
|
|
* @param {Function|IgniteProperty} eventCallback The callback function to be invoked by the event once it fires.
|
|
|
|
|
* @returns {IgniteTemplate} This ignite template so function calls can be chained.
|
|
|
|
|
*/
|
|
|
|
|
onEscape(eventCallback) {
|
|
|
|
|
var eventName = "keydown";
|
|
|
|
|
|
|
|
|
|
if (!this._events[eventName]) {
|
|
|
|
|
this._events[eventName] = [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (eventCallback instanceof IgniteProperty) {
|
|
|
|
|
this._callbacks.push(eventCallback.attachOnChange((oldValue, newValue) => {
|
|
|
|
|
//Create a new wrapped function to check for the escape key being pressed.
|
|
|
|
|
var wrapped = (e) => {
|
|
|
|
|
if (e.key === 'Escape') {
|
|
|
|
|
newValue(e);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
eventCallback._value = wrapped; //Store the wrapped function into the property so we can remove it later
|
|
|
|
|
this.onEventChanged(oldValue, wrapped, eventName); //Invoke event changed with the old value and wrapped one.
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
//Create the initial wrapper
|
|
|
|
|
var target = eventCallback._value;
|
|
|
|
|
var wrapped = (e) => {
|
|
|
|
|
if (e.key === 'Escape') {
|
|
|
|
|
target(e);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//Store the wrapped so that it's the old value next time around.
|
|
|
|
|
eventCallback._value = wrapped;
|
|
|
|
|
|
|
|
|
|
this._events[eventName].push(wrapped);
|
|
|
|
|
} else {
|
|
|
|
|
this.on(eventName, (e) => {
|
|
|
|
|
if (e.key === 'Escape') {
|
|
|
|
|
eventCallback(e);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds a on backspace key press event handler to this template.
|
|
|
|
|
* @param {Function|IgniteProperty} eventCallback The callback function to be invoked by the event once it fires.
|
|
|
|
@ -775,10 +929,112 @@ class IgniteTemplate {
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds an event handler that gets called when this element is being deconstructed from the DOM.
|
|
|
|
|
* @param {Function} eventCallback The callback function to be invoked once this element is disconnected.
|
|
|
|
|
* @returns {IgniteTemplate} This ignite template so function calls can be chained.
|
|
|
|
|
*/
|
|
|
|
|
onDeconstruct(eventCallback) {
|
|
|
|
|
if (eventCallback) {
|
|
|
|
|
this._destructors.push(() => {
|
|
|
|
|
IgniteRendering.push();
|
|
|
|
|
|
|
|
|
|
eventCallback();
|
|
|
|
|
|
|
|
|
|
IgniteRendering.pop();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds a special event handler to this element that invokes with the content of an input after a certain amount of time has passed after typing.
|
|
|
|
|
* This function supports inputs, text area's and content editable elements.
|
|
|
|
|
* @param {Function|IgniteProperty} eventCallback The callback function to be invoked when a typeAhead event occurs, it will be passed the typed value.
|
|
|
|
|
* @param {Number} minCharacters Min number of characters excluding whitespace that have to be typed before this event is invoked. Default is 2.
|
|
|
|
|
* @param {Number} callbackDelay The delay in miliseconds between each event callback. Default is 350.
|
|
|
|
|
* @param {Boolean} callbackReset Whether or not to reset the callback delay on each keypress. Default is true. If true, type ahead only occurrs when typing has stopped.
|
|
|
|
|
* @param {Boolean} enterCallback Whether or not the enter key should be considered for a type ahead. Default is true.
|
|
|
|
|
* @returns {IgniteTemplate} This ignite template so function calls can be chained.
|
|
|
|
|
*/
|
|
|
|
|
onTypeAhead(eventCallback, minCharacters = 2, callbackDelay = 350, callbackReset = true, enterCallback = true) {
|
|
|
|
|
var typeAheadTimeout = null;
|
|
|
|
|
|
|
|
|
|
var typeAheadRunning = false;
|
|
|
|
|
|
|
|
|
|
var lastValue = null;
|
|
|
|
|
|
|
|
|
|
var typeAhead = async (target, force) => {
|
|
|
|
|
var value = null;
|
|
|
|
|
|
|
|
|
|
typeAheadRunning = true;
|
|
|
|
|
|
|
|
|
|
//Get the value from the target if we can.
|
|
|
|
|
if (target instanceof HTMLElement) {
|
|
|
|
|
if (target.tagName == "INPUT" || target.tagName == "TEXTAREA") {
|
|
|
|
|
value = target.value;
|
|
|
|
|
} else if (target.contentEditable == "true") {
|
|
|
|
|
value = target.innerText;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Trim the value if we can
|
|
|
|
|
value = value?.trim();
|
|
|
|
|
|
|
|
|
|
//If the value has at least the min number of characters after being trimmed invoke the callback.
|
|
|
|
|
if (value != null && value.length >= minCharacters && (lastValue != value || force)) {
|
|
|
|
|
try {
|
|
|
|
|
if (eventCallback instanceof IgniteProperty) {
|
|
|
|
|
await eventCallback.value(value);
|
|
|
|
|
} else if (eventCallback instanceof Function) {
|
|
|
|
|
await eventCallback(value);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("Error occurred during type ahead callback", error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Request another type ahead incase the value changed while we were waiting for the event callback to finish.
|
|
|
|
|
typeAheadTimeout = setTimeout(() => typeAhead(target, false), callbackDelay);
|
|
|
|
|
} else {
|
|
|
|
|
typeAheadTimeout = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lastValue = value;
|
|
|
|
|
|
|
|
|
|
typeAheadRunning = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//Attach a keydown event and handle the type ahead.
|
|
|
|
|
this.on("keydown", (e) => {
|
|
|
|
|
//If the key was an enter key, dont allow if it's not allowed.
|
|
|
|
|
if (e.key == "Enter" && !enterCallback) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//If callback reset is true and there's a pending type ahead, clear it.
|
|
|
|
|
if (callbackReset && typeAheadTimeout && !typeAheadRunning) {
|
|
|
|
|
clearTimeout(typeAheadTimeout);
|
|
|
|
|
typeAheadTimeout = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Schedule a new type ahead timeout if one isn't already running.
|
|
|
|
|
if (!typeAheadTimeout) {
|
|
|
|
|
if (e.key == "Enter") {
|
|
|
|
|
typeAheadTimeout = setTimeout(() => typeAhead(e.target, true), 0);
|
|
|
|
|
} else {
|
|
|
|
|
typeAheadTimeout = setTimeout(() => typeAhead(e.target, false), callbackDelay);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds a CSS property to this template with a value and priority.
|
|
|
|
|
* @param {String} name The name of the CSS property to set.
|
|
|
|
|
* @param {String|IgniteProperty} value The value to set for the property. If an IgniteProperty is used it will auto update this style.
|
|
|
|
|
* @param {String|IgniteProperty|IgniteProperty[]} value The value to set for the property. If an IgniteProperty is used it will auto update this style.
|
|
|
|
|
* @param {String} priority If set to "important" then the style will be marked with !important. Acceptable values: important, !important, true, false, null
|
|
|
|
|
* @param {Function} converter Optional function to convert the value if needed.
|
|
|
|
|
* @returns {IgniteTemplate} This ignite template so function calls can be chained.
|
|
|
|
@ -933,7 +1189,7 @@ class IgniteTemplate {
|
|
|
|
|
/**
|
|
|
|
|
* Adds a checked attribute to this template.
|
|
|
|
|
* @param {Boolean|IgniteProperty} value The value to set for the checked attribute.
|
|
|
|
|
* @param {*} converter Optional function that can convert the value if needed.
|
|
|
|
|
* @param {Any} converter Optional function that can convert the value if needed.
|
|
|
|
|
* @returns {IgniteTemplate} This ignite template so function calls can be chained.
|
|
|
|
|
*/
|
|
|
|
|
checked(value, converter = null) {
|
|
|
|
@ -942,8 +1198,8 @@ class IgniteTemplate {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds a disabled attribute and class to this template.
|
|
|
|
|
* @param {Boolean|IgniteProperty} value A value to determine whether or not the element should be marked as disable or not.
|
|
|
|
|
* @param {*} converter Optional function that can convert the value if needed.
|
|
|
|
|
* @param {Boolean|IgniteProperty|IgniteProperty[]} value A value to determine whether or not the element should be marked as disable or not.
|
|
|
|
|
* @param {Any} converter Optional function that can convert the value if needed.
|
|
|
|
|
* @returns {IgniteTemplate} This ignite template so function calls can be chained.
|
|
|
|
|
*/
|
|
|
|
|
disabled(value, converter = null) {
|
|
|
|
@ -1007,7 +1263,7 @@ class IgniteTemplate {
|
|
|
|
|
/**
|
|
|
|
|
* Adds a readonly attribute and class to this template.
|
|
|
|
|
* @param {Boolean|IgniteProperty} value A value to determine whether or not the element should be marked as readonly or not.
|
|
|
|
|
* @param {*} converter Optional function that can convert the value if needed.
|
|
|
|
|
* @param {Any} converter Optional function that can convert the value if needed.
|
|
|
|
|
* @returns {IgniteTemplate} This ignite template so function calls can be chained.
|
|
|
|
|
*/
|
|
|
|
|
readonly(value, converter = null) {
|
|
|
|
@ -1081,7 +1337,7 @@ class IgniteTemplate {
|
|
|
|
|
* Sets a data attribute on the element to be constructed by this template.
|
|
|
|
|
* @param {String} name The name of the data attribute to set on the element this template will construct.
|
|
|
|
|
* @param {String|IgniteProperty} value The value to set for the data attribute of the element this template will construct.
|
|
|
|
|
* @param {*} converter An optional function that can convert the value if needed.
|
|
|
|
|
* @param {Any} converter An optional function that can convert the value if needed.
|
|
|
|
|
* @returns {IgniteTemplate} This ignite template so function calls can be chained.
|
|
|
|
|
*/
|
|
|
|
|
data(name, value, converter = null) {
|
|
|
|
@ -1258,6 +1514,24 @@ class IgniteTemplate {
|
|
|
|
|
this.children[i].construct(this.element);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Construct any options if needed
|
|
|
|
|
if (this._options.length > 0 && this._optionElements.length == 0) {
|
|
|
|
|
this._options.forEach(option => {
|
|
|
|
|
if (option) {
|
|
|
|
|
var element = window.document.createElement("option");
|
|
|
|
|
element.setAttribute("value", option.value);
|
|
|
|
|
element.innerHTML = option.name;
|
|
|
|
|
|
|
|
|
|
this._optionElements.push(element);
|
|
|
|
|
|
|
|
|
|
//Add this element to the dom.
|
|
|
|
|
if (this.element) {
|
|
|
|
|
this.element.appendChild(element);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Set the elements value if there is one.
|
|
|
|
|
if (this._elementValue != null) {
|
|
|
|
|
if (this.element.hasAttribute("type") && (this.element.getAttribute("type").toLowerCase().trim() == "checkbox" || this.element.getAttribute("type").toLowerCase().trim() == "radio")) {
|
|
|
|
@ -1285,10 +1559,15 @@ class IgniteTemplate {
|
|
|
|
|
//Setup a intersect observer if needed
|
|
|
|
|
if (this._intersectObserverCallback && this._intersectObserverCallback.length > 0) {
|
|
|
|
|
this._intersectObserver = new IntersectionObserver(results => {
|
|
|
|
|
if (results[0].isIntersecting) {
|
|
|
|
|
for (var i = 0; i < this._intersectObserverCallback.length; i++) {
|
|
|
|
|
if (this._intersectObserverCallback[i]) {
|
|
|
|
|
this._intersectObserverCallback[i](results[0]);
|
|
|
|
|
if (results) {
|
|
|
|
|
for (var i = 0; i < results.length; i++) {
|
|
|
|
|
if (results[i].isIntersecting && results[i].target == this.element) {
|
|
|
|
|
for (var i2 = 0; i2 < this._intersectObserverCallback.length; i2++) {
|
|
|
|
|
if (this._intersectObserverCallback[i2]) {
|
|
|
|
|
this._intersectObserverCallback[i2](results[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1302,8 +1581,8 @@ class IgniteTemplate {
|
|
|
|
|
|
|
|
|
|
//If our element has not been added to the dom yet, then add it.
|
|
|
|
|
if (this.element.isConnected == false && this.element.parentElement == null) {
|
|
|
|
|
if (sibling) {
|
|
|
|
|
parent.insertBefore(this.element, sibling);
|
|
|
|
|
if (sibling && sibling.nextSibling) {
|
|
|
|
|
sibling.parentElement.insertBefore(this.element, sibling.nextSibling);
|
|
|
|
|
} else {
|
|
|
|
|
parent.appendChild(this.element);
|
|
|
|
|
}
|
|
|
|
@ -1378,12 +1657,14 @@ class IgniteTemplate {
|
|
|
|
|
|
|
|
|
|
//For any classes that are missing on the element, add them. If we have duplicates this
|
|
|
|
|
//can happen.
|
|
|
|
|
if (this.element) {
|
|
|
|
|
this._classes.forEach((cl) => {
|
|
|
|
|
if (!this.element.classList.contains(cl)) {
|
|
|
|
|
this.element.classList.add(cl);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Called when a attribute on this template was changed and needs to be updated
|
|
|
|
@ -1461,8 +1742,12 @@ class IgniteTemplate {
|
|
|
|
|
IgniteRendering.leave();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!this._properties[propertyName]) {
|
|
|
|
|
this._properties[propertyName] = { value: newValue };
|
|
|
|
|
} else {
|
|
|
|
|
this._properties[propertyName].value = newValue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Called when a variable on this template was changed and needs to be updated.
|
|
|
|
@ -1566,6 +1851,58 @@ class IgniteTemplate {
|
|
|
|
|
|
|
|
|
|
this._styles[name].value = newValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Called when the options for this template have changed and need to be updated.
|
|
|
|
|
* @param {Array} newValue
|
|
|
|
|
*/
|
|
|
|
|
onOptionsChanged(newValue) {
|
|
|
|
|
//First remove all existing options
|
|
|
|
|
if (this._optionElements) {
|
|
|
|
|
this._optionElements.forEach(element => element.remove());
|
|
|
|
|
this._optionElements = [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Set the options to null.
|
|
|
|
|
this._options = [];
|
|
|
|
|
|
|
|
|
|
//Convert the newValue into options
|
|
|
|
|
if (Array.isArray(newValue)) {
|
|
|
|
|
this._options = newValue.map((option, index) => {
|
|
|
|
|
if (option instanceof Object) {
|
|
|
|
|
var keys = Object.keys(option);
|
|
|
|
|
|
|
|
|
|
if (keys.length == 0) {
|
|
|
|
|
return null;
|
|
|
|
|
} else {
|
|
|
|
|
return { value: keys[0], name: option[keys[0]] };
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return { value: index, name: option };
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else if (newValue instanceof Object) {
|
|
|
|
|
this._options = Object.keys(newValue).map(key => {
|
|
|
|
|
return { value: key, name: newValue[key] };
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Construct the new options
|
|
|
|
|
this._options.forEach(option => {
|
|
|
|
|
if (option) {
|
|
|
|
|
var element = document.createElement("option");
|
|
|
|
|
element.setAttribute("value", option.value);
|
|
|
|
|
element.innerHTML = option.name;
|
|
|
|
|
|
|
|
|
|
this._optionElements.push(element);
|
|
|
|
|
|
|
|
|
|
//Add this element to the dom.
|
|
|
|
|
if (this.element) {
|
|
|
|
|
this.element.appendChild(element);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -1750,6 +2087,18 @@ class ul extends IgniteTemplate {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* An ignite template that can be used to construct a ol element.
|
|
|
|
|
*/
|
|
|
|
|
class ol extends IgniteTemplate {
|
|
|
|
|
/**
|
|
|
|
|
* @param {...String|Number|IgniteProperty|IgniteTemplate} children A series of children to be added to this template.
|
|
|
|
|
*/
|
|
|
|
|
constructor(...children) {
|
|
|
|
|
super("ol", children);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* An ignite template that can be used to construct a li element.
|
|
|
|
|
*/
|
|
|
|
@ -2002,6 +2351,63 @@ class footer extends IgniteTemplate {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* An ignite template that can be used to construct a iframe element.
|
|
|
|
|
*/
|
|
|
|
|
class iframe extends IgniteTemplate {
|
|
|
|
|
/**
|
|
|
|
|
* @param {...String|Number|IgniteProperty|IgniteTemplate} children A series of children to be added to this template.
|
|
|
|
|
*/
|
|
|
|
|
constructor(...children) {
|
|
|
|
|
super("iframe", children);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* An ignite template that can be used to construct a video element.
|
|
|
|
|
*/
|
|
|
|
|
class video extends IgniteTemplate {
|
|
|
|
|
/**
|
|
|
|
|
* @param {...String|Number|IgniteProperty|IgniteTemplate} children A series of children to be added to this template.
|
|
|
|
|
*/
|
|
|
|
|
constructor(...children) {
|
|
|
|
|
super("video", children);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* An ignite template that can be used to construct a source element.
|
|
|
|
|
*/
|
|
|
|
|
class source extends IgniteTemplate {
|
|
|
|
|
/**
|
|
|
|
|
* @param {...String|Number|IgniteProperty|IgniteTemplate} children A series of children to be added to this template.
|
|
|
|
|
*/
|
|
|
|
|
constructor(...children) {
|
|
|
|
|
super("source", children);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Called when an attribute on this source element is changing.
|
|
|
|
|
* @param {String} name
|
|
|
|
|
* @param {Any} newValue
|
|
|
|
|
*/
|
|
|
|
|
onAttributeChanged(name, newValue) {
|
|
|
|
|
//If the src is changing, we need to stop the parent video player and reset it's position.
|
|
|
|
|
if (this.element && name && name.trim().toLowerCase() == "src") {
|
|
|
|
|
this.element.parentElement.pause();
|
|
|
|
|
this.element.parentElement.currentTime = 0;
|
|
|
|
|
|
|
|
|
|
//If there is a valid video source, call load on the player.
|
|
|
|
|
if (newValue && newValue.length > 0) {
|
|
|
|
|
this.element.parentElement.load();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Call the original on attribute changed function.
|
|
|
|
|
super.onAttributeChanged(name, newValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* An ignite template that can be used to construct a progress element.
|
|
|
|
|
*/
|
|
|
|
@ -2088,12 +2494,14 @@ class line extends IgniteTemplate {
|
|
|
|
|
class text extends IgniteTemplate {
|
|
|
|
|
/**
|
|
|
|
|
* Constructs a text template with the text to render.
|
|
|
|
|
* @param {String|IgniteProperty} text The text to render within this text template.
|
|
|
|
|
* @param {String|IgniteProperty|IgniteProperty[]} text The text to render within this text template.
|
|
|
|
|
* @param {Function} converter An optional function that can be used to convert the text.
|
|
|
|
|
*/
|
|
|
|
|
constructor(text, converter) {
|
|
|
|
|
super();
|
|
|
|
|
|
|
|
|
|
IgniteRendering.push();
|
|
|
|
|
|
|
|
|
|
if (text instanceof IgniteProperty) {
|
|
|
|
|
this._callbacks.push(text.attachOnChange((oldValue, newValue) => this.onTextChanged(converter != null ? converter(newValue) : newValue)));
|
|
|
|
|
this._callbacks.push(text.attachOnPush((list, items) => this.onTextChanged(converter != null ? converter(list) : null)));
|
|
|
|
@ -2125,8 +2533,16 @@ class text extends IgniteTemplate {
|
|
|
|
|
} else {
|
|
|
|
|
this._text = (converter != null ? converter(text) : text);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IgniteRendering.pop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constructs this template and adds it to the DOM if this template
|
|
|
|
|
* has not already been constructed.
|
|
|
|
|
* @param {HTMLElement} parent Parent element that will contain the constructed element.
|
|
|
|
|
* @param {HTMLElement} sibling Optional sibling element that can be used to add the element adjacantly.
|
|
|
|
|
*/
|
|
|
|
|
construct(parent, sibling) {
|
|
|
|
|
//Don't construct if we have no parent, no sibling and no element.
|
|
|
|
|
if (!parent && !sibling && !this.element) {
|
|
|
|
@ -2136,19 +2552,19 @@ class text extends IgniteTemplate {
|
|
|
|
|
if (!this.element) {
|
|
|
|
|
this.element = window.document.createTextNode("");
|
|
|
|
|
|
|
|
|
|
if (sibling) {
|
|
|
|
|
sibling.parentElement.insertBefore(this.element, sibling);
|
|
|
|
|
if (sibling && sibling.nextSibling) {
|
|
|
|
|
sibling.parentElement.insertBefore(this.element, sibling.nextSibling);
|
|
|
|
|
} else {
|
|
|
|
|
parent.appendChild(this.element);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.element.data = this._text;
|
|
|
|
|
this.element.nodeValue = this._text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onTextChanged(newValue) {
|
|
|
|
|
if (this.element) {
|
|
|
|
|
this.element.data = newValue;
|
|
|
|
|
this.element.nodeValue = newValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._text = newValue;
|
|
|
|
@ -2180,6 +2596,12 @@ class html extends IgniteTemplate {
|
|
|
|
|
this.elements = [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constructs this template and adds it to the DOM if this template
|
|
|
|
|
* has not already been constructed.
|
|
|
|
|
* @param {HTMLElement} parent Parent element that will contain the constructed element.
|
|
|
|
|
* @param {HTMLElement} sibling Optional sibling element that can be used to add the element adjacantly.
|
|
|
|
|
*/
|
|
|
|
|
construct(parent, sibling) {
|
|
|
|
|
//Don't construct if we have no parent, no sibling and no element.
|
|
|
|
|
if (!parent && !sibling && !this.element) {
|
|
|
|
@ -2189,8 +2611,8 @@ class html extends IgniteTemplate {
|
|
|
|
|
if (!this.element) {
|
|
|
|
|
this.element = window.document.createTextNode("");
|
|
|
|
|
|
|
|
|
|
if (sibling) {
|
|
|
|
|
sibling.parentElement.insertBefore(this.element, sibling);
|
|
|
|
|
if (sibling && sibling.nextSibling) {
|
|
|
|
|
sibling.parentElement.insertBefore(this.element, sibling.nextSibling);
|
|
|
|
|
} else {
|
|
|
|
|
parent.appendChild(this.element);
|
|
|
|
|
}
|
|
|
|
@ -2278,6 +2700,12 @@ class list extends IgniteTemplate {
|
|
|
|
|
this.tagName = "shadow list";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constructs this template and adds it to the DOM if this template
|
|
|
|
|
* has not already been constructed.
|
|
|
|
|
* @param {HTMLElement} parent Parent element that will contain the constructed element.
|
|
|
|
|
* @param {HTMLElement} sibling Optional sibling element that can be used to add the element adjacantly.
|
|
|
|
|
*/
|
|
|
|
|
construct(parent, sibling) {
|
|
|
|
|
//Don't construct if we have no parent, no sibling and no element.
|
|
|
|
|
if (!parent && !sibling && !this.element) {
|
|
|
|
@ -2287,8 +2715,8 @@ class list extends IgniteTemplate {
|
|
|
|
|
if (!this.element) {
|
|
|
|
|
this.element = window.document.createTextNode(""); //Use a textnode as our placeholder
|
|
|
|
|
|
|
|
|
|
if (sibling) {
|
|
|
|
|
sibling.parentElement.insertBefore(this.element, sibling);
|
|
|
|
|
if (sibling && sibling.nextSibling) {
|
|
|
|
|
sibling.parentElement.insertBefore(this.element, sibling.nextSibling);
|
|
|
|
|
} else {
|
|
|
|
|
parent.appendChild(this.element);
|
|
|
|
|
}
|
|
|
|
@ -2326,12 +2754,17 @@ class list extends IgniteTemplate {
|
|
|
|
|
if (this.list) {
|
|
|
|
|
for (var i = 0; i < this.list.length; i++) {
|
|
|
|
|
var template = this.forEachCallback(this.list[i], i, this.list.length);
|
|
|
|
|
|
|
|
|
|
if (template) {
|
|
|
|
|
if (this.elements.length > 0) {
|
|
|
|
|
template.construct(parent, this.elements[this.elements.length - 1]);
|
|
|
|
|
} else {
|
|
|
|
|
template.construct(parent, this.element);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//If we are reflecting, attach to the elements disconnect event.
|
|
|
|
|
if (this.reflecting) {
|
|
|
|
|
this.reflectCallbacks.push(template.element.attachOnDisconnect(disconnect => this.onItemRemove(this.list[i])));
|
|
|
|
|
this.reflectCallbacks.push(template.element.attachOnDisconnect(() => this.onItemRemove(this.list[i])));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.children.push(template);
|
|
|
|
@ -2368,7 +2801,11 @@ class list extends IgniteTemplate {
|
|
|
|
|
items.forEach(item => {
|
|
|
|
|
var template = this.forEachCallback(item, this.children.length);
|
|
|
|
|
|
|
|
|
|
if (this.elements.length > 0) {
|
|
|
|
|
template.construct(this.element.parentElement, this.elements[this.elements.length - 1]);
|
|
|
|
|
} else {
|
|
|
|
|
template.construct(this.element.parentElement, this.element);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//If we are reflecting, attach to the elements disconnect event.
|
|
|
|
|
if (this.reflecting) {
|
|
|
|
@ -2393,11 +2830,7 @@ class list extends IgniteTemplate {
|
|
|
|
|
items.forEach(item => {
|
|
|
|
|
var template = this.forEachCallback(item, 0);
|
|
|
|
|
|
|
|
|
|
if (this.elements.length > 0) {
|
|
|
|
|
template.construct(this.element.parentElement, this.elements[0]);
|
|
|
|
|
} else {
|
|
|
|
|
template.construct(this.element.parentElement, this.element);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.reflecting) {
|
|
|
|
|
this.reflectCallbacks.unshift(template.element.attachOnDisconnect(disconnect => this.onItemRemove(item)));
|
|
|
|
@ -2470,7 +2903,13 @@ class list extends IgniteTemplate {
|
|
|
|
|
items.forEach(item => {
|
|
|
|
|
var template = this.forEachCallback(item, start);
|
|
|
|
|
|
|
|
|
|
if (start == 0) {
|
|
|
|
|
template.construct(this.element.parentElement, this.element);
|
|
|
|
|
} else if (start <= this.elements.length) {
|
|
|
|
|
template.construct(this.element.parentElement, this.elements[start - 1]);
|
|
|
|
|
} else {
|
|
|
|
|
template.construct(this.element.parentElement, this.elements[this.elements.length - 1]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.reflecting) {
|
|
|
|
|
this.reflectCallbacks.splice(start, 0, template.element.attachOnDisconnect(disconnect => this.onItemRemove(item)));
|
|
|
|
@ -2503,6 +2942,173 @@ class list extends IgniteTemplate {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A special ignite template that converts a value to HTML or a Template and supports
|
|
|
|
|
* dynamic value changes and dynamic converter changes.
|
|
|
|
|
*/
|
|
|
|
|
class converter extends IgniteTemplate {
|
|
|
|
|
/**
|
|
|
|
|
* Creates a new converter with a value and a callback convert function.
|
|
|
|
|
* @param {Any|IgniteProperty|IgniteProperty[]} value
|
|
|
|
|
* @param {IgniteProperty|Function} converter
|
|
|
|
|
*/
|
|
|
|
|
constructor(value, converter) {
|
|
|
|
|
super();
|
|
|
|
|
|
|
|
|
|
if (converter instanceof IgniteProperty) {
|
|
|
|
|
this._callbacks.push(converter.attachOnChange((oldValue, newValue) => this.onConverterChanged(newValue)));
|
|
|
|
|
|
|
|
|
|
this.converter = converter.value;
|
|
|
|
|
} else if (converter instanceof Function) {
|
|
|
|
|
this.converter = converter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!this.converter) {
|
|
|
|
|
throw "A valid converter must be passed.";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (value instanceof IgniteProperty) {
|
|
|
|
|
this._callbacks.push(value.attachOnChange((oldValue, newValue) => this.onValueChanged(newValue)));
|
|
|
|
|
this._callbacks.push(value.attachOnPush((list, items) => this.onValueChanged(list)));
|
|
|
|
|
this._callbacks.push(value.attachOnUnshift((list, items) => this.onValueChanged(list)));
|
|
|
|
|
this._callbacks.push(value.attachOnPop(list => this.onValueChanged(list)));
|
|
|
|
|
this._callbacks.push(value.attachOnShift(list => this.onValueChanged(list)));
|
|
|
|
|
this._callbacks.push(value.attachOnSplice((list, start, deleteCount, items) => this.onValueChanged(list)));
|
|
|
|
|
|
|
|
|
|
this.value = value;
|
|
|
|
|
} else if (Array.isArray(value) && value.length > 0 && value[0] instanceof IgniteProperty) {
|
|
|
|
|
//Attach a callback for all the properties
|
|
|
|
|
value.forEach(prop => {
|
|
|
|
|
if (prop instanceof IgniteProperty) {
|
|
|
|
|
this._callbacks.push(prop.attachOnChange((oldValue, newValue) => this.onValueChanged(value)));
|
|
|
|
|
this._callbacks.push(prop.attachOnPush((list, items) => this.onValueChanged(value)));
|
|
|
|
|
this._callbacks.push(prop.attachOnUnshift((list, items) => this.onValueChanged(value)));
|
|
|
|
|
this._callbacks.push(prop.attachOnPop((list) => this.onValueChanged(value)));
|
|
|
|
|
this._callbacks.push(prop.attachOnShift((list) => this.onValueChanged(value)));
|
|
|
|
|
this._callbacks.push(prop.attachOnSplice((list, start, deleteCount, items) => this.onValueChanged(value)));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.value = value;
|
|
|
|
|
} else if (value) {
|
|
|
|
|
this.value = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.tagName = "converter";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constructs this template and adds it to the DOM if this template
|
|
|
|
|
* has not already been constructed.
|
|
|
|
|
* @param {HTMLElement} parent Parent element that will contain the constructed element.
|
|
|
|
|
* @param {HTMLElement} sibling Optional sibling element that can be used to add the element adjacantly.
|
|
|
|
|
*/
|
|
|
|
|
construct(parent, sibling) {
|
|
|
|
|
//Don't construct if we have no parent, no sibling and no element.
|
|
|
|
|
if (!parent && !sibling && !this.element) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!this.element) {
|
|
|
|
|
this.element = window.document.createTextNode(""); //Use a textnode as our placeholder
|
|
|
|
|
|
|
|
|
|
if (sibling && sibling.nextSibling) {
|
|
|
|
|
sibling.parentElement.insertBefore(this.element, sibling.nextSibling);
|
|
|
|
|
} else {
|
|
|
|
|
parent.appendChild(this.element);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
parent = this.element.parentElement;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//If we haven't converted the value yet, do it now
|
|
|
|
|
if (!this.converted) {
|
|
|
|
|
if (Array.isArray(this.value) && this.value.length > 0 && this.value[0] instanceof IgniteProperty) {
|
|
|
|
|
this.converted = this.converter ? this.converter(...this.value.getPropertyValues()) : this.value.getPropertyValues();
|
|
|
|
|
} else if (this.value instanceof IgniteProperty) {
|
|
|
|
|
this.converted = this.converter ? this.converter(this.value.value) : this.value.value;
|
|
|
|
|
} else {
|
|
|
|
|
this.converted = this.converter ? this.converter(this.value) : this.value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Construct the converted value
|
|
|
|
|
if (this.converted instanceof IgniteTemplate) {
|
|
|
|
|
this.converted.construct(parent, this.element);
|
|
|
|
|
} else if (Array.isArray(this.converted)) {
|
|
|
|
|
var last = this.element;
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < this.converted.length; i++) {
|
|
|
|
|
if (this.converted[i] instanceof IgniteTemplate) {
|
|
|
|
|
this.converted[i].construct(parent, last);
|
|
|
|
|
|
|
|
|
|
last = this.converted[i].element;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onValueChanged(newValue) {
|
|
|
|
|
this.value = newValue;
|
|
|
|
|
|
|
|
|
|
//Deconstruct any existing converted elements
|
|
|
|
|
if (this.converted) {
|
|
|
|
|
if (Array.isArray(this.converted)) {
|
|
|
|
|
this.converted.forEach(element => {
|
|
|
|
|
if (element instanceof IgniteTemplate) {
|
|
|
|
|
element.deconstruct();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else if (this.converted instanceof IgniteTemplate) {
|
|
|
|
|
this.converted.deconstruct();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.converted = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Convert the value using the latest converter
|
|
|
|
|
if (Array.isArray(this.value) && this.value.length > 0 && this.value[0] instanceof IgniteProperty) {
|
|
|
|
|
this.converted = this.converter ? this.converter(...this.value.getPropertyValues()) : this.value.getPropertyValues();
|
|
|
|
|
} else if (this.value instanceof IgniteProperty) {
|
|
|
|
|
this.converted = this.converter ? this.converter(this.value.value) : this.value.value;
|
|
|
|
|
} else {
|
|
|
|
|
this.converted = this.converter ? this.converter(this.value) : this.value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.construct(null, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onConverterChanged(newConverter) {
|
|
|
|
|
this.converter = newConverter;
|
|
|
|
|
|
|
|
|
|
//Deconstruct any existing converted elements
|
|
|
|
|
if (this.converted) {
|
|
|
|
|
if (Array.isArray(this.converted)) {
|
|
|
|
|
this.converted.forEach(element => {
|
|
|
|
|
if (element instanceof IgniteTemplate) {
|
|
|
|
|
element.deconstruct();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else if (this.converted instanceof IgniteTemplate) {
|
|
|
|
|
this.converted.deconstruct();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.converted = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Convert the value using the latest converter
|
|
|
|
|
if (Array.isArray(this.value) && this.value.length > 0 && this.value[0] instanceof IgniteProperty) {
|
|
|
|
|
this.converted = this.converter ? this.converter(...this.value.getPropertyValues()) : this.value.getPropertyValues();
|
|
|
|
|
} else if (this.value instanceof IgniteProperty) {
|
|
|
|
|
this.converted = this.converter ? this.converter(this.value.value) : this.value.value;
|
|
|
|
|
} else {
|
|
|
|
|
this.converted = this.converter ? this.converter(this.value) : this.value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.construct(null, null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A slot template that mimicks the functionality of a slot element in Web Components. This can
|
|
|
|
|
* be used to place children of a IgniteElement anywhere in the DOM. Slots don't actually construct an element,
|
|
|
|
@ -2547,8 +3153,8 @@ class slot extends IgniteTemplate {
|
|
|
|
|
if (!this.element) {
|
|
|
|
|
this.element = window.document.createTextNode("");
|
|
|
|
|
|
|
|
|
|
if (sibling) {
|
|
|
|
|
sibling.parentElement.insertBefore(this.element, sibling);
|
|
|
|
|
if (sibling && sibling.nextSibling) {
|
|
|
|
|
sibling.parentElement.insertBefore(this.element, sibling.nextSibling);
|
|
|
|
|
} else {
|
|
|
|
|
parent.appendChild(this.element);
|
|
|
|
|
}
|
|
|
|
@ -2735,9 +3341,18 @@ class pagination extends IgniteTemplate {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Show the elements in the current page
|
|
|
|
|
if (this.pages && this.pages.length > 0) {
|
|
|
|
|
this.pages[this.currentPage].forEach(item => item.style.removeProperty("display"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constructs this template and adds it to the DOM if this template
|
|
|
|
|
* has not already been constructed.
|
|
|
|
|
* @param {HTMLElement} parent Parent element that will contain the constructed element.
|
|
|
|
|
* @param {HTMLElement} sibling Optional sibling element that can be used to add the element adjacantly.
|
|
|
|
|
* @ignore
|
|
|
|
|
*/
|
|
|
|
|
construct(parent, sibling) {
|
|
|
|
|
//Don't construct if we have no parent, no sibling and no element.
|
|
|
|
|
if (!parent && !sibling && !this.element) {
|
|
|
|
@ -2747,8 +3362,8 @@ class pagination extends IgniteTemplate {
|
|
|
|
|
if (!this.element) {
|
|
|
|
|
this.element = window.document.createTextNode(""); //Use a textnode as our placeholder
|
|
|
|
|
|
|
|
|
|
if (sibling) {
|
|
|
|
|
sibling.parentElement.insertBefore(this.element, sibling);
|
|
|
|
|
if (sibling && sibling.nextSibling) {
|
|
|
|
|
sibling.parentElement.insertBefore(this.element, sibling.nextSibling);
|
|
|
|
|
} else {
|
|
|
|
|
parent.appendChild(this.element);
|
|
|
|
|
}
|
|
|
|
@ -3078,6 +3693,13 @@ class pager extends IgniteTemplate {
|
|
|
|
|
this.recalculate();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constructs this template and adds it to the DOM if this template
|
|
|
|
|
* has not already been constructed.
|
|
|
|
|
* @param {HTMLElement} parent Parent element that will contain the constructed element.
|
|
|
|
|
* @param {HTMLElement} sibling Optional sibling element that can be used to add the element adjacantly.
|
|
|
|
|
* @ignore
|
|
|
|
|
*/
|
|
|
|
|
construct(parent, sibling) {
|
|
|
|
|
//Don't construct if we have no parent, no sibling and no element.
|
|
|
|
|
if (!parent && !sibling && !this.element) {
|
|
|
|
@ -3087,8 +3709,8 @@ class pager extends IgniteTemplate {
|
|
|
|
|
if (!this.element) {
|
|
|
|
|
this.element = window.document.createTextNode(""); //Use a textnode as our placeholder
|
|
|
|
|
|
|
|
|
|
if (sibling) {
|
|
|
|
|
sibling.parentElement.insertBefore(this.element, sibling);
|
|
|
|
|
if (sibling && sibling.nextSibling) {
|
|
|
|
|
sibling.parentElement.insertBefore(this.element, sibling.nextSibling);
|
|
|
|
|
} else {
|
|
|
|
|
parent.appendChild(this.element);
|
|
|
|
|
}
|
|
|
|
@ -3317,6 +3939,13 @@ class population extends IgniteTemplate {
|
|
|
|
|
this.tagName = "shadow population";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constructs this template and adds it to the DOM if this template
|
|
|
|
|
* has not already been constructed.
|
|
|
|
|
* @param {HTMLElement} parent Parent element that will contain the constructed element.
|
|
|
|
|
* @param {HTMLElement} sibling Optional sibling element that can be used to add the element adjacantly.
|
|
|
|
|
* @ignore
|
|
|
|
|
*/
|
|
|
|
|
construct(parent, sibling) {
|
|
|
|
|
//Don't construct if we have no parent, no sibling and no element.
|
|
|
|
|
if (!parent && !sibling && !this.element) {
|
|
|
|
@ -3326,8 +3955,8 @@ class population extends IgniteTemplate {
|
|
|
|
|
if (!this.element) {
|
|
|
|
|
this.element = window.document.createTextNode(""); //Use a textnode as our placeholder
|
|
|
|
|
|
|
|
|
|
if (sibling) {
|
|
|
|
|
sibling.parentElement.insertBefore(this.element, sibling);
|
|
|
|
|
if (sibling && sibling.nextSibling) {
|
|
|
|
|
sibling.parentElement.insertBefore(this.element, sibling.nextSibling);
|
|
|
|
|
} else {
|
|
|
|
|
parent.appendChild(this.element);
|
|
|
|
|
}
|
|
|
|
@ -3390,6 +4019,7 @@ export {
|
|
|
|
|
text,
|
|
|
|
|
html,
|
|
|
|
|
list,
|
|
|
|
|
converter,
|
|
|
|
|
a,
|
|
|
|
|
input,
|
|
|
|
|
textarea,
|
|
|
|
@ -3409,6 +4039,7 @@ export {
|
|
|
|
|
i,
|
|
|
|
|
nav,
|
|
|
|
|
ul,
|
|
|
|
|
ol,
|
|
|
|
|
li,
|
|
|
|
|
br,
|
|
|
|
|
img,
|
|
|
|
@ -3434,5 +4065,8 @@ export {
|
|
|
|
|
line,
|
|
|
|
|
form,
|
|
|
|
|
header,
|
|
|
|
|
footer
|
|
|
|
|
footer,
|
|
|
|
|
iframe,
|
|
|
|
|
video,
|
|
|
|
|
source
|
|
|
|
|
};
|