mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
145 lines
4.9 KiB
JavaScript
145 lines
4.9 KiB
JavaScript
'use strict';
|
|
|
|
var ComponentDef = require('./ComponentDef');
|
|
var componentsUtil = require('./util');
|
|
var isServer = componentsUtil.$__isServer === true;
|
|
|
|
var EMPTY_OBJECT = {};
|
|
|
|
function GlobalComponentsContext(out) {
|
|
this.$__roots = [];
|
|
this.$__preserved = EMPTY_OBJECT;
|
|
this.$__preservedBodies = EMPTY_OBJECT;
|
|
this.$__componentsById = {};
|
|
this.$__out = out;
|
|
this.$__rerenderComponent = undefined;
|
|
this.$__nextIdLookup = null;
|
|
this.$__nextComponentId = componentsUtil.$__nextComponentIdProvider(out);
|
|
}
|
|
|
|
GlobalComponentsContext.prototype = {
|
|
$__initComponents: function(doc) {
|
|
var topLevelComponentDefs = null;
|
|
|
|
this.$__roots.forEach(function(root) {
|
|
var children = root.$__children;
|
|
if (children) {
|
|
// NOTE: ComponentsContext.$__initClientRendered is provided by
|
|
// index-browser.js to avoid a circular dependency
|
|
ComponentsContext.$__initClientRendered(children, doc);
|
|
if (topLevelComponentDefs === null) {
|
|
topLevelComponentDefs = children;
|
|
} else {
|
|
topLevelComponentDefs = topLevelComponentDefs.concat(children);
|
|
}
|
|
}
|
|
});
|
|
|
|
this.$__roots = null;
|
|
|
|
// Reset things stored in global since global is retained for
|
|
// future renders
|
|
this.$__out.global.components = undefined;
|
|
|
|
return topLevelComponentDefs;
|
|
},
|
|
$__preserveDOMNode: function(elId, bodyOnly) {
|
|
var preserved = bodyOnly === true ? this.$__preservedBodies : this.$__preserved;
|
|
if (preserved === EMPTY_OBJECT) {
|
|
if (bodyOnly === true) {
|
|
preserved = this.$__preservedBodies = {};
|
|
} else {
|
|
preserved = this.$__preserved = {};
|
|
}
|
|
}
|
|
preserved[elId] = true;
|
|
},
|
|
$__nextRepeatedId: function(parentId, id) {
|
|
var nextIdLookup = this.$__nextIdLookup || (this.$__nextIdLookup = {});
|
|
|
|
var indexLookupKey = parentId + '-' + id;
|
|
var currentIndex = nextIdLookup[indexLookupKey];
|
|
if (currentIndex == null) {
|
|
currentIndex = nextIdLookup[indexLookupKey] = 0;
|
|
} else {
|
|
currentIndex = ++nextIdLookup[indexLookupKey];
|
|
}
|
|
|
|
return indexLookupKey.slice(0, -2) + '[' + currentIndex + ']';
|
|
}
|
|
};
|
|
|
|
function ComponentsContext(out, parentComponentsContext, shouldAddGlobalRoot) {
|
|
var root;
|
|
|
|
var globalComponentsContext;
|
|
|
|
if (parentComponentsContext === undefined) {
|
|
globalComponentsContext = out.global.components;
|
|
if (globalComponentsContext === undefined) {
|
|
out.global.components = globalComponentsContext = new GlobalComponentsContext(out);
|
|
}
|
|
|
|
root = new ComponentDef(null, null, globalComponentsContext);
|
|
|
|
if (shouldAddGlobalRoot !== false) {
|
|
globalComponentsContext.$__roots.push(root);
|
|
}
|
|
} else {
|
|
globalComponentsContext = parentComponentsContext.$__globalContext;
|
|
var parentComponentStack = parentComponentsContext.$__componentStack;
|
|
root = parentComponentStack[parentComponentStack.length-1];
|
|
}
|
|
|
|
this.$__globalContext = globalComponentsContext;
|
|
this.$__out = out;
|
|
this.$__componentStack = [root];
|
|
}
|
|
|
|
ComponentsContext.prototype = {
|
|
$__createNestedComponentsContext: function(nestedOut) {
|
|
return new ComponentsContext(nestedOut, this);
|
|
},
|
|
$__beginComponent: function(component, isSplitComponent) {
|
|
var componentStack = this.$__componentStack;
|
|
var origLength = componentStack.length;
|
|
var parentComponentDef = componentStack[origLength - 1];
|
|
|
|
var componentId = component.id;
|
|
|
|
var componentDef = new ComponentDef(component, componentId, this.$__globalContext, componentStack, origLength);
|
|
if (isServer) {
|
|
// On the server
|
|
if (parentComponentDef.$__willRerenderInBrowser === true) {
|
|
componentDef.$__willRerenderInBrowser = true;
|
|
} else {
|
|
parentComponentDef.$__addChild(componentDef);
|
|
if (isSplitComponent === false && this.$__out.global.noBrowserRerender !== true) {
|
|
componentDef.$__willRerenderInBrowser = true;
|
|
}
|
|
}
|
|
} else {
|
|
parentComponentDef.$__addChild(componentDef);
|
|
this.$__globalContext.$__componentsById[componentId] = componentDef;
|
|
}
|
|
|
|
componentStack.push(componentDef);
|
|
|
|
return componentDef;
|
|
},
|
|
|
|
$__nextComponentId: function() {
|
|
var componentStack = this.$__componentStack;
|
|
var parentComponentDef = componentStack[componentStack.length - 1];
|
|
return parentComponentDef.$__nextComponentId();
|
|
}
|
|
};
|
|
|
|
function getComponentsContext(out) {
|
|
return out.data.components || (out.data.components = new ComponentsContext(out));
|
|
}
|
|
|
|
module.exports = exports = ComponentsContext;
|
|
|
|
exports.$__getComponentsContext = getComponentsContext;
|