コード例 #1
0
ファイル: mustache_core.js プロジェクト: canjs/can-stache
		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);
		};
コード例 #2
0
ファイル: can-compute_test.js プロジェクト: canjs/can-compute
	var outer = compute(function(){
		ObservationRecorder.ignore(function(){
			c();
		})();
	});
コード例 #3
0
ファイル: mustache_core.js プロジェクト: canjs/can-stache
			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);
			});
コード例 #4
0
	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();
			}
		});
	},