Created
November 7, 2011 17:13
-
-
Save dkullmann/1345555 to your computer and use it in GitHub Desktop.
Mustache Iteration Example w/Backbone and an array of objects
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
jQuery(function() { | |
var Property = Backbone.Model.extend({ | |
/** | |
* Primary key-like ID for each model | |
*/ | |
idAttribute: 'ListingKey', | |
/** | |
* Default attributes for each model | |
*/ | |
defaults: { | |
/** | |
* Tabs for the 'Features' section, in order | |
*/ | |
featureTabs: [ 'interior', 'exterior', 'utilities', 'development', 'additional' ], | |
/** | |
* Settings for the 'Features' section of the 'Details' tab | |
* An ordered list of key value pairs | |
*/ | |
featureFields: { | |
interior: [ | |
{ 'Rooms':'Rooms' }, | |
{ 'Bedroom Features':'BedroomFeatures' }, | |
{ 'Bathroom Features':'BathroomFeatures' }, | |
{ 'Full Baths':'BathFull' }, | |
{ '3/4 Baths':'BathThreeQuarter' }, | |
{ 'Half Baths':'BathHalf' }, | |
{ '1/4 Baths':'BathQuarter' }, | |
{ 'Kitchen Features':'KitchenFeatures' }, | |
{ 'Cooking Appliances':'CookingAppliances' }, | |
{ 'Appliances':'Appliances' }, | |
{ 'Eating Areas':'EatingAreas' }, | |
{ 'Interior Features':'InteriorFeatures' }, | |
{ 'Fireplace Rooms':'FireplaceRooms' }, | |
{ 'Fireplace Features':'FireplaceFeatures' }, | |
{ 'Fireplace Fuel':'FirePlaceFuel' }, | |
{ 'Floor Material':'FloorMaterial' }, | |
{ 'Doors':'Doors' }, | |
{ 'Windows':'Windows' }, | |
{ 'Laundry Locations':'LaundryLocations' }, | |
{ '# of Remote Controls':'NumberOfRemoteControls' } | |
], | |
exterior: [ | |
{ 'Exterior Construction':'ExteriorConstruction' }, | |
{ 'Building Structure Style':'BuildingStructureStyle' }, | |
{ 'Other Structural Features':'OtherStructuralFeatures' }, | |
{ 'Common Walls':'CommonWalls' }, | |
{ 'Building Size':'BuildingSize' }, | |
{ 'Disability Access':'DisabilityAccess' }, | |
{ 'Foundation Details':'FoundationDetails' }, | |
{ 'Roofing':'Roofing' }, | |
{ 'Fence':'Fence' }, | |
{ 'Patio Features':'PatioFeatures' }, | |
{ 'Sprinklers':'Sprinklers' }, | |
{ 'Security/Safety':'SecuritySafety' }, | |
{ 'Spa Descriptions':'SpaDescriptions' }, | |
{ 'Spa Construction':'SpaConstruction' }, | |
{ 'Pool Descriptions':'PoolDescriptions' }, | |
{ 'Pool Construction':'PoolConstruction' }, | |
{ 'Pool Accessories':'PoolAccessories' }, | |
{ 'Parking Spaces Total':'ParkingSpacesTotal' }, | |
{ 'Parking Type':'ParkingType' }, | |
{ 'Parking Features':'ParkingFeatures' }, | |
{ 'Garage Spaces Total':'GarageSpacesTotal' }, | |
{ 'Covered Spaces Total':'CoveredSpacesTotal' }, | |
{ 'Carport Spaces Total':'CarportSpacesTotal' }, | |
{ 'Open Other Spaces Total':'OpenOtherSpacesTotal' }, | |
{ 'RV Access Dimensions':'RVAccessDimensions' }, | |
{ 'Lot Description':'LotDescription' }, | |
{ 'Lot Size Acres':'LotSizeAcres' }, | |
{ 'Lot Size Description':'LotSizeDimensionDescription' }, | |
{ 'Lot Location':'LotLocation' }, | |
{ 'View':'View' } | |
], | |
utilities: [ | |
{ 'Water District':'WaterDistrict' }, | |
{ 'Water':'Water' }, | |
{ 'Water Heater Features':'WaterHeaterFeatures' }, | |
{ 'Sewer':'Sewer' }, | |
{ 'Cooling Type':'CoolingType' }, | |
{ 'Heating Type':'HeatingType' }, | |
{ 'Heating Fuel':'HeatingFuel' }, | |
{ '220 Volt Locations':'Volt220Locations' }, | |
{ 'TV Services':'TVServices' } | |
], | |
development: [ | |
{ 'Total Units':'UnitsTotalInComplex' }, | |
{ 'Unit Floor in Building':'UnitFloorInBuilding' }, | |
{ 'Unit Location':'UnitLocation' }, | |
{ 'Mid-High Rise Amenities':'HighMidRiseAmenities' }, | |
{ 'HOA Fees':'HOAFee1' }, | |
{ 'HOA Fee Frequency':'HOAFeeFrequency1' }, | |
{ 'HOA Fees 2':'HOAFee2' }, | |
{ 'HOA Fees 2 Frequency':'HOAFeeFrequency2' }, | |
{ 'Other Association Fees':'OtherAssociationFees' }, | |
{ 'Association Fees Include':'AssociationFeesInclude' }, | |
{ 'Association Amenities':'AssociationAmenities' }, | |
{ 'Association Rules':'AssociationRules' }, | |
{ 'Association Name':'AssociationName' }, | |
{ 'Inclusions':'Inclusions' }, | |
{ 'Community Features':'CommunityFeatures' }, | |
{ 'Playing Courts':'PlayingCourts' }, | |
{ 'Mello Roos Tax':'TaxMelloRoos' }, | |
{ 'Builders Name':'BuildersName' }, | |
{ 'Builders Model Name':'BuildersModelName' }, | |
{ 'Builders Tract Name':'BuildersTractName' }, | |
{ 'Builders Tract Code':'BuildersTractCode' }, | |
{ 'Tax Parcel Number':'TaxParcelNumber' }, | |
{ 'Tax Legal Lot Number':'TaxLegalLotNumber' }, | |
{ 'Tax Legal Tract Number':'TaxLegalTractNumber' }, | |
{ 'Zoning':'Zoning' } | |
], | |
additional: [ | |
{ 'Original List Price':'OriginalListPrice' }, | |
{ 'Driving Directions':'DrivingDirections' }, | |
{ 'Cross Streets':'CrossStreets' }, | |
{ 'Thomas Guide':'ThomasGuideFullMapString' }, | |
{ 'Area':'Area' }, | |
{ 'Area Other':'AreaOther' }, | |
{ 'City Other':'CityOther' }, | |
{ 'School District':'SchoolDistrict' }, | |
{ 'High School':'HighSchool' }, | |
{ 'Junior/Middle School':'JuniorMiddleSchool' }, | |
{ 'Elementary School':'ElementarySchool' }, | |
{ 'Stories':'Stories' }, | |
{ 'Total Floors':'TotalFloors' }, | |
{ 'Entry Floor Number':'EntryFloorNumber' }, | |
{ 'Entry Location':'EntryLocation' }, | |
{ 'Other Structures':'OtherStructures' }, | |
{ 'Property Condition':'PropertyCondition' }, | |
{ 'Property Faces Direction':'DirectionFaces' }, | |
{ 'Square Footage Source':'SquareFootageSource' }, | |
{ 'Lot Size Source':'LotSizeSource' }, | |
{ 'Year Built Source':'YearBuiltSource' }, | |
{ 'Will Consider Lease':'WillConsiderLease' }, | |
{ 'Land Lease Type':'LandLeaseType' }, | |
{ 'Land Lease Amount Per Year':'LandLeaseAmountPerYear' }, | |
{ 'Land Lease Expiration Date':'LandLeaseExpirationDate'} | |
] | |
} | |
} | |
}); | |
var Properties = Backbone.Collection.extend({ model: Property }); | |
var PropertyDetailView = Backbone.View.extend({ | |
el: '#property-details', | |
template: window.templates.propertyDetails, | |
render: function( options ) { | |
if( options.model ) { | |
this.model = options.model; | |
} | |
// Include view methods and model attributes | |
this.viewData = jQuery.extend({}, this.model.toJSON(), this.viewMethods()); | |
// Render the view | |
jQuery(this.el).html(Mustache.to_html(this.template, this.viewData)); | |
// Place rendered template into the existing element | |
jQuery(this.el).find('#property-details-tabs').tabs(); | |
// Allow chaining | |
return this; | |
}, | |
/** | |
* Extra methods to have available to the view | |
*/ | |
viewMethods: function() { | |
/* Give the methods access to the model */ | |
var thisView = this; | |
var thisModel = this.model; | |
return { | |
/** | |
* Build a table of ordered key => value pairs. Can't do this | |
* in mustache.js because we can't iterate objects unless they have | |
* the same keys | |
*/ | |
table: function() { | |
return function(name, render) { | |
// Retrieve the actual name | |
name = render(name); | |
var rows = '', | |
rowClass = 'even', | |
rowCount = 0, | |
fields = thisModel.attributes.featureFields[name], | |
table = '<table class="pf-table"><tbody>'; | |
// Need two loops here, one for order and another for key => value pairs | |
for (i in fields) { | |
for (label in fields[i]) { | |
var key = fields[i][label]; | |
var value = thisModel.attributes[key] ? thisModel.attributes[key] : 'n/a'; | |
if( i%2 == 0 ) { | |
if( rowCount%2 == 0 ) { rowClass = 'even'; } | |
else { rowClass = 'odd'; } | |
rowCount++; | |
rows += '<tr class="pf-row '+rowClass+'">'; | |
} | |
rows += [ '<td class="pf-cell"><strong class="pf-label">', label, ':</strong><p class="pf-value">', value, '</p></td>' ].join(''); | |
if( i%2 == 1 ) { rows += "</tr>\n"; } | |
} | |
} | |
table += rows + '</tbody></table>'; | |
return table; | |
}; | |
} | |
}; | |
} | |
}); | |
/* Global */ | |
window.Comps = new Properties; | |
window.Comps.reset(window.backbone_models); | |
window.DetailView = new PropertyDetailView(); | |
/* Initialize the subject property */ | |
window.DetailView.render({ model: Comps.get( window.subject_property.Property.ListingKey ) }); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
window.templates = { | |
propertyDetails: [ | |
'<div class="property-detail-header">', | |
'<h3 class="address">{{FullStreetAddress}}<span class="city-state">{{City}}, {{State}} {{ZipCode}}</span></h3>', | |
'<span class="price-label">List Price: <span class="price">{{ListPrice}}</span></span>', | |
'<span class="dom">DOM: <span class="dom-count">{{DOM}}</span></span>', | |
'<a href="fix-me" class="street-view-link property-link">street view</a>', | |
'</div>', | |
'<ul class="property-quick-details">', | |
'<li class="property-icon"><img src="/img/properties/search/singlefamily-sold.png" alt=""></li>', | |
'<li>{{ListingStatus}}</li>', | |
'<li>{{SaleCode}}</li>', | |
'<li>{{BedroomsTotal}} BDS</li>', | |
'<li>{{BathsTotal}} BTHS</li>', | |
'<li>{{BuildingSize}} SF</li>', | |
'<li>{{LotSizeSQFT}} LOT</li>', | |
'<li>{{YearBuilt}} YR</li></ul>', | |
'</ul>', | |
'<div class="property-description">', | |
'<h3 class="comp-section-header">Description</h3>', | |
'<p>{{PublicRemarks}}</p>', | |
'</div>', | |
'<div class="property-features">', | |
'<h3 class="comp-section-header">Features</h3>', | |
'<div id="property-details-tabs">', | |
'<ul>', | |
'{{#featureTabs}}', | |
'<li><a href="#{{.}}">{{.}}</a></li>', | |
'{{/featureTabs}}', | |
'</ul>', | |
'{{#featureTabs}}', | |
'<div id="{{.}}" class="properties">', | |
'{{#table}}{{.}}{{/table}}', | |
'</div>', | |
'{{/featureTabs}}', | |
'</div>', | |
'</div>' | |
].join("\n") | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment