From 488a1682162968f87396d8a9471d55a5d260a1b2 Mon Sep 17 00:00:00 2001 From: Jelle De Loecker Date: Mon, 29 Apr 2024 17:15:36 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Clean=20up=20custom=20elem?= =?UTF-8?q?ent=20`renderCustomTemplate`=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + lib/element/custom_element.js | 130 +++++++++++++++++++++++----------- 2 files changed, 88 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51c0f69..3ae78da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * Refactor variable access in compiled template code * Only clone certain variables once, when they are initially set * Prepare text nodes during compiling +* Clean up custom element `renderCustomTemplate` function ## 2.3.19 (2024-04-13) diff --git a/lib/element/custom_element.js b/lib/element/custom_element.js index 59ab4fc..4c0468d 100644 --- a/lib/element/custom_element.js +++ b/lib/element/custom_element.js @@ -969,34 +969,26 @@ function addTemplateRenderer(element_class) { * * @author Jelle De Loecker * @since 2.0.0 - * @version 2.3.17 + * @version 2.4.0 * - * @param {Boolean} re_render Is this a render done from outside a normal render? + * @param {boolean} re_render Is this a render done from outside a normal render? */ function renderCustomTemplate(re_render) { - let template = this.inner_template, - has_prepare_logic = typeof this.prepareRenderVariables == 'function'; - // Get the private map let private_map = getPrivate(this); // And clear the element cache private_map.cached_elements.clear(); + // Get the template of this custom element + const template = this.inner_template; + if (!template) { return this.prepareRenderVariables(); } - let that = this, - render_vars, - renderer = this.ensureHawkejsRenderer(); - - if (this.constructor.use_new_renderer_scope || renderer?.dialog_open) { - renderer = renderer.createSubRenderer(); - renderer.scope_id = renderer.getId(); - } - + // Get the optional slot data let slot_data = _extractSlotData.call(this, true, re_render); // If there already is a render in progress, resolve it @@ -1007,8 +999,8 @@ function renderCustomTemplate(re_render) { let pledge = new Classes.Pledge.Swift(); this[CURRENT_RENDER] = pledge; - const doEarlyResolve = value => pledge.resolve(value), - alreadyDone = () => this[CURRENT_RENDER] != pledge || pledge.is_done; + // The render variables will go here + let variables; Hawkejs.series(next => { @@ -1019,44 +1011,97 @@ function renderCustomTemplate(re_render) { } else { next(); } - }, function getRenderVariables(next) { + }, next => { - if (!has_prepare_logic) { + if (typeof this.prepareRenderVariables != 'function') { return next(); } - Classes.Pledge.Swift.done(that.prepareRenderVariables(), (err, result) => { + Classes.Pledge.Swift.done(this.prepareRenderVariables(), (err, result) => { if (err) { return next(err); } - render_vars = Hawkejs.Variables.cast(result, renderer); - render_vars = Bound.JSON.clone(render_vars, 'toHawkejs'); - + variables = result; next(); }); - }, function renderTemplate(next) { + }, err => { - if (alreadyDone()) { - doEarlyResolve(false); - return; + if (err) { + return pledge.reject(err); + } + + try { + renderContentsWithTemplate(this, template, variables, slot_data, pledge); + } catch (err) { + pledge.reject(err); + } + }); + + return pledge; +} + +/** + * Render the contents of the given element using the provided template + * + * @author Jelle De Loecker + * @since 2.4.0 + * @version 2.4.0 + * + * @param {HTMLElement} element + * @param {Hawkejs.Template} template + * @param {Hawkejs.Variables} [variables] + * @param {Object} [slot_data] + * @param {Pledge} [pledge] + */ +function renderContentsWithTemplate(element, template, variables, slot_data, pledge) { + + // See if the element has already finished rendering, somehow + const alreadyDone = () => element[CURRENT_RENDER] != pledge || pledge.is_done; + + if (pledge && alreadyDone()) { + pledge.resolve(false); + return pledge; + } + + let renderer = Element.prototype.ensureHawkejsRenderer.call(element); + + if (element.constructor.use_new_renderer_scope || renderer?.dialog_open) { + renderer = renderer.createSubRenderer(); + renderer.scope_id = renderer.getId(); } - if (!render_vars) { - render_vars = new Hawkejs.Variables(renderer); + if (!pledge) { + pledge = new Classes.Pledge.Swift(); + + if (element[CURRENT_RENDER]) { + // If there already is a render in progress, resolve it + element[CURRENT_RENDER].resolve(false); } + } + + element[CURRENT_RENDER] = pledge; + + // Finish the rendering early + const doEarlyResolve = value => pledge.resolve(value); - if (that[Hawkejs.VARIABLES]) { - render_vars = Hawkejs.Variables.cast(that[Hawkejs.VARIABLES], renderer).overlay(render_vars); + if (element[Hawkejs.VARIABLES]) { + variables = element[Hawkejs.VARIABLES].overlay(variables); + } else { + variables = renderer.prepareVariables(variables); } - render_vars.setFromTemplate('self', that); - render_vars.setFromTemplate('child_nodes', slot_data.child_nodes); - render_vars.setFromTemplate('$ancestor_element', that); + if (slot_data) { + variables.setFromTemplate('self', element); + variables.setFromTemplate('child_nodes', slot_data.child_nodes); + } - renderer.renderTemplate(template, render_vars, String(render_counter++)).done(next); - }, function assembleBlock(next, template) { + variables.setFromTemplate('$ancestor_element', element); + + Hawkejs.series(next => { + renderer.renderTemplate(template, variables, String(render_counter++)).done(next); + }, (next, template) => { if (alreadyDone()) { doEarlyResolve(false); @@ -1070,8 +1115,7 @@ function renderCustomTemplate(re_render) { if (Blast.isBrowser) { hawkejs.scene.handleRendererStyles(renderer); } - - }, function assembledBlock(next, block) { + }, (next, block) => { if (alreadyDone()) { doEarlyResolve(false); @@ -1082,17 +1126,17 @@ function renderCustomTemplate(re_render) { i; for (i = 0; i < nodes.length; i++) { - that.append(nodes[i]); + element.append(nodes[i]); } - _insertSlotData.call(that, slot_data); + _insertSlotData.call(element, slot_data); - if (typeof that.renderedTemplate == 'function') { - that.renderedTemplate(); + if (typeof element.renderedTemplate == 'function') { + element.renderedTemplate(); } next(); - }, function resolved(err) { + }, err => { if (alreadyDone()) { doEarlyResolve(false); @@ -1100,7 +1144,7 @@ function renderCustomTemplate(re_render) { } try { - _finishRender.call(that, err); + _finishRender.call(element, err); } catch (_err) { return pledge.reject(_err); }