suite "Placeholders", ()->
	test "Property names with periods (.) indicate a placeholder", ()->
		dispatcher = 'value': 'Medium'

		objectA.prop = 'The size of this shirt is {{size}}, man!'
		if isBrowser
			inputA.value = 'The size of this shirt is {{size}}, man!'
			regA.textContent = 'The size of this shirt is {{size}}, man!'
			regA.setAttribute 'someattr', 'The size of this shirt is {{size}}, man!'

		SimplyBind('value').of(dispatcher)
			.to('prop.size').of(objectA)

		if isBrowser
			SimplyBind('value').of(dispatcher)
				.to('value.size').of(inputA)
				.and.to('textContent.size').of(regA)
				.and.to('attr:someattr.size').of(regA)
			
		expect(objectA.prop).to.equal 'The size of this shirt is Medium, man!'
		if isBrowser
			expect(inputA.value).to.equal 'The size of this shirt is Medium, man!'
			expect(regA.textContent).to.equal 'The size of this shirt is Medium, man!'
			expect(regA.getAttribute 'someattr').to.equal 'The size of this shirt is Medium, man!'
		restartSandbox()
	


	test "No changes should be made to the string when trying to update a placeholder that doesn't exist", ()->
		objectB.prop1 = 'The size of this shirt is _____, man!'
		binding = SimplyBind('prop1').of(objectA).to('prop1.size').of(objectB)

		binding.set 'Medium'
		expect(objectB.prop1).to.equal 'The size of this shirt is _____, man!'
		restartSandbox()



	test "The updating value doesn't have to be a string", ()->
		objectB.prop1 = 'The size of this shirt is {{size}}, man!'
		binding = SimplyBind('prop1').of(objectA).to('prop1.size').of(objectB)
		binding.set false
		expect(objectB.prop1).to.equal 'The size of this shirt is false, man!'
		binding.set null
		expect(objectB.prop1).to.equal 'The size of this shirt is null, man!'
		binding.set {}
		expect(objectB.prop1).to.equal 'The size of this shirt is [object Object], man!'

		restartSandbox()



	test "If a property name has more than one period, only the first will be accounted for", ()->
		objectB.prop1 = 'The size of this shirt is {{size.redundant}}, man!'
		binding = SimplyBind('prop1').of(objectA).to('prop1.size.redundant').of(objectB)
		
		binding.set 'Medium'
		expect(objectB.prop1).to.equal 'The size of this shirt is Medium, man!'
		restartSandbox()



	test "Custom placeholder markers can be set", ()->
		SimplyBind.settings.placeholder = ['^^', '$$']
		
		objectB.prop1 = 'The size of this shirt is ^^size$$, man!'
		
		binding = SimplyBind('prop1').of(objectA).to('prop1.size').of(objectB)
		binding.set 'XXS'
		
		expect(objectB.prop1).to.equal 'The size of this shirt is XXS, man!'
		SimplyBind.settings.placeholder = ['{{', '}}']

		restartSandbox()



	test "Target strings can have multiple placeholders", ()->
		dispatcher = 'value': 'Large'

		objectA.prop = 'The size of this shirt is {{size}}, and {{size}} is {{size}}ly rad!'
		if isBrowser
			inputA.value = 'The size of this shirt is {{size}}, and {{size}} is {{size}}ly rad!'
			regA.textContent = 'The size of this shirt is {{size}}, and {{size}} is {{size}}ly rad!'
			regA.setAttribute 'someattr', 'The size of this shirt is {{size}}, and {{size}} is {{size}}ly rad!'

		SimplyBind('value').of(dispatcher)
			.to('prop.size').of(objectA)

		if isBrowser
			SimplyBind('value').of(dispatcher)
				.to('value.size').of(inputA)
				.and.to('textContent.size').of(regA)
				.and.to('attr:someattr.size').of(regA)
		
		expect(objectA.prop).to.equal 'The size of this shirt is Large, and Large is Largely rad!'
		if isBrowser
			expect(inputA.value).to.equal 'The size of this shirt is Large, and Large is Largely rad!'
			expect(regA.textContent).to.equal 'The size of this shirt is Large, and Large is Largely rad!'
			expect(regA.getAttribute 'someattr').to.equal 'The size of this shirt is Large, and Large is Largely rad!'
		restartSandbox()




	test "Multiple values can be set for the same target that has multiple placeholders", ()->
		dispatcher =
			'verb': 'not'
			'nounOne': 'small'
			'nounTwo': 'pretty'

		objectB.prop = 'The following text is {{verb}} {{nounOne}} and {{nounTwo}}'
		if isBrowser
			inputB.value = 'The following text is {{verb}} {{nounOne}} and {{nounTwo}}'
			regB.setAttribute 'someattr', 'The following text is {{verb}} {{nounOne}} and {{nounTwo}}'

		SimplyBind('verb').of(dispatcher)
			.to('prop.verb').of(objectB)
		
		if isBrowser
			SimplyBind('verb').of(dispatcher)
				.to('value.verb').of(inputB)
				.and.to('textContent.verb').of(regB)
				.and.to('attr:someattr.verb').of(regB)
		


		SimplyBind('nounOne').of(dispatcher)
			.to('prop.nounOne').of(objectB)
		
		if isBrowser
			SimplyBind('nounOne').of(dispatcher)
				.to('value.nounOne').of(inputB)
				.and.to('textContent.nounOne').of(regB)
				.and.to('attr:someattr.nounOne').of(regB)
		


		SimplyBind('nounTwo').of(dispatcher)
			.to('prop.nounTwo').of(objectB)
		
		if isBrowser
			SimplyBind('nounTwo').of(dispatcher)
				.to('value.nounTwo').of(inputB)
				.and.to('textContent.nounTwo').of(regB)
				.and.to('attr:someattr.nounTwo').of(regB)
		

		values = ()-> if not isBrowser then [objectB.prop] else [objectB.prop, inputB.value, regB.textContent, regB.getAttribute 'someattr']
		for value in values()
			expect(value).to.equal 'The following text is not small and pretty'



		dispatcher.verb = 'very'
		dispatcher.nounOne = 'big'
		dispatcher.nounTwo = 'ugly'
		for value in values()
			expect(value).to.equal 'The following text is very big and ugly'


		restartSandbox()




	test "Multiple values can be set for the same target that has multiple placeholders + transforms", ()->
		dispatcher =
			'verbOne': 'not'
			'verbTwo': 'not'
			'nounOne': 'small'
			'nounTwo': 'pretty'

		objectC.prop = 'The following text is {{verbOne}} ({{verbTwo}}) {{nounOne}} and {{nounTwo}}'
		if isBrowser
			inputC.value = 'The following text is {{verbOne}} ({{verbTwo}}) {{nounOne}} and {{nounTwo}}'
			regC.textContent = 'The following text is {{verbOne}} ({{verbTwo}}) {{nounOne}} and {{nounTwo}}'
			regC.setAttribute 'someattr', 'The following text is {{verbOne}} ({{verbTwo}}) {{nounOne}} and {{nounTwo}}'



		SimplyBind('verbOne').of(dispatcher)
			.to('prop.verbOne').of(objectC).transform (value)-> value.toUpperCase()

		if isBrowser
			SimplyBind('verbOne').of(dispatcher)
				.to('value.verbOne').of(inputC)
				.and.to('textContent.verbOne').of(regC)
				.and.to('attr:someattr.verbOne').of(regC)
				.transformAll (value)-> value.toUpperCase()



		SimplyBind('verbTwo').of(dispatcher)
			.to('prop.verbTwo').of(objectC).transform (value)-> value.toLowerCase()

		if isBrowser
			SimplyBind('verbTwo').of(dispatcher)
				.to('value.verbTwo').of(inputC)
				.and.to('textContent.verbTwo').of(regC)
				.and.to('attr:someattr.verbTwo').of(regC)
				.transformAll (value)-> value.toLowerCase()
		


		SimplyBind('nounOne').of(dispatcher)
			.to('prop.nounOne').of(objectC).transform (value)-> value.toUpperCase()

		if isBrowser
			SimplyBind('nounOne').of(dispatcher)
				.to('value.nounOne').of(inputC)
				.and.to('textContent.nounOne').of(regC)
				.and.to('attr:someattr.nounOne').of(regC)
				.transformAll (value)-> value.toUpperCase()
		


		SimplyBind('nounTwo').of(dispatcher)
			.to('prop.nounTwo').of(objectC).transform (value)-> value.toUpperCase()

		if isBrowser
			SimplyBind('nounTwo').of(dispatcher)
				.to('value.nounTwo').of(inputC)
				.and.to('textContent.nounTwo').of(regC)
				.and.to('attr:someattr.nounTwo').of(regC)
				.transformAll (value)-> value.toUpperCase()
		


		values = ()-> if not isBrowser then [objectC.prop] else [objectC.prop, inputC.value, regC.textContent, regC.getAttribute 'someattr']
		for value in values()
			expect(value).to.equal 'The following text is NOT (not) SMALL and PRETTY'


		dispatcher.verbOne = dispatcher.verbTwo = 'Very'
		dispatcher.nounOne = 'Big'
		dispatcher.nounTwo = 'Ugly'
		for value in values()
			expect(value).to.equal 'The following text is VERY (very) BIG and UGLY'


		restartSandbox()




	test "Multiple placeholder bindings to textContent with multiple placeholders in a single textNode containing nested placeholders should function properly", ()-> if not isBrowser then @skip() else
		dispatcher = 'wordA':'', 'wordB':''

		expect(regD.textContent).to.equal 'The following {{wordA}} and {{wordB}} replaced correctly'

		SimplyBind('wordA').of(dispatcher)
			.to('textContent.wordA').of(regD)

		SimplyBind('wordB').of(dispatcher)
			.to('textContent.wordB').of(regD)

		expect(regD.textContent).to.equal 'The following  and  replaced correctly'


		dispatcher.wordA = 'firstWord'
		dispatcher.wordB = 'secondWord'
		expect(regD.textContent).to.equal 'The following firstWord and secondWord replaced correctly'
		restartSandbox()



	test "A single publisher can bind to more than 1 placeholder in a subscriber", ()->
		dispatcher = 'prop':'value'
		receiver = 'prop':'{{first}} {{second}}'

		SimplyBind('prop').of(dispatcher)
			.to('prop.first').of(receiver)
			.and.to('prop.second').of(receiver)

		expect(receiver.prop).to.equal 'value value'

		dispatcher.prop = 'anotherValue'
		expect(receiver.prop).to.equal 'anotherValue anotherValue'



	test "A single publisher can bind to more than 1 placeholder in a subscriber + transforms", ()->
		dispatcher = 'prop':'VaLuE'
		receiver = 'prop':'{{first}} {{second}}'

		SimplyBind('prop').of(dispatcher)
			.to('prop.first').of(receiver).transform (value)-> value.toLowerCase()
			.and.to('prop.second').of(receiver).transform (value)-> value.toUpperCase()

		expect(receiver.prop).to.equal 'value VALUE'

		dispatcher.prop = 'anotherValue'
		expect(receiver.prop).to.equal 'anothervalue ANOTHERVALUE'



	test "When an object prop with placeholders is an updater, it can either update individual placeholder values or its entire value", ()->
		dispatcher = 'nounA':'color', 'nounB':'car', 'adverb':'very', 'color':'red'
		receiver = 'prop':'The {{nounA}} of this {{nounB}} is {{adverb}} {{color}}'
		lastReceiver = 'prop':''

		SimplyBind('nounA').of(dispatcher).to('prop.nounA').of(receiver)
		SimplyBind('nounB').of(dispatcher).to('prop.nounB').of(receiver)
		SimplyBind('adverb').of(dispatcher).to('prop.adverb').of(receiver)
		SimplyBind('color').of(dispatcher).to('prop.color').of(receiver)
		expect(receiver.prop).to.equal 'The color of this car is very red'
		
		SimplyBind('prop.nounA').of(receiver)
			.to('prop').of(lastReceiver)

		expect(lastReceiver.prop).to.equal 'color'
		dispatcher.nounA = 'colour'
		expect(lastReceiver.prop).to.equal 'colour'


		SimplyBind('prop.nounB').of(receiver)
			.to('prop').of(lastReceiver)

		expect(lastReceiver.prop).to.equal 'car'
		dispatcher.nounB = 'airplane'
		expect(lastReceiver.prop).to.equal 'airplane'


		SimplyBind('prop').of(receiver)
			.to('prop').of(lastReceiver)

		expect(lastReceiver.prop).to.equal 'The colour of this airplane is very red'




	test "When manually changing the value of the prop after binding, the application of the placeholders will ignore the changes", ()-> if not isBrowser then @skip() else
		dispatcher = 'verb':'', 'nounOne':'', 'nounTwo':''
		objectA.prop1 = regB.textContent

		SimplyBind('verb').of(dispatcher)
			.to('prop1.verb').of(objectA)
			.and.to('textContent.verb').of(regB)
		
		SimplyBind('nounOne').of(dispatcher)
			.to('prop1.nounOne').of(objectA)
			.and.to('textContent.nounOne').of(regB)
		
		SimplyBind('nounTwo').of(dispatcher)
			.to('prop1.nounTwo').of(objectA)
			.and.to('textContent.nounTwo').of(regB)

		dispatcher.verb = 'looking'
		dispatcher.nounOne = 'nice'
		dispatcher.nounTwo = 'long'
		expect(objectA.prop1).to.equal 'The following text is looking nice and long'
		expect(objectA.prop1).to.equal(regB.textContent)


		upperCaseNodes = (nodes)-> for node in nodes
			if node.nodeType is 3
				node.textContent = node.textContent.toUpperCase()
			else
				upperCaseNodes(node)
		
		upperCaseNodes(regB.childNodes)
		objectA.prop1 = 'modified'
		
		dispatcher.verb = 'not looking'
		dispatcher.nounOne = 'ugly'
		dispatcher.nounTwo = 'short'
		expect(objectA.prop1).to.equal 'The following text is not looking ugly and short'
		expect(objectA.prop1).to.equal(regB.textContent)

		# But new text nodes won't be replaced!
		$regBH1.append '<span> and some other attribute</span>'
		dispatcher.verb = 'looking'
		dispatcher.nounOne = 'nice'
		dispatcher.nounTwo = 'long'
		expect(objectA.prop1).to.equal 'The following text is looking nice and long'
		expect(regB.textContent).to.equal 'The following text is looking nice and long and some other attribute'




	test "DOM Elements that contain textContent placeholders that encapsulate the entire textNode will behave normally", ()-> if not isBrowser then @skip() else
		regA.innerHTML = 'This <span>{{placeholder}}</span> is separated from others'
		expect(regA.textContent).to.equal 'This {{placeholder}} is separated from others'

		SimplyBind('prop').of(objectA)
			.to('textContent.placeholder').of(regA)

		objectA.prop = 'word'
		expect(regA.textContent).to.equal 'This word is separated from others'
		restartSandbox()

