1 // ========================================================================== 2 // Project: SproutCore - JavaScript Application Framework 3 // Copyright: ©2006-2011 Strobe Inc. and contributors. 4 // Portions ©2008-2011 Apple Inc. All rights reserved. 5 // License: Licensed under MIT license (see license.js) 6 // ========================================================================== 7 8 sc_require('mixins/inline_editable'); 9 sc_require('mixins/inline_editor_delegate'); 10 sc_require('delegates/inline_text_field'); 11 12 13 /** 14 @class 15 16 Displays a static string of text. 17 18 You use a label view anytime you need to display a static string of text 19 or to display text that may need to be edited using only an inline control. 20 21 @extends SC.View 22 @extends SC.Control 23 @extends SC.InlineEditable 24 @extends SC.InlineEditorDelegate 25 @since SproutCore 1.0 26 */ 27 SC.LabelView = SC.View.extend(SC.Control, SC.InlineEditable, 28 /** @scope SC.LabelView.prototype */ { 29 30 classNames: ['sc-label-view'], 31 32 displayProperties: ['displayTitle', 'displayHint', 'displayToolTip', 'icon'], 33 34 /** 35 The delegate that gets notified of events related to the editing process. Set 36 this to the object you want to handles the lifecycle of the inline editor. 37 38 Defaults to itself. 39 @type SC.Object 40 */ 41 inlineEditorDelegate: SC.InlineTextFieldDelegate, 42 43 isEditable: NO, 44 45 /** 46 The exampleInlineTextFieldView property is by default a 47 SC.InlineTextFieldView but it can be set to a customized inline text field 48 view. 49 50 @property 51 @type {SC.View} 52 @default {SC.InlineTextFieldView} 53 */ 54 exampleEditor: SC.InlineTextFieldView, 55 56 /** 57 Whether the value, hint and toolTip will be escaped to avoid HTML injection 58 attacks or not. 59 60 You should only disable this option if you are sure you are displaying 61 non-user generated text. 62 63 Note: this is not an observed display property. If you change it after 64 rendering, you should call `displayDidChange` on the view to update the layer. 65 66 @type Boolean 67 @default true 68 */ 69 escapeHTML: true, 70 71 /** 72 If true, then the value will be localized. 73 This is a default that can be overidden by the settings in the owner view. 74 */ 75 localize: NO, 76 localizeBindingDefault: SC.Binding.oneWay().bool(), 77 78 /** 79 If set to true, the label element will include the 'ellipsis' class, which 80 by default sets the 'white-space' style to 'nowrap' and the 'text-overflow' 81 style to 'ellipsis'. 82 83 Note: that this does NOT work with multi-line text. 84 85 Note: this is not an observed display property. If you change it after 86 rendering, you should call `displayDidChange` on the view to update the layer. 87 88 @type Boolean 89 @default false 90 */ 91 needsEllipsis: false, 92 93 /** 94 Set this to a validator or to a function and the value 95 will be passed through it before being set. 96 97 This is a default default that can be overidden by the 98 settings in the owner view. 99 */ 100 formatter: null, 101 102 /** 103 The value of the label. 104 105 You may also set the value using a content object and a contentValueKey. 106 107 @field {String} 108 */ 109 value: '', 110 111 /** 112 The hint to display if no value is set. Should be used only if isEditable 113 is set to YES. 114 */ 115 hint: null, 116 117 /** @deprecated */ 118 hintEnabled: function() { 119 //@if(debug) 120 SC.warn("Developer Warning: The hintEnabled property of SC.LabelView is deprecated. Please simply get the isEditable property to determine if the hint will be displayed instead."); 121 //@endif 122 return this.get('isEditable'); 123 }.property('isEditable').cacheable(), 124 125 /** 126 An optional icon to display to the left of the label. Set this value 127 to either a CSS class name (for spriting) or an image URL. 128 */ 129 icon: null, 130 131 /** 132 Set the alignment of the label view. 133 134 Note: this is not an observed display property. If you change it after 135 rendering, you should call `displayDidChange` on the view to update the layer. 136 137 @type String SC.ALIGN_LEFT|SC.ALIGN_CENTER|SC.ALIGN_RIGHT 138 @default null 139 @deprecated Use CSS instead. 140 */ 141 textAlign: null, 142 143 // 144 // SUPPORT FOR AUTOMATIC RESIZING 145 // 146 supportsAutoResize: YES, 147 autoResizeLayer: function() { return this.get('layer'); } 148 .property('layer').cacheable(), 149 150 autoResizeText: function() { return this.get('displayTitle'); } 151 .property('displayTitle').cacheable(), 152 153 autoResizePadding: SC.propertyFromRenderDelegate('autoResizePadding', { height: 0, width: 10 }), 154 155 /** 156 The name of the theme's SC.LabelView render delegate. 157 158 @type String 159 */ 160 renderDelegateName: 'labelRenderDelegate', 161 162 /** 163 The value that will actually be displayed. 164 165 This property is dynamically computed by applying localization, 166 string conversion and other normalization utilities. 167 168 @type String 169 */ 170 displayTitle: function() { 171 var value, formatter; 172 173 value = this.get('value') ; 174 175 // 1. apply the formatter 176 formatter = this.getDelegateProperty('formatter', this.displayDelegate) ; 177 if (formatter) { 178 var formattedValue = (SC.typeOf(formatter) === SC.T_FUNCTION) ? 179 formatter(value, this) : formatter.fieldValueForObject(value, this) ; 180 if (!SC.none(formattedValue)) value = formattedValue ; 181 } 182 183 // 2. If the returned value is an array, convert items to strings and 184 // join with commas. 185 if (SC.typeOf(value) === SC.T_ARRAY) { 186 var ary = []; 187 for(var idx=0, idxLen = value.get('length'); idx< idxLen;idx++) { 188 var x = value.objectAt(idx) ; 189 if (!SC.none(x) && x.toString) x = x.toString() ; 190 ary.push(x) ; 191 } 192 value = ary.join(',') ; 193 } 194 195 // 3. If value is not a string, convert to string. (handles 0) 196 if (!SC.none(value) && value.toString) value = value.toString() ; 197 198 // 4. Localize 199 if (value && this.getDelegateProperty('localize', this.displayDelegate)) value = SC.String.loc(value) ; 200 201 return value; 202 }.property('value', 'localize', 'formatter').cacheable(), 203 204 /** 205 The hint that will actually be displayed depending on localization and 206 sanitizing (or not). 207 208 @type String 209 */ 210 displayHint: function () { 211 var hint = this.get('hint'), 212 isEditable = this.get('isEditable'); 213 214 if (isEditable) { 215 if (hint && this.getDelegateProperty('localize', this.displayDelegate)) { 216 hint = SC.String.loc(hint); 217 } 218 } else { 219 hint = null; 220 } 221 222 return hint; 223 }.property('hint', 'localize', 'isEditable').cacheable(), 224 225 /** @deprecated */ 226 hintValue: function() { 227 //@if(debug) 228 SC.warn("Developer Warning: The hintValue property of SC.LabelView is deprecated. Please simply get the hint or displayHint (localized) property instead."); 229 //@endif 230 var hintVal = this.get('hint'); 231 return hintVal; 232 }.property('hint').cacheable(), 233 234 /** @private */ 235 mouseDown: function(evt) { 236 // Capture the event if it's a double click and we are editable. 237 return this.get('isEditable') && evt.clickCount === 2; 238 }, 239 240 /** @private If isEditable is set to true, opens the inline text editor view. */ 241 doubleClick: function (evt) { return this.beginEditing(); }, 242 243 /* 244 * @method 245 * 246 * Hide the label view while the inline editor covers it. 247 */ 248 inlineEditorDidBeginEditing: function(original, editor, value, editable) { 249 this._oldOpacity = this.get('layout').opacity || 1; 250 this.adjust('opacity', 0); 251 252 original(editor, value, editable); 253 }.enhance(), 254 255 /* 256 * @method 257 * 258 * Restore the label view when the inline editor finishes. 259 */ 260 inlineEditorDidEndEditing: function() { 261 this.adjust('opacity', this._oldOpacity); 262 this._oldOpacity = null ; 263 } 264 }); 265