var branchRenderer = function branchRenderer(scope, parentSectionNodeList, truthyRenderer, falseyRenderer){ // If this is within a tag, make sure we only get string values. var stringOnly = state.tag; //!steal-remove-start if (process.env.NODE_ENV !== 'production') { scope.set('scope.filename', state.filename); scope.set('scope.lineNumber', state.lineNo); } //!steal-remove-end var nodeList = [this]; nodeList.expression = expressionString; // register this nodeList. // Register it with its parent ONLY if this is directly nested. Otherwise, it's unnecessary. nodeLists.register(nodeList, null, parentSectionNodeList || true, state.directlyNested); // Get the evaluator. This does not need to be cached (probably) because if there // an observable value, it will be handled by `can.view.live`. var evaluator = makeEvaluator( scope, nodeList, mode, exprData, truthyRenderer, falseyRenderer, stringOnly ); // Create a compute that can not be observed by other // computes. This is important because this renderer is likely called by // parent expressions. If this value changes, the parent expressions should // not re-evaluate. We prevent that by making sure this compute is ignored by // everyone else. //var compute = can.compute(evaluator, null, false); var gotObservableValue = evaluator[canSymbol.for("can.onValue")]; var observable; if(gotObservableValue) { observable = evaluator; } else { //!steal-remove-start if (process.env.NODE_ENV !== 'production') { Object.defineProperty(evaluator,"name",{ value: "{{"+(mode || "")+expressionString+"}}" }); } //!steal-remove-end observable = new Observation(evaluator,null,{isObservable: false}); } if(canReflect.setPriority(observable, nodeList.nesting) === false) { throw new Error("can-stache unable to set priority on observable"); } // Bind on the computeValue to set the cached value. This helps performance // so live binding can read a cached value instead of re-calculating. canReflect.onValue(observable, k); var value = canReflect.getValue(observable); // If value is a function and not a Lookup ({{foo}}), // it's a helper that returned a function and should be called. if(typeof value === "function" && !(exprData instanceof expression.Lookup)) { // A helper function should do it's own binding. Similar to how // we prevented this function's compute from being noticed by parent expressions, // we hide any observables read in the function by saving any observables that // have been read and then setting them back which overwrites any `can.__observe` calls // performed in value. ObservationRecorder.ignore(value)(this); } // If the computeValue has observable dependencies, setup live binding. else if( canReflect.valueHasDependencies(observable) ) { // Depending on where the template is, setup live-binding differently. if(state.attr) { live.attr(this, state.attr, observable); } else if( state.tag ) { live.attrs( this, observable ); } else if(state.text && !valueShouldBeInsertedAsHTML(value)) { //!steal-remove-start if (process.env.NODE_ENV !== 'production') { if(value !== null && typeof value === "object") { dev.warn("Previously, the result of "+ expressionString+" in "+state.filename+":"+state.lineNo+ ", was being inserted as HTML instead of TEXT. Please use stache.safeString(obj) "+ "if you would like the object to be treated as HTML."); } } //!steal-remove-end live.text(this, observable, this.parentNode, nodeList); } else { live.html(this, observable, this.parentNode, { nodeList: nodeList }); } } // If the computeValue has no observable dependencies, just set the value on the element. else { if(state.attr) { domMutate.setAttribute(this, state.attr, value); } else if(state.tag) { live.attrs(this, value); } else if(state.text && !valueShouldBeInsertedAsHTML(value)) { this.nodeValue = live.makeString(value); } else if( value != null ){ if (typeof value[viewInsertSymbol] === "function") { var insert = value[viewInsertSymbol]({ nodeList: nodeList }); var oldNodes = nodeLists.update(nodeList, [insert]); nodeLists.replace(oldNodes, insert); } else { nodeLists.replace([this], frag(value, this.ownerDocument)); } } } // Unbind the compute. canReflect.offValue(observable, k); };
var outer = compute(function(){ ObservationRecorder.ignore(function(){ c(); })(); });
var partialFrag = new Observation(function(){ var localPartialName = partialName; var partialScope = scope; // If the second parameter of a partial is a custom context if(exprData && exprData.argExprs.length === 1) { var newContext = canReflect.getValue( exprData.argExprs[0].value(scope) ); if(typeof newContext === "undefined") { //!steal-remove-start if (process.env.NODE_ENV !== 'production') { dev.warn('The context ('+ exprData.argExprs[0].key +') you passed into the' + 'partial ('+ partialName +') is not defined in the scope!'); } //!steal-remove-end }else{ partialScope = scope.add(newContext); } } // Look up partials in templateContext first var partial = canReflect.getKeyValue(partialScope.templateContext.partials, localPartialName); var renderer; if (partial) { renderer = function() { return partial.render ? partial.render(partialScope, nodeList) : partial(partialScope); }; } // Use can.view to get and render the partial. else { var scopePartialName = partialScope.read(localPartialName, { isArgument: true }).value; if (scopePartialName === null || !scopePartialName && localPartialName[0] === '*') { return frag(""); } if (scopePartialName) { localPartialName = scopePartialName; } renderer = function() { if(typeof localPartialName === "function"){ return localPartialName(partialScope, {}, nodeList); } else { var domRenderer = core.getTemplateById(localPartialName); //!steal-remove-start if (process.env.NODE_ENV !== 'production') { if (!domRenderer) { dev.warn( (state.filename ? state.filename + ':' : '') + (state.lineNo ? state.lineNo + ': ' : '') + 'Unable to find partial "' + localPartialName + '".'); } } //!steal-remove-end return domRenderer ? domRenderer(partialScope, {}, nodeList) : getDocument().createDocumentFragment(); } }; } var res = ObservationRecorder.ignore(renderer)(); return frag(res); });
data: function(el, attrData) { if (domData.get.call(el, "preventDataBindings")) { return; } var viewModel, getViewModel = ObservationRecorder.ignore(function() { return viewModel || (viewModel = canViewModel(el)); }), teardown, attributeDisposal, removedDisposal, bindingContext = { element: el, templateType: attrData.templateType, scope: attrData.scope, parentNodeList: attrData.nodeList, get viewModel(){ return getViewModel(); } }; // Setup binding var dataBinding = makeDataBinding({ name: attrData.attributeName, value: el.getAttribute(attrData.attributeName), }, bindingContext, { syncChildWithParent: false }); //!steal-remove-start if (process.env.NODE_ENV !== 'production') { if (dataBinding.siblingBindingData.child.source === "viewModel" && !domData.get(el, "viewModel")) { dev.warn('This element does not have a viewModel. (Attempting to bind `' + dataBinding.siblingBindingData.bindingAttributeName + '="' + dataBinding.siblingBindingData.parent.name + '"`)'); } } //!steal-remove-end dataBinding.binding.start(); var attributeListener = function(ev) { var attrName = ev.attributeName, value = el.getAttribute(attrName); if (attrName === attrData.attributeName) { if (teardown) { teardown(); } if(value !== null ) { var dataBinding = makeDataBinding({name: attrName, value: value}, bindingContext, { syncChildWithParent: false }); if(dataBinding) { // The viewModel is created, so call callback immediately. dataBinding.binding.start(); teardown = dataBinding.binding.stop.bind(dataBinding.binding); } teardown = dataBinding.onTeardown; } } }; var tearItAllDown = function() { if (teardown) { teardown(); teardown = undefined; } if (removedDisposal) { removedDisposal(); removedDisposal = undefined; } if (attributeDisposal) { attributeDisposal(); attributeDisposal = undefined; } }; if (attrData.nodeList) { ViewNodeList.register([], tearItAllDown, attrData.nodeList, false); } // Listen for changes teardown = dataBinding.binding.stop.bind(dataBinding.binding); attributeDisposal = domMutate.onNodeAttributeChange(el, attributeListener); removedDisposal = domMutate.onNodeRemoval(el, function() { var doc = el.ownerDocument; var ownerNode = doc.contains ? doc : doc.documentElement; if (!ownerNode || ownerNode.contains(el) === false) { tearItAllDown(); } }); },