1 sc_require("handlebars"); 2 sc_require("ext/handlebars"); 3 sc_require("ext/handlebars/bind"); 4 sc_require("ext/handlebars/collection"); 5 sc_require("ext/handlebars/localization"); 6 sc_require("ext/handlebars/view"); 7 8 // Global hash of shared templates. This will automatically be populated 9 // by the build tools so that you can store your Handlebars templates in 10 // separate files that get loaded into JavaScript at buildtime. 11 SC.TEMPLATES = SC.Object.create(); 12 13 /** @class 14 15 SC.TemplateView allows you to create a view that uses the Handlebars templating 16 engine to generate its HTML representation. 17 18 To use it, create a file in your project called +mytemplate.handlebars+. Then, 19 set the +templateName+ property of your SC.TemplateView to +mytemplate+. 20 21 Alternatively, you can set the +template+ property to any function that 22 returns a string. It is recommended that you use +SC.Handlebars.compile()+ to 23 generate a function from a string containing Handlebars markup. 24 25 @extends SC.CoreView 26 @since SproutCore 1.5 27 */ 28 SC.TemplateView = SC.CoreView.extend( 29 /** @scope SC.TemplateView.prototype */ { 30 31 // This makes it easier to build custom views on top of TemplateView without 32 // gotchas, but may have tab navigation repercussions. The tab navigation 33 // system should be revisited. 34 acceptsFirstResponder: YES, 35 36 /** 37 The name of the template to lookup if no template is provided. 38 39 SC.TemplateView will look for a template with this name in the global 40 +SC.TEMPLATES+ hash. Usually this hash will be populated for you 41 automatically when you include +.handlebars+ files in your project. 42 43 @type String 44 */ 45 templateName: null, 46 47 /** 48 The hash in which to look for +templateName+. Defaults to SC.TEMPLATES. 49 50 @type Object 51 */ 52 templates: SC.TEMPLATES, 53 54 /** 55 The template used to render the view. This should be a function that 56 accepts an optional context parameter and returns a string of HTML that 57 will be inserted into the DOM relative to its parent view. 58 59 In general, you should set the +templateName+ property instead of setting 60 the template yourself. 61 62 @type Function 63 */ 64 template: function(key, value) { 65 if (value !== undefined) { 66 return value; 67 } 68 69 var templateName = this.get('templateName'), 70 template = this.get('templates').get(templateName); 71 72 if (!template) { 73 //@if(debug) 74 if (templateName) { 75 SC.Logger.warn('%@ - Unable to find template "%@".'.fmt(this, templateName)); 76 } 77 //@endif 78 79 return function() { return ''; }; 80 } 81 82 return template; 83 }.property('templateName').cacheable(), 84 85 /** 86 The object from which templates should access properties. 87 88 This object will be passed to the template function each time the render 89 method is called, but it is up to the individual function to decide what 90 to do with it. 91 92 By default, this will be the view itself. 93 94 @type Object 95 */ 96 context: function(key, value) { 97 if (value !== undefined) { 98 return value; 99 } 100 101 return this; 102 }.property().cacheable(), 103 104 /** 105 When the view is asked to render, we look for the appropriate template 106 function and invoke it, then push its result onto the passed 107 SC.RenderContext instance. 108 109 @param {SC.RenderContext} context the render context 110 */ 111 render: function(context) { 112 var data, 113 output, 114 template = this.get('template'), 115 templateContext = this.get('context'); 116 117 this._didRenderChildViews = YES; 118 119 data = { view: this, isRenderData: true }; 120 output = template(templateContext, { data: data }); 121 122 context.push(output); 123 }, 124 125 // in TemplateView, updating is handled by observers created by helpers in the 126 // template. As a result, we create an empty update method so that the old 127 // (pre-1.5) behavior which would force a full re-render does not get activated. 128 update: function() { }, 129 130 /** 131 Since mouseUp events will not fire unless we return YES to mouseDown, the 132 default mouseDown implementation returns YES if a mouseDown method exists. 133 */ 134 mouseDown: function() { 135 if (this.mouseUp) { return YES; } 136 return NO; 137 } 138 }); 139