1 /** 2 * Copyright (C) 2005-2010 Alfresco Software Limited. 3 * 4 * This file is part of Alfresco 5 * 6 * Alfresco is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU Lesser General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * Alfresco is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public License 17 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 /** 21 * Period component. 22 * 23 * @namespace Alfresco 24 * @class Alfresco.Period 25 */ 26 (function() 27 { 28 /** 29 * YUI Library aliases 30 */ 31 var Dom = YAHOO.util.Dom, 32 Event = YAHOO.util.Event; 33 34 /** 35 * Alfresco Slingshot aliases 36 */ 37 var $html = Alfresco.util.encodeHTML; 38 39 /** 40 * Period constructor. 41 * 42 * @param {String} htmlId The HTML id of the parent element 43 * @param {String} currentValueHtmlId The HTML id of the parent element 44 * @return {Alfresco.Period} The new Period instance 45 * @constructor 46 */ 47 Alfresco.Period = function(htmlId, currentValueHtmlId) 48 { 49 // Mandatory properties 50 this.name = "Alfresco.Period"; 51 this.id = htmlId; 52 this.currentValueHtmlId = currentValueHtmlId; 53 54 /* Register this component */ 55 Alfresco.util.ComponentManager.register(this); 56 57 /* Load YUI Components */ 58 Alfresco.util.YUILoaderHelper.require(["button"], this.onComponentsLoaded, this); 59 60 // Initialise prototype properties 61 this.widgets = {}; 62 this.periodDefinitionsByType = {}; 63 this.periodDefinitionsByLabel = {}; 64 65 return this; 66 }; 67 68 Alfresco.Period.prototype = 69 { 70 /** 71 * Object container for initialization options 72 * 73 * @property options 74 * @type object 75 */ 76 options: 77 { 78 /** 79 * The current value 80 * 81 * @property currentValue 82 * @type string 83 */ 84 currentValue: "", 85 86 /** 87 * Array of objects representing the period data 88 * returned from the server 89 * 90 * @property data 91 * @type Array of objects 92 */ 93 data: [], 94 95 /** 96 * Flag to determine whether the picker is in disabled mode 97 * 98 * @property disabled 99 * @type boolean 100 * @default false 101 */ 102 disabled: false, 103 104 /** 105 * Flag to indicate whether the field is mandatory 106 * 107 * @property mandatory 108 * @type boolean 109 * @default false 110 */ 111 mandatory: false 112 }, 113 114 /** 115 * Object container for storing YUI widget instances. 116 * 117 * @property widgets 118 * @type object 119 */ 120 widgets: null, 121 122 /** 123 * Object containing all period definitions keyed by period type. 124 * 125 * @property periodDefinitionsByType 126 * @type object 127 */ 128 periodDefinitionsByType: null, 129 130 /** 131 * Object containing all period definitions keyed by period label. 132 * 133 * @property periodDefinitionsByLabel 134 * @type object 135 */ 136 periodDefinitionsByLabel: null, 137 138 /** 139 * Set multiple initialization options at once. 140 * 141 * @method setOptions 142 * @param obj {object} Object literal specifying a set of options 143 * @return {Alfresco.Period} returns 'this' for method chaining 144 */ 145 setOptions: function Period_setOptions(obj) 146 { 147 this.options = YAHOO.lang.merge(this.options, obj); 148 return this; 149 }, 150 151 /** 152 * Set messages for this component. 153 * 154 * @method setMessages 155 * @param obj {object} Object literal specifying a set of messages 156 * @return {Alfresco.Period} returns 'this' for method chaining 157 */ 158 setMessages: function Period_setMessages(obj) 159 { 160 Alfresco.util.addMessages(obj, this.name); 161 return this; 162 }, 163 164 /** 165 * Fired by YUILoaderHelper when required component script files have 166 * been loaded into the browser. 167 * 168 * @method onComponentsLoaded 169 */ 170 onComponentsLoaded: function Period_onComponentsLoaded() 171 { 172 Event.onContentReady(this.id, this.onReady, this, true); 173 }, 174 175 /** 176 * Fired by YUI when parent element is available for scripting. 177 * Component initialisation, including instantiation of YUI widgets and event listener binding. 178 * 179 * @method onReady 180 */ 181 onReady: function Period_onReady() 182 { 183 // create the period definition data structure 184 for (var p = 0; p < this.options.data.length; p++) 185 { 186 this.periodDefinitionsByType[this.options.data[p].type] = this.options.data[p]; 187 this.periodDefinitionsByLabel[this.options.data[p].label] = this.options.data[p]; 188 } 189 190 // add a 'Not Set' option 191 var notSetOption = 192 { 193 type: "", 194 label: this._msg("form.notset"), 195 hasExpression: false 196 }; 197 198 this.periodDefinitionsByType[notSetOption.type] = notSetOption; 199 this.periodDefinitionsByLabel[notSetOption.label] = notSetOption; 200 201 // split the current value into it's parts 202 var parts = this.options.currentValue.split("|"), 203 periodType = this.options.currentValue, 204 expression = 1; 205 if (parts.length == 2) 206 { 207 periodType = parts[0]; 208 expression = parts[1]; 209 } 210 211 // get the period definition for the current value 212 var periodDef = this.periodDefinitionsByType[periodType]; 213 214 if (this.options.disabled) 215 { 216 // populate the view mode span with a human readable representation 217 // of the current value 218 var displayValue = this.options.currentValue; 219 if (periodDef !== undefined) 220 { 221 if (periodDef.hasExpression) 222 { 223 displayValue = expression + " " + periodDef.label; 224 if (expression > 1) 225 { 226 displayValue += "s"; 227 } 228 } 229 else 230 { 231 displayValue = periodDef.label; 232 } 233 } 234 235 // update the span to show the display value 236 Dom.get(this.id).innerHTML = $html(displayValue); 237 } 238 else 239 { 240 // sort the period options in display label order 241 var sortedOptions = []; 242 for (var x in this.periodDefinitionsByType) 243 { 244 sortedOptions.push(this.periodDefinitionsByType[x].label); 245 } 246 sortedOptions.sort(); 247 248 // populate the drop down list with period options 249 // using the sorted array of labels 250 var def = null, 251 eSelect = Dom.get(this.id + "-type"); 252 253 for (p = 0; p < sortedOptions.length; p++) 254 { 255 def = this.periodDefinitionsByLabel[sortedOptions[p]]; 256 eSelect.options[p] = new Option(def.label, def.type, periodType === def.type, periodType === def.type); 257 } 258 259 // populate the expression field with the current value 260 if (periodDef !== undefined && periodDef.hasExpression) 261 { 262 Dom.get(this.id + "-expression").value = expression; 263 } 264 } 265 266 // add an onchange event listener to the select drop down 267 Event.addListener(this.id + "-type", "change", this._handleDataChange, this, true); 268 269 // add an onkeyup event listender to the expression field 270 Event.addListener(this.id + "-expression", "keyup", this._handleDataChange, this, true); 271 }, 272 273 /** 274 * Handles any change to the control i.e. the drop down list or the 275 * expression field. If the current control data is valid the hidden 276 * field is updated with the data represented in the submission format. 277 * 278 * @method _handleDataChange 279 * @param event The event that occurred 280 * @private 281 */ 282 _handleDataChange: function Period__handleDataChange(event) 283 { 284 // get the current values and construct the new value 285 var type = Dom.get(this.id + "-type").value, 286 expression = Dom.get(this.id + "-expression").value, 287 newValue = type + "|" + expression, 288 valueValid = true; 289 290 if (type === "") 291 { 292 newValue = ""; 293 Dom.get(this.id + "-expression").value = ""; 294 } 295 else 296 { 297 var periodDef = this.periodDefinitionsByType[type]; 298 if (periodDef.hasExpression) 299 { 300 if (expression === "") 301 { 302 expression = 1; 303 newValue += expression; 304 } 305 else if (isNaN(expression)) 306 { 307 valueValid = false; 308 } 309 } 310 else 311 { 312 newValue = type; 313 Dom.get(this.id + "-expression").value = ""; 314 } 315 } 316 317 if (valueValid) 318 { 319 YAHOO.util.Dom.get(this.currentValueHtmlId).value = newValue; 320 321 if (Alfresco.logger.isDebugEnabled()) 322 { 323 Alfresco.logger.debug("Hidden field '" + this.currentValueHtmlId + "' updated to '" + newValue + "'"); 324 } 325 326 // inform the forms runtime that the control value has been updated (if field is mandatory) 327 if (this.options.mandatory) 328 { 329 YAHOO.Bubbling.fire("mandatoryControlValueUpdated", this); 330 } 331 } 332 }, 333 334 /** 335 * Gets a custom message 336 * 337 * @method _msg 338 * @param messageId {string} The messageId to retrieve 339 * @return {string} The custom message 340 * @private 341 */ 342 _msg: function Period__msg(messageId) 343 { 344 return Alfresco.util.message.call(this, messageId, "Alfresco.Period", Array.prototype.slice.call(arguments).slice(1)); 345 } 346 }; 347 })(); 348