1 /*
  2  * ***** BEGIN LICENSE BLOCK *****
  3  * Zimbra Collaboration Suite Web Client
  4  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016 Synacor, Inc.
  5  *
  6  * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License");
  7  * you may not use this file except in compliance with the License.
  8  * You may obtain a copy of the License at: https://www.zimbra.com/license
  9  * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15
 10  * have been added to cover use of software over a computer network and provide for limited attribution
 11  * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B.
 12  *
 13  * Software distributed under the License is distributed on an "AS IS" basis,
 14  * WITHOUT WARRANTY OF ANY KIND, either express or implied.
 15  * See the License for the specific language governing rights and limitations under the License.
 16  * The Original Code is Zimbra Open Source Web Client.
 17  * The Initial Developer of the Original Code is Zimbra, Inc.  All rights to the Original Code were
 18  * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015.
 19  *
 20  * All portions of the code are Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved.
 21  * ***** END LICENSE BLOCK *****
 22  */
 23 
 24 
 25 /**
 26  * @constructor
 27  * @class
 28  * OSelect1_XFormItem class -- lightning fast SELECT type widget
 29  * @author Owen Williams, Greg Solovyev
 30  * 
 31  * @private
 32  */
 33 OSelect1_XFormItem = function(){ this._enabled = true; }
 34 XFormItemFactory.createItemType("_OSELECT1_", "oselect1", OSelect1_XFormItem, Select1_XFormItem);
 35 
 36 OSelect1_XFormItem._mouseWheelEventAttached = false;
 37 OSelect1_XFormItem._mouseWheelCurrentSelect;
 38 OSelect1_XFormItem._mouseWheelHideMenu = function() {
 39 	//DBG.println(AjxDebug.DBG1, "OSelect1_XFormItem._mouseWheelCurrentSelect.hideMenu hiding menu time " +  (new Date()).getTime());
 40 	OSelect1_XFormItem._mouseWheelCurrentSelect.hideMenu();
 41 };
 42 
 43 // override the default SELECT type
 44 //XFormItemFactory.registerItemType("_SELECT1_", "select1", OSelect1_XFormItem)
 45 OSelect1_XFormItem.prototype.focusable = false;
 46 OSelect1_XFormItem.prototype.cssClass = "oselect";
 47 OSelect1_XFormItem.prototype.multiple = false;
 48 OSelect1_XFormItem.prototype.writeElementDiv = false;
 49 OSelect1_XFormItem.prototype.width = "auto";
 50 OSelect1_XFormItem.prototype.editable = false;
 51 OSelect1_XFormItem.prototype.menuUp = false;
 52 OSelect1_XFormItem.prototype.noteUp = false;
 53 OSelect1_XFormItem.prototype.inputSize = 25;
 54 OSelect1_XFormItem.prototype.bmolsnr = true;
 55 OSelect1_XFormItem.prototype.nowrap = false;
 56 OSelect1_XFormItem.prototype.labelWrap = true;
 57 //TODO: get showing check working for the normal SELECT, requires:
 58 //		* separate notion of hilited row (for mouseover) and selected row(s)
 59 //		* teach select1 that more than one value may be selected (same as select)
 60 //		* convert OSELECT_CHECK to just use showCheck?
 61 //		* does √ work everywhere?  Use an image?
 62 OSelect1_XFormItem.prototype.setMenuWidth = true;
 63 OSelect1_XFormItem.prototype.showCheck = false;
 64 OSelect1_XFormItem.prototype.checkHTML = "√";
 65 OSelect1_XFormItem.MENU_DIR_DOWN=1;
 66 OSelect1_XFormItem.MENU_DIR_UP=2;
 67 OSelect1_XFormItem.MENU_DIR_UNKNOWN=0;
 68 OSelect1_XFormItem.NOTE_HEIGHT=22;
 69 OSelect1_XFormItem.prototype.menuDirection = OSelect1_XFormItem.MENU_DIR_UNKNOWN;
 70 OSelect1_XFormItem.prototype.visibilityChecks = [XFormItem.prototype.hasReadPermission];
 71 OSelect1_XFormItem.prototype.enableDisableChecks = [XFormItem.prototype.hasWritePermission];
 72 
 73 //	methods
 74 OSelect1_XFormItem.prototype.initFormItem = function () {
 75 	// if we're dealing with an XFormChoices object...
 76 	var choices = this.getChoices();
 77 	if (choices == null || choices.constructor != XFormChoices) return;
 78 
 79 	//	...set up to receive notification when its choices change
 80 	var listener = new AjxListener(this, this.choicesChangeLsnr);
 81 	choices.addListener(DwtEvent.XFORMS_CHOICES_CHANGED, listener);
 82 }
 83 
 84 OSelect1_XFormItem.prototype.updateElement = function (newValue) {
 85 	if (this.choicesAreDirty()) this.updateChoicesHTML();
 86 	// hack: if this item can display multiple values and there's a comma in the value
 87 	//		assume it's a list of values
 88 	if (this.getMultiple() && newValue != null && newValue.indexOf(",") > -1) {
 89 		newValue = newValue.split(",");
 90 		for (var i = 0; i < newValue.length; i++) {
 91 			newValue[i] = this.getChoiceLabel(newValue[i]);
 92 		}
 93 	} else {
 94 		newValue = this.getChoiceLabel(newValue);
 95 	}
 96 	if (newValue == null) newValue = "";
 97 	
 98 	var el = this.getDisplayElement();
 99 
100 	if (el) {
101 		if(this.getInheritedProperty("editable")) {
102 			if((!newValue || newValue=="") && el.value != newValue) {
103 				var i=0;
104 			}
105 			el.value = newValue;
106 			//DBG.println(AjxDebug.DBG1, AjxBuffer.concat(this.getId(),".value = ",newValue));
107 			if(this.getElement() && el.offsetWidth && this.getElement().style)
108 				this.getElement().style.width = el.offsetWidth + 20 + 'px';
109 				
110 		} else {
111 			el.innerHTML = newValue;
112 		}
113 		//el.readOnly = !this.getInheritedProperty("editable");
114 	}
115 }
116 
117 OSelect1_XFormItem.prototype.getShowCheck = function () {
118 	return this.cacheInheritedProperty("showCheck", "$showCheck");
119 }
120 
121 OSelect1_XFormItem.prototype.getCheckHTML = function () {
122 	return this.cacheInheritedProperty("checkHTML", "$checkHTML");
123 }
124 
125 
126 OSelect1_XFormItem.prototype.getMenuElementId = function () {
127 	return "___OSELECT_MENU___";
128 }
129 OSelect1_XFormItem.prototype.getMenuElement = function () {
130 	var id = this.getMenuElementId();
131 	var el = this.getElement(id);
132 	if (el == null) {
133 		el = this.createElement(id, null, "div", "MENU CONTENTS");
134 	}
135 	return el;
136 }
137 
138 OSelect1_XFormItem.prototype.getNoteElementId = function () {
139 	return "___OSELECT_NOTE___";
140 }
141 OSelect1_XFormItem.prototype.getNoteElement = function () {
142 	var id = this.getNoteElementId();
143 	var el = this.getElement(id);
144 	if (el == null) {
145 		el = this.createElement(id, null, "div", "NOTE CONTENTS");
146 	}
147 	return el;
148 }
149 /*OSelect1_XFormItem.prototype.setError = function (message, childError) {
150 	if(window.console && window.console.log) console.log("Showing error note");
151 	var errLoc = this.getErrorLocation();
152 	if (errLoc == _PARENT_ || errLoc == _INHERIT_){
153 		this.getParentItem().setError(message, true);
154 		return;
155 	}
156 	this.showNote(message, this.getErrorNoteCssClass());
157 	this.__errorState = XFormItem.ERROR_STATE_ERROR;
158 }
159 
160 OSelect1_XFormItem.prototype.clearError = function () {
161 	if(window.console && window.console.log) console.log("Hiding error note");
162 	var errLoc = this.getErrorLocation();
163 	if (errLoc == _PARENT_ || errLoc == _INHERIT_){
164 		this.getParentItem().clearError();
165 		return;
166 	}
167 	this.hideNote();
168 	this.__errorState = XFormItem.ERROR_STATE_VALID;
169 }*/
170 
171 OSelect1_XFormItem.prototype.showMenu = function() {
172 	if(!this._enabled)
173 		return;
174 	if(window.console && window.console.log) console.log("Showing menu");
175 	this.hideInputTooltip();
176 	
177 	if (AjxEnv.isIE && !OSelect1_XFormItem._mouseWheelEventAttached) {
178 		var form = this.getForm();
179 		var formElement = form.getHtmlElement();
180 		if (formElement.attachEvent) {
181 			formElement.attachEvent("onmousewheel", OSelect1_XFormItem._mouseWheelHideMenu);
182 			OSelect1_XFormItem._mouseWheelCurrentSelect = this;
183 			OSelect1_XFormItem._mouseWheelEventAttached = true;
184 		}
185 	}
186 
187 	var menu = this.getMenuElement();
188 	if (menu == null) return; 
189 
190 	menu.className = this.getMenuCssClass();
191 	menu.innerHTML = this.getChoicesHTML();	
192 	var bounds;
193 	//bounds = this.getBounds(this.getElement().childNodes[0]);
194 	if(this.getInheritedProperty("editable")) {
195 		bounds = this.getBounds(this.getDisplayElement());
196 	} else {
197 		bounds = this.getBounds(this.getElement());
198 	}
199 	var w =DwtShell.getShell(window).getSize();
200 	var wh = w.y;
201 	var WINDOW_GUTTER = 8;
202 	menu.style.left = parseInt(bounds.left) + 'px';
203 	menu.style.top = parseInt(bounds.top) + parseInt(bounds.height) - 1 + 'px';
204 	var choices = this.getNormalizedChoices();
205 	if(choices && choices.values) {
206 		menu.style.overflow="auto";
207         var visibleChoices = choices.values.length - choices.totalInvisibleChoices;
208         menu.style.height = "auto";
209     }
210 
211 	var value = this.getInstanceValue();
212 	var getDisplayValueMethod = this.getDisplayValueMethod();
213 	if (getDisplayValueMethod) {
214 		value = getDisplayValueMethod.call(this, value);
215 	}
216 	var selectedItemNum = this.getChoiceNum(value);
217 	this.__currentHiliteItem = selectedItemNum;
218 	this.hiliteChoice(selectedItemNum);
219 	menu.style.zIndex = Dwt.Z_HIDDEN;
220 	menu.style.display = "block";
221 
222 
223 	var mBounds = this.getBounds(menu);
224 	var menuHeight = mBounds.height;
225 	var menuTop = mBounds.top;
226     if (this.getInheritedProperty("setMenuWidth") == true) {
227         if (AjxEnv.isIE) {
228             if(this.getInheritedProperty("editable")) {
229                 menu.style.width = parseInt(bounds.width)+4 + 'px';
230                 menu.getElementsByTagName("table")[0].style.width = parseInt(bounds.width) - 1 + 'px';
231             } else {
232                 menu.style.width = parseInt(bounds.width)+2 + 'px';
233                 menu.getElementsByTagName("table")[0].style.width = parseInt(bounds.width) - 1 + 'px';
234             }
235         } else {
236             if(this.getInheritedProperty("editable")) {
237                 menu.style.width = parseInt(bounds.width)-5 + 'px';
238                 menu.getElementsByTagName("table")[0].style.width = parseInt(bounds.width) - 6 + 'px';
239             } else {
240                 menu.style.width = parseInt(bounds.width)-3 + 'px';
241                 menu.getElementsByTagName("table")[0].style.width = parseInt(bounds.width) - 4 + 'px';
242             }
243         }
244     }
245 	if(menuHeight + menuTop > wh - WINDOW_GUTTER) {
246 		//menu does not fit downwards - check if it fits upwards
247 		if((bounds.top - menuHeight) > WINDOW_GUTTER) {
248 			//yes - it fits upwards
249 			
250 			menu.style.top = bounds.top - menuHeight + 'px';
251 			menu.getElementsByTagName("table")[0].className = this.getChoiceTableCssClass();				
252 		} else {
253 			/*
254 			* menu is too big to expand either up or down 
255 			* make it expand wherever ther is more space and make it scrollable
256 			*/
257 			if(bounds.top > ((wh - WINDOW_GUTTER*2)/2) ) {
258 				//expand upwards
259 				menu.style.height = parseInt(bounds.top) - WINDOW_GUTTER + 'px';
260 				menu.style.top = WINDOW_GUTTER + 'px';
261 				this.menuDirection = OSelect1_XFormItem.MENU_DIR_UP;
262 			} else {
263 				//expand downwards
264 				menu.style.top	= 	parseInt(menu.style.top)+2 + 'px';
265 				menu.style.height = wh-WINDOW_GUTTER-parseInt(menu.style.top) + 'px';
266 				this.menuDirection = OSelect1_XFormItem.MENU_DIR_DOWN;
267 			}
268 
269             if(!AjxEnv.isIE){
270                 menu.style.height = parseInt(menu.style.height) - 11;
271             }
272 			menu.style.overflow="auto";	
273 			menu.getElementsByTagName("table")[0].className = this.getChoiceScrollTableCssClass();
274 			menu.getElementsByTagName("table")[0].width="100%";
275 		} 
276 	} else {
277 		menu.getElementsByTagName("table")[0].className = this.getChoiceTableCssClass();
278 	}
279 
280     if(!AjxEnv.isIE && menu.clientWidth && menu.scrollWidth && (menu.scrollWidth > menu.clientWidth)){
281         menu.style.overflow="auto";
282     }
283 
284 	menu.style.zIndex = 1000000;
285 	if (this.$hideListener == null) {
286 		this.$hideListener = new AjxListener(this, this.oMouseUp);
287 	}
288 	
289 	if (this.$outsideMouseDownListener == null) {
290 		this.$outsideMouseDownListener = new AjxListener(this, this.onOutsideMouseDown);
291 	}
292 
293 	AjxCore.addListener(window, DwtEvent.ONMOUSEUP, this.$hideListener);
294 	AjxCore.addListener(document.body, DwtEvent.ONMOUSEDOWN, this.$outsideMouseDownListener);
295 	Dwt.setHandler(this.getForm().getHtmlElement(), DwtEvent.ONMOUSEWHEEL, this.$outsideMouseDownListener);	
296 	DwtEventManager.addListener(DwtEvent.ONMOUSEDOWN, this.$outsideMouseDownListener);	
297 	this.menuUp = true;
298 }
299 
300 OSelect1_XFormItem.prototype.choicesChangeLsnr = function () {
301 	this._choiceDisplayIsDirty = true;
302 	delete this.$normalizedChoices;
303 	if(this.menuUp)
304 		this.showMenu();
305 }
306 
307 OSelect1_XFormItem.prototype.redrawChoices = function () {
308 	var menu = this.getMenuElement();
309 	if (menu == null) return; 
310 
311 	menu.innerHTML = this.getChoicesHTML();		
312 }
313 
314 OSelect1_XFormItem.prototype.hideMenu = function () {
315 	if(!this.menuUp) {
316 		return;
317 	}	
318 	if(window.console && window.console.log) console.log("Hiding menu");
319 	// hide the menu on a timer so we don't have to deal with wierd selection bugs
320 	setTimeout(this.getFormGlobalRef()+".getElement('" + this.getMenuElementId() + "').style.display = 'none'", 10);
321 
322 	AjxCore.removeListener(window, DwtEvent.ONMOUSEUP, this.$hideListener);
323 	AjxCore.removeListener(document.body, DwtEvent.ONMOUSEDOWN, this.$outsideMouseDownListener);
324 	Dwt.clearHandler(this.getForm().getHtmlElement(), DwtEvent.ONMOUSEWHEEL);
325 	DwtEventManager.removeListener(DwtEvent.ONMOUSEDOWN, this.$outsideMouseDownListener);
326 	if (AjxEnv.isIE &&  OSelect1_XFormItem._mouseWheelEventAttached) {
327 		var form = this.getForm();
328 		var formElement = form.getHtmlElement();
329 		if (formElement.detachEvent) {
330 			if (window.event != null) window.event.cancelBubble = true;
331 			formElement.detachEvent("onmousewheel", OSelect1_XFormItem._mouseWheelHideMenu);
332 			OSelect1_XFormItem._mouseWheelEventAttached = false;
333 			OSelect1_XFormItem._mouseWheelCurrentSelect = null;
334 		}
335 	}
336 	this.menuUp = false;
337 	this.hideNote();
338 }
339 
340 OSelect1_XFormItem.prototype.moveMenuY = function (y, shorten, lengthen) {
341 	var menu = this.getMenuElement();
342 	if (menu == null) return; 
343 	var mBounds = this.getBounds(menu);
344 	var menuHeight = mBounds.height;
345 	var menuTop = mBounds.top;
346 	var newTop = parseInt(menuTop)+parseInt(y);
347 	var newBotton = parseInt(newTop)+parseInt(menuHeight);
348 	menu.style.top = newTop + 'px';
349 	//shorten the menu
350 	if(shorten) {
351 		menu.style.height = parseInt(menu.style.height)-Math.abs(parseInt(y)) + 'px';
352 	} else if(lengthen) {
353 		menu.style.height = parseInt(menu.style.height)+Math.abs(parseInt(y)) + 'px';
354 	}
355 	
356 }
357 
358 OSelect1_XFormItem.prototype.showNote = function(noteText, noteClass) {
359 	var note = this.getNoteElement();
360 	if(!note == null) return;
361 	note.className = noteClass ? noteClass : this.getNoteCssClass();
362 	note.innerHTML = noteText;	
363 	note.style.display = "block";
364 	var bounds;
365 	if(this.getInheritedProperty("editable")) {
366 		bounds = this.getBounds(this.getDisplayElement());
367 	} else {
368 		bounds = this.getBounds(this.getElement());
369 	}
370 	//note.style.width = menu.style.width;
371 	note.style.left = bounds.left + 'px';
372 	if(this.menuDirection == OSelect1_XFormItem.MENU_DIR_UP) {
373 		note.style.top = bounds.top + bounds.height + 'px';
374 		//this.moveMenuY((-1)*OSelect1_XFormItem.NOTE_HEIGHT,true,false);
375 	} else {
376 		note.style.top = bounds.top - OSelect1_XFormItem.NOTE_HEIGHT + 'px';
377 		//this.moveMenuY(OSelect1_XFormItem.NOTE_HEIGHT,true,false);
378 	}
379 	note.style.zIndex = 1000000;
380 	this.noteUp = true;
381 }
382 
383 OSelect1_XFormItem.prototype.hideNote = function() {
384 	if(!this.noteUp) return;
385 	var note = this.getNoteElement();
386 	if(!note == null) return;
387 	note.innerHTML = "";	
388 	note.style.display = "none";	
389 	note.style.zIndex = Dwt.Z_HIDDEN;
390 	this.noteUp = false;
391 }
392 
393 OSelect1_XFormItem.prototype.oMouseUp = function (ev) {
394 	// hide the menu on a timer so we don't have to deal with wierd selection bugs
395 	ev = ev || window.event;
396 	var found = false;
397     if (ev) {
398 		// figure out if we are over the menu that is up
399 		var htmlEl = DwtUiEvent.getTarget(ev);
400 		var inputId = this.getId()+"_display";
401 		var arrowId = this.getId() + "_arrow_button";
402 	//	DBG.println(AjxDebug.DBG1, AjxBuffer.concat("oMouseUp; htmlEl.nodeName=",htmlEl.nodeName," htmlEl.localName = ", htmlEl.nodeName));
403 		//check if the user clicked on the scrollbar
404 			if(htmlEl.localName == "scrollbar" && ( (htmlEl.parentNode && htmlEl.parentNode.id=="___OSELECT_MENU___") || (htmlEl.id && htmlEl.id=="___OSELECT_MENU___"))) { 
405 				found = true;
406 			} else if (htmlEl.id && htmlEl.id == "___OSELECT_MENU___"){
407 				found = true;
408 			} else if (htmlEl.id && htmlEl.id == inputId){
409 				found = true;
410 			} else if (htmlEl.id && htmlEl.id == arrowId){
411 				found = true;
412 			}
413 	}
414 
415 
416 	if(!found) {
417 		//DBG.println(AjxDebug.DBG1, "OSelect1_XFormItem.oMouseUp hiding menu time " +  (new Date()).getTime());
418 		this.hideMenu();
419 	}	
420 	return true;
421 }
422 
423 OSelect1_XFormItem.prototype.onOutsideMouseDown = function (ev) {
424 	// hide the menu on a timer so we don't have to deal with wierd selection bugs
425 	ev = ev || window.event;
426 	var found = false;
427 	var htmlEl;
428     if (ev) {
429 		// figure out if we are over the menu that is up
430 		htmlEl = DwtUiEvent.getTarget(ev);
431 		var inputId = this.getId()+"_display";
432 		var arrowId = this.getId() + "_arrow_button";
433 		if(htmlEl && htmlEl.attributes && htmlEl.attributes.length) {
434 			var cnt = htmlEl.attributes.length;
435 			for(var i = 0; i < cnt; i++) {
436 				if(htmlEl.attributes[i].name == "itemnum") {
437 					this.onChoiceClick(htmlEl.attributes[i].value, ev);
438 					found = true;
439 					break;
440 				}
441 			}
442 		}
443 		if(!found) {
444 		//	DBG.println(AjxDebug.DBG1, AjxBuffer.concat("onOutsideMouseDown; htmlEl.nodeName=", htmlEl.nodeName," htmlEl.localName = ", htmlEl.localName, " htmlEl.id=", htmlEl.id));
445 			//check if the user clicked on the scrollbar or on the input or on the arrow
446 			if(htmlEl.localName == "scrollbar" && ( (htmlEl.parentNode && htmlEl.parentNode.id=="___OSELECT_MENU___") || (htmlEl.id && htmlEl.id=="___OSELECT_MENU___"))) { 
447 				found = true;
448 			} else if (htmlEl.id && htmlEl.id == "___OSELECT_MENU___"){
449 				found = true;
450 			} else if (htmlEl.id && htmlEl.id == inputId) {
451 				found = true;				
452 			} else if (htmlEl.id && htmlEl.id == arrowId) {
453 				found = true;
454 			}
455 		}
456 		
457 	}
458 	if(!found) {
459 		//DBG.println(AjxDebug.DBG1, "OSelect1_XFormItem.onOutsideMouseDown hiding menu htmlEl id = " + htmlEl.id + " time " +  (new Date()).getTime());
460 		this.hideMenu();
461 	}	
462 	return true;
463 }
464 
465 OSelect1_XFormItem.prototype.getBounds = function(anElement, containerElement) {
466 	var myBounds = new Object();
467 	myBounds.left = 0;
468 	myBounds.top = 0;
469 	myBounds.width = anElement.clientWidth ? anElement.clientWidth: anElement.offsetWidth;
470 	myBounds.height = anElement.offsetHeight;
471 
472 	if(!containerElement) {
473 		containerElement = AjxEnv.isIE ? anElement.document.body : anElement.ownerDocument.body;
474 	}
475 
476 	// account for the scrollbars if necessary
477 	var hasScroll = (anElement.scrollLeft !== void 0);
478 	var trace = anElement;
479 
480 	while(trace !=null && trace != containerElement) {
481 		myBounds.left += trace.offsetLeft;
482 		myBounds.top += trace.offsetTop;
483 
484 		var nextEl = trace.offsetParent;
485 		while (hasScroll && (trace != nextEl)) {
486 			myBounds.left -= trace.scrollLeft;
487 			myBounds.top -= trace.scrollTop;
488 			trace = AjxEnv.isIE ? nextEl : trace.parentNode;
489 		}
490 		trace = nextEl;
491 	}
492 	return myBounds;
493 };
494 
495 
496 
497 // TAKE DIRECTLY FROM DWT_SELECT
498 OSelect1_XFormItem.prototype.onChoiceOver = function (itemNum, event) {
499 	if (this.__currentHiliteItem != null) this.dehiliteChoice(this.__currentHiliteItem);
500 	this.hiliteChoice(itemNum);
501 	this.__currentHiliteItem = itemNum;
502 }
503 OSelect1_XFormItem.prototype.onChoiceOut = function (itemNum, event) {
504 	if (this.__currentHiliteItem != null) this.dehiliteChoice(this.__currentHiliteItem);
505 	this.__currentHiliteItem = null;
506 }
507 OSelect1_XFormItem.prototype.onChoiceClick = function (itemNum, event) {
508 	this.choiceSelected(itemNum, false, event);
509 }
510 
511 OSelect1_XFormItem.prototype.onChoiceDoubleClick = function (itemNum, event) {
512 	this.choiceSelected(itemNum, true, event);
513 }
514 
515 OSelect1_XFormItem.prototype.onValueTyped = function(label, event) {	
516 	var value = this.getChoiceValue(label);
517 	if(window.console && window.console.log) console.log("onValueTyped called value: " + value);
518 	this.setValue(value, false, event);
519 }
520 
521 OSelect1_XFormItem.prototype.onKeyUp = function(value, event) {
522 
523 	if(event.keyCode==XFG.ARROW_UP) {
524 		if(!this.menuUp)
525 			this.showMenu();
526 		
527 		this.hilitePreviousChoice(event);
528 		this.isSelecting = true;
529 		return;
530 	} 
531 	
532 	if(event.keyCode==XFG.ARROW_DOWN) {
533 		if(!this.menuUp)
534 			this.showMenu();
535 			
536 		this.hiliteNextChoice(event);
537 		this.isSelecting = true;
538 		return;
539 	} 
540 		
541 	if(this.isSelecting && this.menuUp && event.keyCode==DwtKeyEvent.KEY_ENTER && this.__currentHiliteItem != null && this.__currentHiliteItem != undefined) {
542 		var value = this.getNormalizedValues()[this.__currentHiliteItem];
543 		if(value != null && value != undefined) {
544 //			DBG.println(AjxDebug.DBG1, "OSelect1_XFormItem.onKeyUp handled key code "+ event.keyCode +" char code " + (new Date()).getTime());
545 			this.setValue(value, true, event);
546 			this.hideMenu();
547 			return;
548 		}
549 	} 
550 	this.isSelecting = false;		
551 	var method = this.getKeyUpMethod();
552 	if(method)
553 		method.call(this, value, event);
554 }
555 
556 OSelect1_XFormItem.prototype.getKeyUpMethod = function () {
557 	return this.cacheInheritedMethod("keyUp","$keyUp","elementValue, event");
558 }
559 
560 OSelect1_XFormItem.prototype.choiceSelected = function (itemNum, clearOldValues, event) {
561 	this.onChoiceOut();
562 	//DBG.println(AjxDebug.DBG1, "OSelect1_XFormItem.choiceSelected hiding menu "+  (new Date()).getTime());
563 	this.hideMenu();
564 	var value = this.getNormalizedValues()[itemNum];
565 	var editable = this.getInheritedProperty("editable");
566 	if(editable) {
567 		this.getDisplayElement().value = this.getNormalizedLabels()[itemNum];
568 	}
569 	this.setValue(value, clearOldValues, event);
570 }
571 
572 OSelect1_XFormItem.prototype.hiliteNextChoice = function() {
573 	var choices = this.getNormalizedChoices();
574 	if(!(choices && choices.values && choices.values.length>0)) {
575 		return;
576 	}
577 	
578 	if(this.__currentHiliteItem == null || this.__currentHiliteItem == undefined) {
579 		this.hiliteChoice(0);
580 	} else { 
581 		this.dehiliteChoice(this.__currentHiliteItem);
582 		if ((this.__currentHiliteItem+1) < choices.values.length) {
583 			this.__currentHiliteItem++;
584 		} else {
585 			this.__currentHiliteItem = 0;
586 		}
587 		this.hiliteChoice(this.__currentHiliteItem);
588 	}
589 }
590 	
591 OSelect1_XFormItem.prototype.hilitePreviousChoice = function() {
592 	var choices = this.getNormalizedChoices();
593 	if(!(choices && choices.values && choices.values.length>0)) {
594 		return;
595 	}
596 	
597 	if(this.__currentHiliteItem == null || this.__currentHiliteItem == undefined) {
598 		this.hiliteChoice(0);
599 	} else { 
600 		this.dehiliteChoice(this.__currentHiliteItem);
601 		
602 		if ((this.__currentHiliteItem-1) > -1) {
603 			this.__currentHiliteItem--;
604 		} else {
605 			this.__currentHiliteItem = choices.values.length-1;
606 		}
607 		this.hiliteChoice(this.__currentHiliteItem);
608 	}
609 }	
610 
611 
612 OSelect1_XFormItem.prototype.setValue = function (newValue, clearOldValues, event) {
613 	if(window.console && window.console.log) console.log("setValue called + " + newValue);
614 	var method = this.getElementChangedMethod();
615 	method.call(this, newValue, this.getInstanceValue(), event);
616 }
617 
618 OSelect1_XFormItem.prototype.hiliteChoice = function (itemNum) {
619 	this.setChoiceCssClass(itemNum, this.getChoiceSelectedCssClass());
620 	if (this.getShowCheck() == true) {
621 		var els = this.getChoiceElements(itemNum);
622 		if (els) els[0].innerHTML = this.getCheckHTML();
623 	}
624 }
625 
626 OSelect1_XFormItem.prototype.displayMouseOver = function () {
627 	if(!this._enabled)
628 		return;
629 }
630 
631 OSelect1_XFormItem.prototype.displayMouseOut = function () {
632 	if(!this._enabled)
633 		return;
634 }
635 
636 OSelect1_XFormItem.prototype.displayMouseDown = function () {
637 	if(!this._enabled)
638 		return;
639 }
640 
641 OSelect1_XFormItem.prototype.dehiliteChoice = function(itemNum) {
642 	this.setChoiceCssClass(itemNum, this.getChoiceCssClass());
643 	if (this.getShowCheck() == true) {
644 		var els = this.getChoiceElements(itemNum);
645 		if (els) els[0].innerHTML = " ";
646 	}
647 }
648 
649 
650 OSelect1_XFormItem.prototype.clearAllHilites = function () {
651 	for (var i = 0; i < this._normalizedValues.length; i++) {
652 		this.dehiliteChoice(i);
653 	}
654 }
655 
656 
657 
658 OSelect1_XFormItem.prototype.setChoiceCssClass = function (itemNum, cssClass) {
659 	var els = this.getChoiceElements(itemNum);
660 	if (els) {
661 		els.className = cssClass;
662 	}
663 }
664 
665 OSelect1_XFormItem.prototype.getArrowElement = function () {
666 	return this.getForm().getElement(this.getId() + "_arrow_button");
667 }
668 
669 OSelect1_XFormItem.prototype.getDisplayElement = function () {
670 	return this.getElement(this.getId() + "_display");
671 }
672 
673 
674 OSelect1_XFormItem.prototype.getItemNumFromEvent = function (event) {
675 	var target = event.target || event.src;
676 	while (target) {
677 		if (target.id) {
678 			var itemNum = parseInt(target.id);
679 			if (isNaN(itemNum)) return -1;
680 			return itemNum;
681 		}
682 		target = target.parentNode;
683 	}
684 	return -1;
685 }
686 
687 OSelect1_XFormItem.prototype.getChoiceElements = function (itemNum) {
688 	if (itemNum == null || itemNum == -1) return null;
689 	try {
690 		return this.getForm().getElement([this.getId(), "_choice_",itemNum].join(""));
691 	} catch (e) {
692 		return null;
693 	}
694 }
695 
696 
697 OSelect1_XFormItem.prototype.outputHTML = function (HTMLoutput) {
698 	var id = this.getId();
699 	var ref = this.getFormGlobalRef() + ".getItemById('"+ id + "')";	
700 	var inputHtml;
701 	var editable = this.getInheritedProperty("editable");
702 	if(editable) {
703 		var inputSize = this.getInheritedProperty("inputSize");		
704 		inputHtml = ["<input type=text id=", id, "_display class=", this.getDisplayCssClass(), " value='VALUE' ", 
705 					" onchange=\"",ref, ".onValueTyped(this.value, event||window.event)\"",
706 					" onmouseup=\"", ref, ".showMenu(this)\"",
707 					" onkeyup=\"",ref, ".onKeyUp(this.value, event||window.event)\"", "size=",inputSize,
708 					">"].join("");
709 	}
710 	
711 	if (this.getWidth() == "auto" && !editable) {
712 		var element = this.getElement("tempDiv");
713 		if(!element) 
714 			element = this.createElement("tempDiv", null, "div", "MENU CONTENTS");
715 		element.style.left = '-1000px';
716 		element.style.top = '-1000px';
717 		element.className = this.getMenuCssClass();
718 		element.innerHTML = this.getChoicesHTML();
719 		this._width = element.offsetWidth+20;
720 		element.innerHTML = "";
721 	}
722 
723 	
724 	if(editable) {
725 		HTMLoutput.append(
726 			"<div id=", id, this.getCssString(),
727 				" onclick=\"", this.getFormGlobalRef(), ".getItemById('",this.getId(),"').showMenu(this)\"",
728 				" onselectstart=\"return false\"",
729 				">",
730 				"<table ", this.getTableCssString(), ">", 
731 					"<tr><td width=100%>",inputHtml,"</td>",
732 						"<td>", this.getArrowButtonHTML(),"</td>", 
733 					"</tr>", 
734 				"</table>", 
735 			"</div>"
736 		);
737 	} else {
738 		HTMLoutput.append(
739 			"<div id=", id, this.getCssString(),
740 				" onclick=\"", this.getFormGlobalRef(), ".getItemById('",this.getId(),"').showMenu(this)\"",
741 				" onselectstart=\"return false\"",
742 				"><table ", this.getTableCssString(), ">",
743 					"<tr><td width=100%><div id=", id, "_display class=", this.getDisplayCssClass(), ">VALUE</div></td>",
744 						"<td>", this.getArrowButtonHTML(),"</td>", 
745 					"</tr>", 
746 				"</table>", 
747 			"</div>"
748 		);	
749 	}
750 }
751 
752 OSelect1_XFormItem.prototype.getArrowButtonHTML = function () {
753 	var ref = this.getFormGlobalRef() + ".getItemById('"+ this.getId()+ "')";
754 	return AjxBuffer.concat("<div id=", this.getId(), "_arrow_button",
755 	 " onmouseover=\"", ref, ".displayMouseOver();\"",
756  	 " onmouseout=\"", ref, ".displayMouseOut();\"",
757  	 " onmousedown=\"", ref, ".displayMouseDown();\"", 	 
758  	 ">", AjxImg.getImageHtml("SelectPullDownArrow"), "</div>");
759 }
760 
761 OSelect1_XFormItem.prototype.getTableCssClass = function () {
762 	return this.cssClass + "_table";
763 }
764 OSelect1_XFormItem.prototype.getDisplayCssClass = function () {
765 	return this.cssClass + "_display";
766 }
767 
768 OSelect1_XFormItem.prototype.getMenuCssClass = function () {
769 	return this.cssClass + "_menu";
770 }
771 OSelect1_XFormItem.prototype.getChoiceTableCssClass = function () {
772 	return this.cssClass + "_choice_table";
773 }
774 OSelect1_XFormItem.prototype.getChoiceScrollTableCssClass = function () {
775 	return this.cssClass + "_choice_table_scrolled";
776 }
777 
778 OSelect1_XFormItem.prototype.getChoiceCssClass = function () {
779 	return this.cssClass + "_choice";
780 }
781 OSelect1_XFormItem.prototype.getChoiceSelectedCssClass = function () {
782 	return this.cssClass + "_choice_selected";
783 }
784 
785 OSelect1_XFormItem.prototype.getNoteCssClass = function () {
786 	return this.cssClass + "_note";
787 }
788 
789 OSelect1_XFormItem.prototype.getErrorNoteCssClass = function () {
790 	return this.cssClass + "_error_note";
791 }
792 
793 OSelect1_XFormItem.prototype.outputChoicesHTMLStart = function(html) {
794 	html.append("<table cellspacing=0 cellpadding=0 id=", this.getId(),"_menu_table class=", this.getChoiceTableCssClass(), ">");
795 	
796 }
797 OSelect1_XFormItem.prototype.outputChoicesHTMLEnd = function(html) {
798 	html.append("</table>");
799 }
800 
801 OSelect1_XFormItem.prototype.getChoiceHTML = function (itemNum, value, label, cssClass) {
802 	var ref = this.getFormGlobalRef() + ".getItemById('"+ this.getId()+ "')";
803 	//try DIVs
804 	return AjxBuffer.concat("<tr><td><div id=\"", this.getId(), "_choice_", itemNum, "\" ", "class=", cssClass, 
805 			" onmouseover=\"",ref, ".onChoiceOver(", itemNum,", event||window.event)\"",
806 			" onmouseout=\"",ref, ".onChoiceOut(", itemNum,", event||window.event)\"",
807 			" onclick=\"",ref, ".onChoiceClick(", itemNum,", event||window.event)\"",
808 			" itemnum = '", itemNum, "'",">",label,	"</div></td></tr>");
809 	
810 }
811 
812 
813 // set up how disabling works for this item type
814 OSelect1_XFormItem.prototype.setElementEnabled = function(enabled) {
815 	this._enabled = enabled;
816 	var table = this.getForm().getElement(this.getId()).getElementsByTagName("table")[0];
817 	if(enabled) {
818 		this.getDisplayElement().className = this.getDisplayCssClass();
819 		var el = this.getArrowElement();
820 		if(el)
821 			AjxImg.setImage(el, "SelectPullDownArrow");
822 			
823 		this.getForm().getElement(this.getId()).className = this.cssClass;
824 		table.className = this.getTableCssClass();
825 		if(this.getInheritedProperty("editable")) {
826 			this.getDisplayElement().disabled=false;
827 		}
828 	} else {
829 		this.getDisplayElement().className = this.getDisplayCssClass() + "_disabled";
830 		var el = this.getArrowElement();
831 		/*if(el)
832 			AjxImg.setImage(el, "SelectPullDownArrowDis");
833 		*/	
834 		this.getForm().getElement(this.getId()).className = this.cssClass + "_disabled";
835 		table.className = this.getTableCssClass()+"_disabled";
836 		if(this.getInheritedProperty("editable")) {
837 			this.getDisplayElement().disabled=true;
838 		}
839 	}
840 }
841 
842 //
843 //	OSelect class -- lightning fast SELECT type widget
844 //
845 OSelect_XFormItem = function() {}
846 XFormItemFactory.createItemType("_OSELECT_", "oselect", OSelect_XFormItem, OSelect1_XFormItem);
847 
848 OSelect_XFormItem.prototype.focusable = false;
849 OSelect_XFormItem.prototype.multiple = true;
850 OSelect_XFormItem.prototype.writeElementDiv = true;
851 OSelect_XFormItem.prototype.overflow = "auto";
852 OSelect_XFormItem.prototype.cssStyle = "border:2px inset gray;";
853 OSelect_XFormItem.prototype.showCheck = false;
854 
855 OSelect_XFormItem.prototype.outputHTML = function(html) {
856 	var it = this.getChoicesHTML();
857 	html.append(it);
858 }
859 
860 OSelect_XFormItem.prototype.choicesChangeLsnr = function () {
861 	this._choiceDisplayIsDirty = true;
862 	delete this.$normalizedChoices;
863 	var element = this.getElement();
864 	if(element)
865 		element.innerHTML = this.getChoicesHTML();	
866 }
867 
868 OSelect_XFormItem.prototype.outputChoicesHTMLStart = function(html) {
869 	html.append("<table id=", this.getId(),"_menu_table width=100% cellspacing=2 cellpadding=0>");
870 }
871 OSelect_XFormItem.prototype.outputChoicesHTMLEnd = function(html) {
872 	html.append("</table>");
873 }
874 
875 
876 OSelect_XFormItem.prototype.getMenuElementId = function () {
877 	return this.getId();
878 }
879 
880 OSelect_XFormItem.prototype.updateElement = function (values) {
881 	var element = this.getElement();
882 	element.innerHTML = this.getChoicesHTML();
883 
884 	if (values == null) return;	
885 	if(this.getMultiple()) {
886 		if (typeof values == "string") values = values.split(",");
887 		for (var i = 0; i < values.length; i++) {
888 			var itemNum = this.getChoiceNum(values[i]);
889 			if (itemNum != -1) this.hiliteChoice(itemNum);
890 		}
891 	} else {
892 		var itemNum = this.getChoiceNum(values);
893 		if (itemNum != -1) this.hiliteChoice(itemNum);
894 	}
895 
896     //updateEnabledDisabled() should run after the element is created.
897     //OSelect_XFormItem updateElement will redraw the elements.
898     //The redraw of the elements will screw the enable disable state of the element
899     //So we update the enable disable state after the redraw.      
900     this.updateEnabledDisabled();
901 }
902 
903 OSelect_XFormItem.prototype.onChoiceOver = function (itemNum) {}
904 OSelect_XFormItem.prototype.onChoiceOut = function (itemNum) {}
905 
906 OSelect_XFormItem.prototype.onChoiceClick = function (itemNum, event) {
907 	event = event || window.event;
908 	var clearOthers = true;
909 	var includeIntermediates = false;
910 	
911 	if(this.getMultiple()) {
912 		clearOthers = false;
913 		if (event.shiftKey) {
914 			includeIntermediates = true;
915 		}
916 	}
917 	
918 	this.choiceSelected(itemNum, clearOthers, includeIntermediates, event);
919 };
920 
921 OSelect_XFormItem.prototype.choiceSelected = function (itemNum, clearOldValues, includeIntermediates, event) {
922 	if (includeIntermediates){
923 		this._selectionCursor = itemNum;
924 		if (this._selectionAnchor == null) {
925 			this._selectionAnchor = itemNum;
926 		}
927 	} else {
928 		this._selectionAnchor = itemNum;
929 		this._selectionCursor = itemNum;
930 	}
931 
932 	var value = this.getNormalizedValues()[itemNum];
933 	this.setValue(value, clearOldValues, includeIntermediates, event);
934 }
935 
936 OSelect_XFormItem.prototype.setValue = function (newValue, clearOldValues, includeIntermediates, event) {
937 
938 	var newValues;
939 	if (clearOldValues) {
940 		if(this.getMultiple()) {
941 			if(newValue instanceof Array)
942 				newValues = newValue;
943 			else
944 				newValues = [newValue];
945 		} else {
946 			newValues = newValue;
947 		}
948 	} else {
949 		if (includeIntermediates) {
950 			newValues = [];
951 			var vals = this.getNormalizedValues();
952 			var start = this._selectionCursor;
953 			var dist = this._selectionAnchor - this._selectionCursor;
954 			if (dist < 0 ) {
955 				dist = this._selectionCursor - this._selectionAnchor;
956 				start = this._selectionAnchor;
957 			}
958 			for (var i = start; i <= start + dist; ++i) {
959 				newValues.push(vals[i]);
960 			}
961 		} else {
962 			var oldValues = this.getInstanceValue();
963 			if(typeof oldValues == "string") {
964 				newValues = oldValues;
965 			} else if(typeof oldValues =="object" || oldValues instanceof Array) {
966 				newValues = [];
967 				for(var a in oldValues) {
968 					newValues[a] = oldValues[a];
969 				}
970 			}
971 			if(newValues) {
972 				if (typeof newValues == "string") {
973 					if (newValues == "") 	
974 						newValues = [];
975 					else
976 						newValues = newValues.split(",");
977 				}
978 			} else {
979 				newValues = new Array();			
980 			}			
981 			
982 			var found = false;
983 			var i;
984 			for (i = 0; i < newValues.length; i++) {
985 				if (newValues[i] == newValue) {
986 					found = true;
987 					break;
988 				}
989 			}
990 			
991 			if (found) {
992 				newValues.splice(i, 1);
993 			} else {
994 				newValues.push(newValue);
995 			}
996 		}
997 		if(!newValues || (newValues.length == 1 && newValues[0] == "")) {
998 			newValues = []
999 		} 
1000 		// if we have a modelItem which is a LIST type
1001 		//	convert the output to the propert outputType
1002 		var modelItem = this.getModelItem();
1003 		if (modelItem && modelItem.getOutputType) {
1004 			if (modelItem.getOutputType() == _STRING_) {
1005 				newValues = newValues.join(modelItem.getItemDelimiter());
1006 			}
1007 		} else {
1008 			// otherwise assume we should convert it to a comma-separated string
1009 			newValues = newValues.join(",");
1010 		}
1011 	}
1012 	this.getForm().itemChanged(this, newValues, event);
1013 }
1014 
1015 OSelect_XFormItem.prototype.setElementEnabled = function (enabled) {
1016 	var choices = this.getNormalizedChoices();
1017 	if(!choices)
1018 		return;
1019 	
1020 	var values = choices.values;
1021 	if(!values)
1022 		return;
1023 		
1024 	var cnt = values.length;
1025 	for(var i=0; i < cnt; i ++) {
1026 		var chkbx = this.getElement(this.getId() + "_choiceitem_" + i);	
1027 		if(chkbx) {
1028 			if(enabled) {
1029 				chkbx.className = this.getChoiceCssClass();
1030 				chkbx.disabled = false;
1031 			} else {
1032 				chkbx.className = this.getChoiceCssClass() + "_disabled";
1033 				chkbx.disabled = true;
1034 			}
1035 		} 
1036 	}
1037 };
1038 
1039 
1040 
1041 
1042 OSelect_Check_XFormItem = function() {}
1043 XFormItemFactory.createItemType("_OSELECT_CHECK_", "oselect_check", OSelect_Check_XFormItem, OSelect_XFormItem)
1044 OSelect_Check_XFormItem.prototype.cssClass = "oselect_check";
1045 OSelect_Check_XFormItem.prototype.getChoiceHTML = function (itemNum, value, label, cssClass) {
1046 	var ref = this.getFormGlobalRef() + ".getItemById('"+ this.getId()+ "')";
1047 	var id = this.getId();
1048 
1049 /*
1050  	// Bug 44925
1051  	// The checkbox label is always on activated status. Since it is not a standard XForm component,
1052  	// it is not controlled by enableDisableChecks property.
1053 
1054 	return AjxBuffer.concat(
1055 		"<tr><td class=", cssClass, 
1056 			" onmouseover=\"",ref, ".onChoiceOver(", itemNum,", event||window.event)\"",
1057 			" onmouseout=\"",ref, ".onChoiceOut(", itemNum,", event||window.event)\"",
1058 			" onclick=\"",ref, ".onChoiceClick(", itemNum,", event||window.event)\"",
1059 			" ondblclick=\"",ref, ".onChoiceDoubleClick(", itemNum,", event||window.event)\"",
1060 		">",
1061 		"<table cellspacing=0 cellpadding=0><tr><td><input type=checkbox id='",id,"_choiceitem_",itemNum,"'></td><td>",
1062 				label,                     //<--  the label is always on activated status
1063 		"</td></tr></table></td></tr>"
1064 	);
1065 */
1066 
1067 	// The bugfixing for bug 44925
1068 	// By checking the __isEnabled property via getIsEnabled(), the fixing can make the label working with
1069 	// checkbox under same property: 
1070 	//     1) both should be in grey(disabled) when the item is disabled, vise versa;
1071 	//     2) both should be removed all the event handlers on element when it is disabled, vise versa.
1072 
1073         return AjxBuffer.concat(
1074                 "<tr><td class=", cssClass,
1075                         (this.getIsEnabled())?(" onmouseover=\"" + ref + ".onChoiceOver(" + itemNum + ", event||window.event)\""):"",
1076                         (this.getIsEnabled())?(" onmouseout=\"" + ref +  ".onChoiceOut(" + itemNum + ", event||window.event)\""):"",
1077                         (this.getIsEnabled())?(" onclick=\"" + ref + ".onChoiceClick(" + itemNum + ", event||window.event)\""):"",
1078                         (this.getIsEnabled())?(" ondblclick=\"" + ref + ".onChoiceDoubleClick(" + itemNum + ", event||window.event)\""):"",
1079                 ">",
1080                 "<table cellspacing=0 cellpadding=0><tr><td><input type=checkbox id='",id,"_choiceitem_",itemNum,"'></td><td>",
1081                                 (!this.getIsEnabled())?("<font color=\"#808080\">"):"", label,(!this.getIsEnabled())?("</font>"):"",
1082                 "</td></tr></table></td></tr>"
1083         );
1084 
1085 }
1086 
1087 
1088 OSelect_Check_XFormItem.prototype.hiliteChoice = function (itemNum) {
1089 	var chEl = this.getChoiceElements(itemNum);
1090 	if(chEl) {
1091 		var el = chEl[0];
1092 		el.className = this.getChoiceSelectedCssClass();
1093 	
1094 		var checks = el.getElementsByTagName("input");
1095 		if (checks) {
1096 			checks[0].checked = true;
1097 		}
1098 	}
1099 }
1100 
1101 OSelect_Check_XFormItem.prototype.dehiliteChoice = function(itemNum) {
1102 	var chEl = this.getChoiceElements(itemNum);
1103 	if(chEl) {
1104 		var el = chEl[0];
1105 		el.className = this.getChoiceCssClass();
1106 
1107 		var checks = el.getElementsByTagName("input");
1108 		if (checks) {
1109 			checks[0].checked = false;
1110 		}
1111 	}
1112 }
1113 
1114 OSelect_Check_XFormItem.prototype.getChoiceElements = function (itemNum) {
1115 	if (itemNum == null || itemNum == -1) return null;
1116 	try {
1117 		return this.getForm().getElement(this.getId() + "_menu_table").rows[itemNum].getElementsByTagName("td");
1118 	} catch (e) {
1119 		return null;
1120 	}
1121 }
1122 
1123 OSelect_Check_XFormItem.prototype.selectAll = function (ev) {
1124 	var newValues = [];
1125 	if(this.$normalizedChoices && this.$normalizedChoices.values) {
1126 		var choices = this.$normalizedChoices.values;
1127 		var cnt = choices.length;
1128 		for(var i =0; i < cnt; i ++) {
1129 			newValues.push(choices[i]);
1130 		}
1131 	}
1132 	this.setValue(newValues,true,false,ev);
1133 }
1134 
1135 OSelect_Check_XFormItem.prototype.deselectAll = function (ev) {
1136 	this.getForm().itemChanged(this, [], ev);
1137 }
1138 
1139 OSelect_Check_XFormItem.prototype.updateElement = function (values) {
1140 	var element = this.getElement();
1141 	element.innerHTML = this.getChoicesHTML();
1142 	this.clearAllHilites();
1143 	if (values) {	
1144 		if(this.getMultiple()) {
1145 			if (typeof values == "string") values = values.split(",");
1146 			for (var i = 0; i < values.length; i++) {
1147 				var itemNum = this.getChoiceNum(values[i]);
1148 				if (itemNum != -1) this.hiliteChoice(itemNum);
1149 			}
1150 		} else {
1151 			var itemNum = this.getChoiceNum(values);
1152 			if (itemNum != -1) this.hiliteChoice(itemNum);
1153 		}
1154 	}
1155     this.updateEnabledDisabled();
1156 }
1157 
1158 OSelect_Check_XFormItem.prototype.clearAllHilites = function () {
1159 	var choices = this.getNormalizedChoices();
1160 	var cnt;
1161 	if(choices.values) {
1162 		cnt = choices.values.length;
1163 		for(var i=0; i< cnt; i++) {
1164 			this.dehiliteChoice(i);		
1165 		}
1166 	}
1167 }
1168 
1169 OSelect_DblCheck_XFormItem = function() {}
1170 XFormItemFactory.createItemType("_OSELECT_DBL_CHECK_", "oselect_dbl_check", OSelect_DblCheck_XFormItem, OSelect_Check_XFormItem)
1171 
1172 OSelect_DblCheck_XFormItem.prototype.onSubChoiceOver = function (itemNum) {}
1173 OSelect_DblCheck_XFormItem.prototype.onSubChoiceOut = function (itemNum) {}
1174 
1175 OSelect_DblCheck_XFormItem.prototype.onSubChoiceClick = function (itemNum, event) {
1176 	event = event || window.event;
1177 	var clearOthers = true;
1178 	var includeIntermediates = false;
1179 	
1180 	if(this.getMultiple()) {
1181 		clearOthers = false;
1182 		if (event.shiftKey) {
1183 			includeIntermediates = true;
1184 		}
1185 	}
1186 	
1187 	this.subChoiceSelected(itemNum, clearOthers, includeIntermediates, event);
1188 };
1189 
1190 OSelect_DblCheck_XFormItem.prototype.subChoiceSelected = function (itemNum, clearOldValues, includeIntermediates, event) {
1191 	if (includeIntermediates){
1192 		this._subSelectionCursor = itemNum;
1193 		if (this._subSelectionAnchor == null) {
1194 			this._subSselectionAnchor = itemNum;
1195 		}
1196 	} else {
1197 		this._subSelectionAnchor = itemNum;
1198 		this._subSelectionCursor = itemNum;
1199 	}
1200 
1201 	var value = this.getNormalizedValues()[itemNum];
1202 	this.setSubValue(value, clearOldValues, includeIntermediates, event);
1203 }
1204 
1205 OSelect_DblCheck_XFormItem.prototype.setSubValue = function (newValue, clearOldValues, includeIntermediates, event) {
1206 	var newValues;
1207 
1208 	if (clearOldValues) {
1209 		if(this.getMultiple()) {
1210 			if(newValue instanceof Array)
1211 				newValues = newValue;
1212 			else
1213 				newValues = [newValue];
1214 		} else {
1215 			newValues = newValue;
1216 		}
1217 	} else {
1218 		if (includeIntermediates) {
1219 			newValues = [];
1220 			var vals = this.getNormalizedValues();
1221 			var start = this._subSelectionCursor;
1222 			var dist = this._subSelectionAnchor - this._subSelectionCursor;
1223 			if (dist < 0 ) {
1224 				dist = this._subSelectionCursor - this._subSelectionAnchor;
1225 				start = this._subSelectionAnchor;
1226 			}
1227 			for (var i = start; i <= start + dist; ++i) {
1228 				newValues.push(vals[i]);
1229 			}
1230 		} else {
1231 			var oldValues = this.getInstanceValue(this.getInheritedProperty("subRef"));
1232 			if(typeof oldValues == "string") {
1233 				newValues = new String(oldValues);
1234 			} else if(typeof oldValues =="object" || oldValues instanceof Array) {
1235 				newValues = [];
1236 				for(var a in oldValues) {
1237 					newValues[a] = oldValues[a];
1238 				}
1239 			}
1240 			if(newValues) {
1241 				if (typeof newValues == "string") {
1242 					if (newValues == "") 	
1243 						newValues = [];
1244 					else
1245 						newValues = newValues.split(",");
1246 				}
1247 			} else {
1248 				newValues = new Array();			
1249 			}			
1250 			
1251 			var found = false;
1252 			for (var i = 0; i < newValues.length; i++) {
1253 				if (newValues[i] == newValue) {
1254 					found = true;
1255 					break;
1256 				}
1257 			}
1258 			
1259 			if (found) {
1260 				newValues.splice(i, 1);
1261 			} else {
1262 				newValues.push(newValue);
1263 			}
1264 		}
1265 		if(!newValues || (newValues.length == 1 && newValues[0] == "")) {
1266 			newValues = []
1267 		} 
1268 		// if we have a modelItem which is a LIST type
1269 		//	convert the output to the propert outputType
1270 		var modelItem = this.getSubModelItem();
1271 		if (modelItem && modelItem.getOutputType) {
1272 			if (modelItem.getOutputType() == _STRING_) {
1273 				newValues = newValues.join(modelItem.getItemDelimiter());
1274 			}
1275 		} else {
1276 			// otherwise assume we should convert it to a comma-separated string
1277 			newValues = newValues.join(",");
1278 		}
1279 	}
1280 	this.getForm().subItemChanged(this, newValues, event);
1281 }
1282 
1283 OSelect_DblCheck_XFormItem.prototype.getSubLabel = function () {
1284 	return this.getInheritedProperty("subLabel");	
1285 }
1286 
1287 OSelect_DblCheck_XFormItem.prototype.getChoiceHTML = function (itemNum, value, label, cssClass) {
1288 	var ref = this.getFormGlobalRef() + ".getItemById('"+ this.getId()+ "')";
1289 	var id = this.getId();
1290 	var subLabel = this.getSubLabel();
1291 	return AjxBuffer.concat(
1292 		"<tr><td class=", cssClass, 
1293 			" onmouseover=\"",ref, ".onChoiceOver(", itemNum,", event||window.event)\"",
1294 			" onmouseout=\"",ref, ".onChoiceOut(", itemNum,", event||window.event)\"",
1295 			" onclick=\"",ref, ".onChoiceClick(", itemNum,", event||window.event)\"",
1296 			" ondblclick=\"",ref, ".onChoiceDoubleClick(", itemNum,", event||window.event)\">",
1297 				"<table cellspacing=0 cellpadding=0><tr><td><input type=checkbox id='",id,"_choiceitem_",itemNum,"'></td><td>",
1298 				label,
1299 				"</td></tr></table>",
1300 			"</td><td class=",cssClass,
1301 				" onmouseover=\"",ref,".onSubChoiceOver(", itemNum, ", event||window.event)\"",
1302 				" onmouseout=\"",ref, ".onSubChoiceOut(", itemNum, ", event||window.event)\"",
1303 				" onclick=\"",ref, ".onSubChoiceClick(", itemNum, ", event||window.event)\"",
1304 				" ondblclick=\"",ref, ".onSubChoiceDoubleClick(", itemNum, ".event||window.event)\">",
1305 					"<table cellspacing=0 cellpadding=0><tr><td><input type=checkbox id='",id,"_subchoiceitem_",itemNum,"'></td><td>",
1306 				subLabel,
1307 				"</td></tr></table>",
1308 		"</td></tr>"
1309 	);
1310 }
1311 
1312 OSelect_DblCheck_XFormItem.prototype.hiliteChoice = function (itemNum) {
1313 	var chEl = this.getChoiceElements(itemNum);
1314 	if(chEl) {
1315 		var el = chEl[0];
1316 		el.className = this.getChoiceSelectedCssClass();
1317 	
1318 		var checks = el.getElementsByTagName("input");
1319 		if (checks) {
1320 			checks[0].checked = true;
1321 			this.enableSubChoice(itemNum);
1322 		}
1323 	}
1324 }
1325 
1326 OSelect_DblCheck_XFormItem.prototype.dehiliteChoice = function(itemNum) {
1327 	var chEl = this.getChoiceElements(itemNum);
1328 	if(chEl) {
1329 		var el = chEl[0];
1330 		el.className = this.getChoiceCssClass();
1331 
1332 		var checks = el.getElementsByTagName("input");
1333 		if (checks) {
1334 			checks[0].checked = false;
1335 			this.dehiliteSubChoice(itemNum);
1336 			this.disableSubChoice(itemNum);
1337 		}
1338 	}
1339 }
1340 
1341 OSelect_DblCheck_XFormItem.prototype.hiliteSubChoice = function (itemNum) {
1342 	var chEl = this.getChoiceElements(itemNum);
1343 	if(chEl) {
1344 		var el = chEl[3];
1345 		el.className = this.getChoiceSelectedCssClass();
1346 
1347 		var checks = el.getElementsByTagName("input");
1348 		if (checks) {
1349 			checks[0].checked = true;
1350 		}
1351 	}
1352 }
1353 
1354 OSelect_DblCheck_XFormItem.prototype.dehiliteSubChoice = function(itemNum) {
1355 	var chEl = this.getChoiceElements(itemNum);
1356 	if(chEl) {
1357 		var el = chEl[3];
1358 		el.className = this.getChoiceCssClass();
1359 
1360 		var checks = el.getElementsByTagName("input");
1361 		if (checks) {
1362 			checks[0].checked = false;
1363 		}
1364 	}
1365 }
1366 
1367 OSelect_DblCheck_XFormItem.prototype.disableSubChoice = function (itemNum) {
1368 	var chEl = this.getChoiceElements(itemNum);
1369 	if(chEl) {
1370 		var el = chEl[3];
1371 		el.className = this.getChoiceCssClass() + "_disabled";
1372 
1373 		var checks = el.getElementsByTagName("input");
1374 		if (checks) {
1375 			checks[0].disabled = true;
1376 		}
1377 	}
1378 }
1379 
1380 OSelect_DblCheck_XFormItem.prototype.enableSubChoice = function (itemNum) {
1381 	var chEl = this.getChoiceElements(itemNum);
1382 	if(chEl) {
1383 		var el = chEl[3];
1384 		el.className = this.getChoiceCssClass();
1385 
1386 		var checks = el.getElementsByTagName("input");
1387 		if (checks) {
1388 			checks[0].disabled = false;
1389 		}
1390 	}
1391 }
1392 
1393 
1394 OSelect_DblCheck_XFormItem.prototype.updateElement = function () {
1395 	var element = this.getElement();
1396 	element.innerHTML = this.getChoicesHTML();
1397 	var values = this.getInstanceValue();
1398 	this.clearAllHilites();
1399 	if (values) {	
1400 		if(this.getMultiple()) {
1401 			if (typeof values == "string") values = values.split(",");
1402 			for (var i = 0; i < values.length; i++) {
1403 				var itemNum = this.getChoiceNum(values[i]);
1404 				if (itemNum != -1) this.hiliteChoice(itemNum);
1405 			}
1406 		} else {
1407 			var itemNum = this.getChoiceNum(values);
1408 			if (itemNum != -1) this.hiliteChoice(itemNum);
1409 		}
1410 	}
1411 	
1412 	var subValues = this.getInstanceValue(this.getInheritedProperty("subRef"));
1413 	if (subValues) {	
1414 		if(this.getMultiple()) {
1415 			if (typeof subValues == "string") subValues = subValues.split(",");
1416 			for (var i = 0; i < subValues.length; i++) {
1417 				var itemNum = this.getChoiceNum(subValues[i]);
1418 				if (itemNum != -1) this.hiliteSubChoice(itemNum);
1419 			}
1420 		} else {
1421 			var itemNum = this.getChoiceNum(values);
1422 			if (itemNum != -1) this.hiliteSubChoice(itemNum);
1423 		}
1424 	}	
1425     this.updateEnabledDisabled();
1426 }
1427 
1428 OSelect_DblCheck_XFormItem.prototype.onSubChoiceDoubleClick = function (itemNum, event) {
1429 	this.subChoiceSelected(itemNum, true, event);
1430 }
1431 
1432 OSelect_DblCheck_XFormItem.prototype.setElementEnabled = function (enabled) {
1433 	var choices = this.getNormalizedChoices();
1434 	if(!choices)
1435 		return;
1436 	
1437 	var values = choices.values;
1438 	if(!values)
1439 		return;
1440 		
1441 	var cnt = values.length;
1442 	for(var i=0; i < cnt; i ++) {
1443 		var chkbx = this.getElement(this.getId() + "_choiceitem_" + i);
1444 		var chkbxSub = this.getElement(this.getId() + "_subchoiceitem_" + i);	
1445 		if(chkbx && chkbxSub) {
1446 			if(enabled) {
1447 				chkbx.className = this.getChoiceCssClass();
1448 				chkbx.disabled = false;
1449 //				chkbxSub.className = this.getChoiceCssClass();
1450 //				chkbxSub.disabled = false;					
1451 			} else {
1452 				chkbx.className = this.getChoiceCssClass() + "_disabled";
1453 				chkbx.disabled = true;
1454 				chkbxSub.className = this.getChoiceCssClass() + "_disabled";
1455 				chkbxSub.disabled = true;				
1456 			}
1457 		} 
1458 	}
1459 };
1460 
1461 OSelect_DblCheck_XFormItem.prototype.deselectAll = function (ev) {
1462 	this.getForm().subItemChanged(this, [], ev);
1463 	this.getForm().itemChanged(this, [], ev);
1464 }
1465