<form id='attendee'></form>
<pre id='out'></pre>
<button id='ba'>Payal's Grandmother Preset</button>
<script id='attendeeMustache' type='text/mustache'>
<p id='attending'>
Can you make it?
<input value="yes" type="radio" id="available" {{checked attendee.attending}}/>
<label for='available'>Yes</label>
<input value="no" type="radio" id='notavailable' {{checked attendee.attending}}/>
<label for='notavailable'>No</label>.
</p>
<p>
<input name="name" {{value attendee.name}} {{placeholder "name" attendee.name}}/>
</p>
<div id='address' {{fadeInWhen attending}}>
<p id='country'>
Country:</br>
<input name="country" value="USA" type="radio" id='usa' {{checked attendee.country}} />
<label for='usa'>USA</label>
<input name="country" value="India" type="radio" id='india' {{checked attendee.country}}/>
<label for='india'>India</label>
<input name="country" value="Canada" type="radio" id='canada' {{checked attendee.country}}/>
<label for='canada'>Canada</label>
</p>
<div id='street'>
<p>
<input name="street" {{value attendee.street}} {{placeholder "street" attendee.street}}/>
<input name="apt" {{value attendee.apt}} {{placeholder "apt" attendee.apt}}/>
</p>
<p id='location-units'>
<input name="city"
{{value attendee.city}}
{{fadeInWhen cityOrStateSetOrCountryNotUSA}}
{{placeholder "city" attendee.city}}/>
<input name="state"
{{value attendee.state}}
{{fadeInWhen cityOrStateSetOrCountryNotUSA}}
{{placeholder statePlaceholder attendee.state}}/>
<input name="zip"
{{value attendee.zip}}
{{placeholder zipPlaceholder attendee.zip}}/>
</p>
</div>
</div>
</script>
setupMustacheHelpers()
var attendee = new can.Observe({
country: "USA"
}),
placeholders = {
usa: {
state: "state",
zip: "zip code"
},
india: {
state: "state",
zip: "postal code"
},
canada: {
state: "province",
zip: "postal code"
}
},
countryPlaceholders = function(){
return placeholders[(attendee.attr('country')).toLowerCase()]
};
$("#attendee").html( can.view("attendeeMustache", {
attendee: attendee,
statePlaceholder: can.compute(function(){
return countryPlaceholders().state
}),
zipPlaceholder: can.compute(function(){
return countryPlaceholders().zip
}),
cityOrStateSetOrCountryNotUSA: can.compute(function(){
return attendee.attr('state') ||
attendee.attr('city') ||
( attendee.attr('country') &&
attendee.attr('country') !== "USA" );
}),
attending: can.compute(function(){
console.log("re-eval");
return attendee.attr('attending') === 'yes'
})
}));
attendee.bind("change", function(){
$("#out").text( JSON.stringify( attendee.attr() ).replace(/,/g,",\n ") );
})
$("#ba").click(function(){
attendee.attr({
name: "Payal's Grandmother",
attending: "yes",
country: "India",
street: "1234 Punjab St",
apt: "4u",
city: "Hyderabad",
state: "Andhra Pradesh",
zip: "500001"
})
})
function setupMustacheHelpers() {
var placeholderSupported = false// "placeholder" in document.createElement("input");
// Adds a placeholder for browsers that don't support it
Placeholder = can.Control({
init: function(element, options) {
if( placeholderSupported ) {
this.element.attr('placeholder', this.options.placeholder() );
} else {
if( this.element.val() === '' ) {
this.addPlaceholder();
} else {
this.changed = true;
}
}
},
addPlaceholder: function(){
this.element.val(this.options.placeholder())
.addClass('placeholder');
this.changed = false;
},
removePlaceholder: function(){
this.element.val("").removeClass('placeholder');
},
'focus': function(el, ev) {
if( ! placeholderSupported && !this.changed ) {
if( this.element.val() === this.options.placeholder() ) {
this.removePlaceholder();
}
}
},
'blur': function(){
if( !placeholderSupported ) {
if( this.element.val() === '' ) {
this.addPlaceholder();
}
}
},
"{value} change": function(value, ev, newVal, oldVal){
if( !placeholderSupported && newVal) {
this.element.removeClass('placeholder');
}
},
"{placeholder} change": function(placeholder, ev, newVal, oldVal){
if( placeholderSupported ) {
this.element.attr('placeholder', newVal)
} else {
if( !this.changed && !this.isFocused() ) {
this.element.val(newVal);
}
}
},
"change" : function(){
this.changed = (this.element.val() !== "");
},
isFocused: function(){
return document.activeElement === this.element[0];
}
});
can.Mustache.registerHelper('placeholder', function(placeholder, value){
return function(el){
if(typeof placeholder === "string"){
placeholder = can.compute(placeholder);
}
new Placeholder(el, {
placeholder: placeholder,
value: value
});
}
});
// adds a checked property if value matches the value
// of the current element
var Checked = can.Control({
init: function(){
this.check()
},
"{value} change": "check",
check: function(){
if(this.options.value() === this.element.val()){
this.element.prop("checked", true)
} else {
this.element.prop("checked", false)
}
},
"change": function(){
if(this.element.is(":checked")){
this.options.value(this.element.val())
}
}
})
can.Mustache.registerHelper('checked', function(value){
return function(el){
new Checked(el, {value: value});
}
});
// 2-way binds an element and value
var Value = can.Control({
init: function(){
this.set()
},
"{value} change": "set",
set: function(){
this.element.val(this.options.value())
},
"change": function(){
this.options.value(this.element.val())
}
});
can.Mustache.registerHelper('value', function(value){
return function(el){
new Value(el, {value: value});
}
});
// Fades an element in when a value is truthy
var FadeInWhen = can.Control({
init: function(){
if(this.options.value()){
this.element.show();
} else {
this.element.hide()
}
},
"{value} change": function(value, ev, newVal){
if( newVal ) {
this.element.fadeIn();
} else {
this.element.hide()
}
}
});
can.Mustache.registerHelper('fadeInWhen', function(value){
return function(el){
console.log("fadeInWhen",el,value())
new FadeInWhen(el, {value: value});
}
});
};