/* * ***** BEGIN LICENSE BLOCK ***** * Version: ZAPL 1.1 * * The contents of this file are subject to the Zimbra AJAX Public * License Version 1.1 ("License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.zimbra.com/license * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is: Zimbra AJAX Toolkit. * * The Initial Developer of the Original Code is Zimbra, Inc. * Portions created by Zimbra are Copyright (C) 2005 Zimbra, Inc. * All Rights Reserved. * * Contributor(s): * * ***** END LICENSE BLOCK ***** */ // // OSelect class -- lightning fast SELECT type widget // function OSelect1_XFormItem(){ this._enabled = true; } XFormItemFactory.createItemType("_OSELECT1_", "oselect1", OSelect1_XFormItem, Select1_XFormItem); OSelect1_XFormItem._mouseWheelEventAttached = false; OSelect1_XFormItem._mouseWheelCurrentSelect; OSelect1_XFormItem._mouseWheelHideMenu = function() { OSelect1_XFormItem._mouseWheelCurrentSelect.hideMenu(); }; // override the default SELECT type //XFormItemFactory.registerItemType("_SELECT1_", "select1", OSelect1_XFormItem) OSelect1_XFormItem.prototype.focusable = false; OSelect1_XFormItem.prototype.cssClass = "oselect"; OSelect1_XFormItem.prototype.multiple = false; OSelect1_XFormItem.prototype.writeElementDiv = false; OSelect1_XFormItem.prototype.width = "auto"; //TODO: get showing check working for the normal SELECT, requires: // * separate notion of hilited row (for mouseover) and selected row(s) // * teach select1 that more than one value may be selected (same as select) // * convert OSELECT_CHECK to just use showCheck? // * does √ work everywhere? Use an image? OSelect1_XFormItem.prototype.showCheck = false; OSelect1_XFormItem.prototype.checkHTML = "√"; OSelect1_XFormItem.prototype.updateElement = function (newValue) { // hack: if this item can display multiple values and there's a comma in the value // assume it's a list of values if (this.getMultiple() && newValue != null && newValue.indexOf(",") > -1) { newValue = newValue.split(","); for (var i = 0; i < newValue.length; i++) { newValue[i] = this.getChoiceLabel(newValue[i]); } } else { newValue = this.getChoiceLabel(newValue); } if (newValue == null) newValue = ""; var el = this.getDisplayElement(); if (el) el.innerHTML = newValue; } OSelect1_XFormItem.prototype.getShowCheck = function () { return this.cacheInheritedProperty("showCheck", "$showCheck"); } OSelect1_XFormItem.prototype.getCheckHTML = function () { return this.cacheInheritedProperty("checkHTML", "$checkHTML"); } OSelect1_XFormItem.prototype.getMenuElementId = function () { return "___OSELECT_MENU___"; } OSelect1_XFormItem.prototype.getMenuElement = function () { var id = this.getMenuElementId(); var el = this.getElement(id); if (el == null) { el = this.createElement(id, null, "div", "MENU CONTENTS"); } return el; } OSelect1_XFormItem.prototype.showMenu = function() { if(!this._enabled) return; if (AjxEnv.isIE && !OSelect1_XFormItem._mouseWheelEventAttached) { var form = this.getForm(); var formElement = form.getHtmlElement(); if (formElement.attachEvent) { formElement.attachEvent("onmousewheel", OSelect1_XFormItem._mouseWheelHideMenu); OSelect1_XFormItem._mouseWheelCurrentSelect = this; OSelect1_XFormItem._mouseWheelEventAttached = true; } } var menu = this.getMenuElement(); if (menu == null) return; //DBG.println(this,".showMenu() -- couldn't get menu element."); menu.className = this.getMenuCssClass(); menu.innerHTML = this.getChoicesHTML(); // move the menu underneath the button // LATER THIS SHOULD RESPECT THIS WINDOW SIZE, ETC var bounds = this.getBounds(this.getElement()); //alert(bounds.left + ":" + bounds.top+ ":" + bounds.width+ ":" + bounds.height); menu.style.left = bounds.left; menu.style.top = bounds.top + bounds.height - 1; var choices = this.getNormalizedChoices(); if(choices && choices.values) { if(choices.values.length > 5) { menu.style.top = parseInt(menu.style.top)+2; menu.style.height = 110; menu.style.overflow="auto"; menu.style.width = parseInt(bounds.width)+2; } else { menu.style.height = (choices.values.length * 22) + 4; menu.style.width = bounds.width; menu.style.overflow="hidden"; } } var value = this.getInstanceValue(); if (this.$getDisplayValue) { value = this.$getDisplayValue(value); } var selectedItemNum = this.getChoiceNum(value); this.__currentHiliteItem = selectedItemNum; this.hiliteChoice(selectedItemNum); menu.style.zIndex = 1000000; menu.style.display = "block"; if (this.$hideListener == null) { this.$hideListener = new AjxListener(this, this.oMouseUp); } if (this.$outsideMouseDownListener == null) { this.$outsideMouseDownListener = new AjxListener(this, this.onOutsideMouseDown); } AjxCore.addListener(window, "onmouseup", this.$hideListener); AjxCore.addListener(document.body, "onmousedown", this.$outsideMouseDownListener); DwtEventManager.addListener(DwtEvent.ONMOUSEDOWN, this.$outsideMouseDownListener); } OSelect1_XFormItem.prototype.hideMenu = function () { // hide the menu on a timer so we don't have to deal with wierd selection bugs setTimeout(this.getFormGlobalRef()+".getElement('" + this.getMenuElementId() + "').style.display = 'none'", 10); AjxCore.removeListener(window, "onmouseup", this.$hideListener); AjxCore.removeListener(document.body, "onmousedown", this.$outsideMouseDownListener); DwtEventManager.removeListener(DwtEvent.ONMOUSEDOWN, this.$outsideMouseDownListener); if (AjxEnv.isIE && OSelect1_XFormItem._mouseWheelEventAttached) { var form = this.getForm(); var formElement = form.getHtmlElement(); if (formElement.detachEvent) { window.event.cancelBubble = true; formElement.detachEvent("onmousewheel", OSelect1_XFormItem._mouseWheelHideMenu); OSelect1_XFormItem._mouseWheelEventAttached = false; OSelect1_XFormItem._mouseWheelCurrentSelect = null; } } } OSelect1_XFormItem.prototype.oMouseUp = function (ev) { // hide the menu on a timer so we don't have to deal with wierd selection bugs ev = ev || window.event; var found = false; if (ev) { // figure out if we are over the menu that is up var htmlEl = DwtUiEvent.getTarget(ev); // DBG.println(AjxDebug.DBG1, AjxBuffer.concat("oMouseUp; htmlEl.nodeName=",htmlEl.nodeName," htmlEl.localName = ", htmlEl.nodeName)); //check if the user clicked on the scrollbar if(htmlEl.localName == "scrollbar" && htmlEl.parentNode && htmlEl.parentNode.id=="___OSELECT_MENU___") { found = true; } } if(!found) this.hideMenu(); /*else AjxCore.removeListener(window, "onmouseup", this.$hideListener);*/ return true; } OSelect1_XFormItem.prototype.onOutsideMouseDown = function (ev) { // hide the menu on a timer so we don't have to deal with wierd selection bugs ev = ev || window.event; var found = false; if (ev) { // figure out if we are over the menu that is up var htmlEl = DwtUiEvent.getTarget(ev); if(htmlEl && htmlEl.attributes && htmlEl.attributes.length) { var cnt = htmlEl.attributes.length; for(var i = 0; i < cnt; i++) { if(htmlEl.attributes[i].name == "itemnum") { this.onChoiceClick(htmlEl.attributes[i].value, ev); found = true; break; } } } if(!found) { // DBG.println(AjxDebug.DBG1, AjxBuffer.concat("onOutsideMouseDown; htmlEl.nodeName=", htmlEl.nodeName," htmlEl.localName = ", htmlEl.localName, " htmlEl.id=", htmlEl.id)); //check if the user clicked on the scrollbar if(htmlEl.localName == "scrollbar" && htmlEl.parentNode && htmlEl.parentNode.id=="___OSELECT_MENU___") { found = true; } else if (htmlEl.id && htmlEl.id == "___OSELECT_MENU___"){ found = true; } } } if(!found) this.hideMenu(); /* else { AjxCore.removeListener(document.body, "onmousedown", this.$outsideMouseDownListener); DwtEventManager.removeListener(DwtEvent.ONMOUSEDOWN, this.$outsideMouseDownListener); }*/ return true; } OSelect1_XFormItem.prototype.getBounds = function(anElement, containerElement) { var myBounds = new Object(); myBounds.left = 0; myBounds.top = 0; myBounds.width = anElement.offsetWidth; myBounds.height = anElement.offsetHeight; if(!containerElement) { containerElement = AjxEnv.isIE ? anElement.document.body : anElement.ownerDocument.body; } // account for the scrollbars if necessary var hasScroll = (anElement.scrollLeft !== void 0); var trace = anElement; while(trace != containerElement) { myBounds.left += trace.offsetLeft; myBounds.top += trace.offsetTop; var nextEl = trace.offsetParent; while (hasScroll && (trace != nextEl)) { myBounds.left -= trace.scrollLeft; myBounds.top -= trace.scrollTop; trace = AjxEnv.isIE ? nextEl : trace.parentNode; } trace = nextEl; } return myBounds; }; // TAKE DIRECTLY FROM DWT_SELECT OSelect1_XFormItem.prototype.onChoiceOver = function (itemNum, event) { if (this.__currentHiliteItem != null) this.dehiliteChoice(this.__currentHiliteItem); this.hiliteChoice(itemNum); this.__currentHiliteItem = itemNum; } OSelect1_XFormItem.prototype.onChoiceOut = function (itemNum, event) { if (this.__currentHiliteItem != null) this.dehiliteChoice(this.__currentHiliteItem); this.__currentHiliteItem = null; } OSelect1_XFormItem.prototype.onChoiceClick = function (itemNum, event) { this.choiceSelected(itemNum, false, event); } OSelect1_XFormItem.prototype.onChoiceDoubleClick = function (itemNum, event) { this.choiceSelected(itemNum, true, event); } OSelect1_XFormItem.prototype.choiceSelected = function (itemNum, clearOldValues, event) { this.onChoiceOut(); this.hideMenu(); var value = this.getNormalizedValues()[itemNum]; this.setValue(value, clearOldValues, event); } OSelect1_XFormItem.prototype.setValue = function (newValue, clearOldValues, event) { var method = this.getElementChangedMethod(); method.call(this, newValue, this.getInstanceValue(), event); } OSelect1_XFormItem.prototype.hiliteChoice = function (itemNum) { this.setChoiceCssClass(itemNum, this.getChoiceSelectedCssClass()); if (this.getShowCheck() == true) { var els = this.getChoiceElements(itemNum); if (els) els[0].innerHTML = this.getCheckHTML(); } } OSelect1_XFormItem.prototype.showArrowOver = function () { if(!this._enabled) return; AjxImg.setImage(this.getArrowElement(), DwtImg.SELECT_PULL_DOWN_ENABLED); } OSelect1_XFormItem.prototype.showArrowOut = function () { if(!this._enabled) return; AjxImg.setImage(this.getArrowElement(), DwtImg.SELECT_PULL_DOWN); } OSelect1_XFormItem.prototype.showArrowDown = function () { if(!this._enabled) return; AjxImg.setImage(this.getArrowElement(), DwtImg.SELECT_PULL_DOWN_DEPRESSED); } OSelect1_XFormItem.prototype.dehiliteChoice = function(itemNum) { this.setChoiceCssClass(itemNum, this.getChoiceCssClass()); if (this.getShowCheck() == true) { var els = this.getChoiceElements(itemNum); if (els) els[0].innerHTML = " "; } } OSelect1_XFormItem.prototype.clearAllHilites = function () { for (var i = 0; i < this._normalizedValues.length; i++) { this.dehiliteChoice(i); } } OSelect1_XFormItem.prototype.setChoiceCssClass = function (itemNum, cssClass) { var els = this.getChoiceElements(itemNum); if (els) { els.className = cssClass; /* if (this.getShowCheck()) { els[0].className = cssClass + "_check"; els[1].className = cssClass; } else { els[0].className = cssClass; } */ } } OSelect1_XFormItem.prototype.getArrowElement = function () { return this.getForm().getElement(this.getId() + "_arrow_button"); } OSelect1_XFormItem.prototype.getDisplayElement = function () { return this.getElement(this.getId() + "_display"); } OSelect1_XFormItem.prototype.getItemNumFromEvent = function (event) { var target = event.target || event.src; while (target) { if (target.id) { var itemNum = parseInt(target.id); if (isNaN(itemNum)) return -1; return itemNum; } target = target.parentNode; } return -1; } OSelect1_XFormItem.prototype.getChoiceElements = function (itemNum) { if (itemNum == null || itemNum == -1) return null; try { // return this.getForm().getElement(this.getId() + "_menu_table").rows[itemNum].getElementsByTagName("td"); return this.getForm().getElement(this.getId() + "_menu_table").getElementsByTagName("div")[itemNum]; } catch (e) { return null; } } OSelect1_XFormItem.prototype.outputHTML = function (HTMLoutput, updateScript, indent) { var id = this.getId(); if (this.getWidth() == "auto") { var element = this.getElement("temp"); var element = this.createElement("temp", null, "div", "MENU CONTENTS"); element.style.left = -1000; element.style.top = -1000; element.className = this.getMenuCssClass(); element.innerHTML = this.getChoicesHTML(); this._width = element.offsetWidth+20; element.innerHTML = ""; } HTMLoutput.append(indent, "
VALUE | \r", indent,
" ", this.getArrowButtonHTML()," | \r", indent, "
| ", label, " |