1 (function ($, rf) { 2 3 rf.ui = rf.ui || {}; 4 5 rf.ui.Select = function(id, options) { 6 this.id = id; 7 var mergedOptions = $.extend({}, defaultOptions, options); 8 mergedOptions['attachTo'] = id; 9 mergedOptions['scrollContainer'] = $(document.getElementById(id + "Items")).parent()[0]; 10 mergedOptions['focusKeeperEnabled'] = false; 11 $super.constructor.call(this, id, mergedOptions); 12 13 this.options = mergedOptions; 14 this.defaultLabel = mergedOptions.defaultLabel; 15 var inputLabel = this.__getValue(); 16 this.initialValue = (inputLabel != this.defaultLabel) ? inputLabel : ""; 17 this.selValueInput = $(document.getElementById(id + "selValue")); 18 this.container = this.selValueInput.parent(); 19 this.clientSelectItems = mergedOptions.clientSelectItems; 20 this.filterFunction = mergedOptions.filterFunction; 21 22 23 if (mergedOptions.showControl && !mergedOptions.disabled) { 24 this.container.bind("mousedown", $.proxy(this.__onBtnMouseDown, this)) 25 .bind("mouseup", $.proxy(this.__onMouseUp, this)); 26 } 27 28 this.selectFirst = mergedOptions.selectFirst; 29 this.popupList = new rf.ui.PopupList((id + "List"), this, mergedOptions); 30 this.list = this.popupList.__getList(); 31 this.listElem = $(document.getElementById(id + "List")); 32 33 this.listElem.bind("mousedown", $.proxy(this.__onListMouseDown, this)); 34 this.listElem.bind("mouseup", $.proxy(this.__onMouseUp, this)); 35 36 var listEventHandlers = {}; 37 listEventHandlers["listshow" + this.namespace] = $.proxy(this.__listshowHandler, this); 38 listEventHandlers["listhide" + this.namespace] = $.proxy(this.__listhideHandler, this); 39 listEventHandlers["change" + this.namespace] = $.proxy(this.__onInputChangeHandler, this); 40 rf.Event.bind(this.input, listEventHandlers, this); 41 42 this.originalItems = this.list.__getItems(); 43 this.enableManualInput = mergedOptions.enableManualInput; 44 45 if (this.originalItems.length > 0 && this.enableManualInput) { 46 this.cache = new rf.utils.Cache("", this.originalItems, getData, true); 47 } 48 this.changeDelay = mergedOptions.changeDelay; 49 }; 50 51 rf.ui.InputBase.extend(rf.ui.Select); 52 var $super = rf.ui.Select.$super; 53 54 var defaultOptions = { 55 defaultLabel: "", 56 selectFirst: true, 57 showControl: true, 58 enableManualInput: false, 59 itemCss: "rf-sel-opt", 60 selectItemCss: "rf-sel-sel", 61 listCss: "rf-sel-lst-cord", 62 changeDelay: 8, 63 disabled: false, 64 filterFunction : undefined 65 }; 66 67 var REGEXP_TRIM = /^[\n\s]*(.*)[\n\s]*$/; 68 69 var getData = function (nodeList) { 70 var data = []; 71 nodeList.each(function () { 72 ; 73 data.push($(this).text().replace(REGEXP_TRIM, "$1")); 74 }); 75 return data; 76 } 77 78 $.extend(rf.ui.Select.prototype, ( function () { 79 return{ 80 name : "select", 81 defaultLabelClass : "rf-sel-dflt-lbl", 82 83 __listshowHandler: function(e) { 84 }, 85 86 __listhideHandler: function(e) { 87 }, 88 89 __onInputChangeHandler: function(e) { 90 this.__setValue(this.input.val()); 91 }, 92 93 __onBtnMouseDown: function(e) { 94 if (!this.popupList.isVisible()) { 95 this.__updateItems(); 96 this.__showPopup(); 97 } else { 98 this.__hidePopup(); 99 } 100 this.isMouseDown = true; 101 }, 102 103 __focusHandler: function(e) { 104 if (!this.focused) { 105 if (this.__getValue() == this.defaultLabel) { 106 this.__setValue(""); 107 } 108 this.focusValue = this.selValueInput.val(); 109 this.focused = true; 110 this.invokeEvent.call(this, "focus", document.getElementById(this.id), e); 111 } 112 }, 113 114 __keydownHandler: function(e) { 115 var code; 116 117 if (e.keyCode) { 118 code = e.keyCode; 119 } else if (e.which) { 120 code = e.which; 121 } 122 123 var visible = this.popupList.isVisible(); 124 125 switch (code) { 126 case rf.KEYS.DOWN: 127 e.preventDefault(); 128 if (!visible) { 129 this.__updateItems(); 130 this.__showPopup(); 131 } else { 132 this.list.__selectNext(); 133 } 134 break; 135 136 case rf.KEYS.UP: 137 e.preventDefault(); 138 if (visible) { 139 this.list.__selectPrev(); 140 } 141 break; 142 143 case rf.KEYS.RETURN: 144 e.preventDefault(); 145 if (visible) { 146 this.list.__selectCurrent(); 147 } 148 return false; 149 break; 150 151 case rf.KEYS.TAB: 152 break; 153 154 case rf.KEYS.ESC: 155 e.preventDefault(); 156 if (visible) { 157 this.__hidePopup(); 158 } 159 break; 160 161 default: 162 var _this = this; 163 window.clearTimeout(this.changeTimerId); 164 this.changeTimerId = window.setTimeout(function() { 165 _this.__onChangeValue(e); 166 }, this.changeDelay); 167 break; 168 } 169 }, 170 171 __onChangeValue: function(e) { 172 this.list.__selectByIndex(); 173 var newValue = this.__getValue(); 174 if (this.cache && this.cache.isCached(newValue)) { 175 this.__updateItems(); 176 177 if (this.list.__getItems().length != 0) { 178 this.container.removeClass("rf-sel-fld-err"); 179 } else { 180 this.container.addClass("rf-sel-fld-err"); 181 } 182 183 if (!this.popupList.isVisible()) { 184 this.__showPopup(); 185 } 186 } 187 }, 188 189 __blurHandler: function(e) { 190 if (!this.isMouseDown) { 191 var that = this; 192 this.timeoutId = window.setTimeout(function() { 193 if (that.input !== null) { 194 that.onblur(e); 195 } 196 }, 200); 197 } else { 198 this.__setInputFocus(); 199 this.isMouseDown = false; 200 } 201 }, 202 203 __onListMouseDown: function(e) { 204 this.isMouseDown = true; 205 }, 206 207 __onMouseUp: function(e) { 208 this.isMouseDown = false; 209 this.__setInputFocus(); 210 }, 211 212 __updateItems: function() { 213 var newValue = this.__getValue(); 214 newValue = (newValue != this.defaultLabel) ? newValue : ""; 215 this.__updateItemsFromCache(newValue); 216 217 if (this.selectFirst) { 218 this.list.__selectByIndex(0); 219 } 220 }, 221 222 __updateItemsFromCache: function(value) { 223 if (this.originalItems.length > 0 && this.enableManualInput) { 224 var newItems = this.cache.getItems(value, this.filterFunction); 225 var items = $(newItems); 226 this.list.__setItems(items); 227 $(document.getElementById(this.id + "Items")).empty().append(items); 228 } 229 }, 230 231 __getClientItemFromCache: function(inputLabel) { 232 var value; 233 var label; 234 if (this.enableManualInput) { 235 var items = this.cache.getItems(inputLabel, this.filterFunction); 236 if (items && items.length > 0) { 237 var first = $(items[0]); 238 $.each(this.clientSelectItems, function() { 239 if (this.id == first.attr("id")) { 240 label = this.label; 241 value = this.value; 242 return false; 243 } 244 }); 245 } else { 246 label = inputLabel; 247 value = ""; 248 } 249 } 250 251 if (label) { 252 return {'label': label, 'value': value}; 253 } 254 }, 255 256 __getClientItem: function(inputLabel) { 257 var value; 258 var label = inputLabel; 259 $.each(this.clientSelectItems, function() { 260 if (label == this.label) { 261 value = this.value; 262 } 263 }); 264 265 if (label && value) { 266 return {'label': label, 'value': value}; 267 } 268 }, 269 270 __showPopup: function() { 271 this.popupList.show(); 272 this.invokeEvent.call(this, "listshow", document.getElementById(this.id)); 273 }, 274 275 __hidePopup: function() { 276 this.popupList.hide(); 277 this.invokeEvent.call(this, "listhide", document.getElementById(this.id)); 278 }, 279 280 showPopup: function() { 281 if (!this.popupList.isVisible()) { 282 this.__updateItems(); 283 this.__showPopup(); 284 } 285 this.__setInputFocus(); 286 if (!this.focused) { 287 if (this.__getValue() == this.defaultLabel) { 288 this.__setValue(""); 289 } 290 this.focusValue = this.selValueInput.val(); 291 this.focused = true; 292 this.invokeEvent.call(this, "focus", document.getElementById(this.id)); 293 } 294 }, 295 296 hidePopup: function() { 297 if (this.popupList.isVisible()) { 298 this.__hidePopup(); 299 var inputLabel = this.__getValue(); 300 301 if (!inputLabel || inputLabel == "") { 302 this.__setValue(this.defaultLabel); 303 this.selValueInput.val(""); 304 } 305 306 this.focused = false; 307 this.invokeEvent.call(this, "blur", document.getElementById(this.id)); 308 if (this.focusValue != this.selValueInput.val()) { 309 this.invokeEvent.call(this, "change", document.getElementById(this.id)); 310 } 311 } 312 }, 313 314 processItem: function(item) { 315 var key = $(item).attr("id"); 316 var label; 317 $.each(this.clientSelectItems, function() { 318 if (this.id == key) { 319 label = this.label; 320 return false; 321 } 322 }); 323 this.__setValue(label); 324 this.__hidePopup(); 325 this.__setInputFocus(); 326 this.__save(); 327 328 this.invokeEvent.call(this, "selectitem", document.getElementById(this.id)); 329 }, 330 331 __save: function() { 332 var value = ""; 333 var label = ""; 334 var inputLabel = this.__getValue(); 335 var clientSelectItem; 336 337 if (inputLabel && inputLabel != "") { 338 if (this.enableManualInput) { 339 clientSelectItem = this.__getClientItemFromCache(inputLabel); 340 } else { 341 clientSelectItem = this.__getClientItem(inputLabel); 342 } 343 344 if (clientSelectItem) { 345 label = clientSelectItem.label; 346 value = clientSelectItem.value; 347 } 348 } 349 350 this.__setValue(label); 351 this.selValueInput.val(value); 352 }, 353 354 onblur: function(e) { 355 this.__hidePopup(); 356 var inputLabel = this.__getValue(); 357 358 if (!inputLabel || inputLabel == "") { 359 this.__setValue(this.defaultLabel); 360 this.selValueInput.val(""); 361 } 362 363 this.focused = false; 364 this.invokeEvent.call(this, "blur", document.getElementById(this.id), e); 365 if (this.focusValue != this.selValueInput.val()) { 366 this.invokeEvent.call(this, "change", document.getElementById(this.id), e); 367 } 368 }, 369 370 getValue: function() { 371 return this.selValueInput.val(); 372 }, 373 374 setValue: function(value) { 375 if (value == null || value == '') { 376 this.__setValue(''); 377 this.__save(); 378 this.__updateItems(); 379 return; 380 } 381 var item; 382 for (var i = 0; i < this.clientSelectItems.length; i++) { 383 item = this.clientSelectItems[i]; 384 if (item.value == value) { 385 this.__setValue(item.label); 386 this.__save(); 387 this.list.__selectByIndex(i); 388 return; 389 } 390 } 391 }, 392 393 getLabel: function() { 394 return this.__getValue(); 395 }, 396 397 destroy: function() { 398 this.popupList.destroy(); 399 this.popupList = null; 400 $super.destroy.call(this); 401 } 402 } 403 })()); 404 405 // client-side validation 406 rf.csv = rf.csv || {}; 407 rf.csv.validateSelectLabelValue = function (input, id, params, msg) { 408 var value = $(document.getElementById(id + 'selValue')).val(); 409 var label = $(document.getElementById(id + 'Input')).val(); 410 411 var defaultLabel = RichFaces.component(id).defaultLabel; 412 413 if (!value && label && (label != defaultLabel)) { 414 throw rf.csv.getMessage(null, 'UISELECTONE_INVALID', [id, ""]); 415 } 416 }; 417 418 })(RichFaces.jQuery, window.RichFaces);