1 /*
  2  * ***** BEGIN LICENSE BLOCK *****
  3  * Zimbra Collaboration Suite Web Client
  4  * Copyright (C) 2006, 2007, 2008, 2009, 2010, 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) 2006, 2007, 2008, 2009, 2010, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved.
 21  * ***** END LICENSE BLOCK *****
 22  */
 23 
 24 
 25 /**
 26  * Creates a radio button group.
 27  * @constructor
 28  * @class
 29  * This class implements a group of radio buttons
 30  *
 31  * @param {hash} [radios] 	a hash whose keys are the ids of the radio button elements
 32  * 		and whose values are the values associated with those buttons
 33  * @param {string} [selectedId]	the id of the button to select initially
 34  * 
 35  * TODO: this really should be a DwtComposite
 36  * 
 37  * @private
 38  */
 39 DwtRadioButtonGroup = function(radios, selectedId) {
 40 	this._radios = {};
 41 	this._radioButtons = {};
 42 	this._values = {};
 43 	this._value2id = {};
 44 	this._eventMgr = new AjxEventMgr();
 45 	
 46 	for (var id in radios) {
 47 		this.addRadio(id, radios[id], (id == selectedId));
 48 	}
 49 };
 50 
 51 DwtRadioButtonGroup.prototype.toString =
 52 function() {
 53 	return "DwtRadioButtonGroup";
 54 };
 55 
 56 //
 57 // Data
 58 //
 59 
 60 DwtRadioButtonGroup.prototype._enabled = true;
 61 DwtRadioButtonGroup.prototype._visible = true;
 62 
 63 //
 64 // Public methods
 65 //
 66 
 67 DwtRadioButtonGroup.prototype.addSelectionListener = function(listener) {
 68 	return this._eventMgr.addListener(DwtEvent.SELECTION, listener);
 69 };
 70 
 71 DwtRadioButtonGroup.prototype.removeSelectionListener = function(listener) {
 72 	return this._eventMgr.removeListener(DwtEvent.SELECTION, listener);
 73 };
 74 
 75 DwtRadioButtonGroup.prototype.setEnabled = function(enabled) {
 76 	this._enabled = enabled;
 77 	for (var id in this._radios) {
 78 		this._radios[id].disabled = !enabled;
 79 	}
 80 };
 81 DwtRadioButtonGroup.prototype.isEnabled = function() {
 82 	return this._enabled;
 83 };
 84 
 85 DwtRadioButtonGroup.prototype.setVisible = function(visible) {
 86 	this._visible = visible;
 87 	for (var id in this._radioButtons) {
 88 		this._radioButtons[id].setVisible(visible);
 89 	}
 90 	for (var id in this._radios) {
 91 		Dwt.setVisible(this._radios[id], visible);
 92 	}
 93 };
 94 DwtRadioButtonGroup.prototype.isVisible = function() {
 95 	return this._visible;
 96 };
 97 
 98 DwtRadioButtonGroup.prototype.addRadio =
 99 function(id, radioButtonOrValue, selected) {
100 	var isRadioButton = radioButtonOrValue instanceof DwtRadioButton;
101 	var radioButton = isRadioButton ? radioButtonOrValue : null;
102 	var value = radioButton ? radioButton.getValue() : radioButtonOrValue;
103 
104 	this._values[id] = value;
105 	this._value2id[value] = id;
106 	var element = document.getElementById(id);
107 	this._radios[id] = element;
108 	this._radioButtons[id] = radioButton;
109 	var handler = AjxCallback.simpleClosure(this._handleClick, this);
110 	Dwt.setHandler(element, DwtEvent.ONCLICK, handler);
111    	element.checked = selected;
112     if (selected) {
113     	this._selectedId = id;
114     }
115 };
116 
117 DwtRadioButtonGroup.prototype.getRadioByValue = function(value) {
118 	var id = this._value2id[value];
119 	return this._radios[id];
120 };
121 
122 DwtRadioButtonGroup.prototype.getRadioButtonByValue = function(value) {
123 	var id = this._value2id[value];
124 	return this._radioButtons[id];
125 };
126 
127 DwtRadioButtonGroup.prototype.setSelectedId =
128 function(id, skipNotify) {
129 	if (id != this._selectedId) {
130 		var el = document.getElementById(id);
131 		if (!el) return;
132 		el.checked = true;
133 		this._selectedId = id;
134 		if (!skipNotify) {
135 			var selEv = DwtShell.selectionEvent;
136 			selEv.reset();
137 			this._notifySelection(selEv);
138 		}
139 	}
140 };
141 
142 DwtRadioButtonGroup.prototype.setSelectedValue =
143 function(value, skipNotify) {
144 	var id = this._valueToId(value);
145 	this.setSelectedId(id, skipNotify);
146 };
147 
148 DwtRadioButtonGroup.prototype.getSelectedId =
149 function() {
150 	return this._selectedId;
151 };
152 
153 DwtRadioButtonGroup.prototype.getSelectedValue =
154 function() {
155 	return this._values[this._selectedId];
156 };
157 
158 DwtRadioButtonGroup.prototype.getValue =
159 function() {
160 	return this.getSelectedValue();
161 };
162 
163 DwtRadioButtonGroup.prototype.getData =
164 function(key) {
165 	var selectedRadio = !AjxUtil.isUndefined(this._selectedId) && this._radioButtons[this._selectedId];
166 	if (selectedRadio) {
167 		return selectedRadio.getData(key);
168 	}
169 	// return undefined;
170 }
171 
172 //
173 // Protected methods
174 //
175 
176 DwtRadioButtonGroup.prototype._valueToId =
177 function(value) {
178 	for (var id in this._values) {
179 		if (this._values[id] == value) {
180 			return id;
181 		}
182 		if (value === true && this._values[id] == "true") {
183 			return id;
184 		}
185 		if (value === false && (this._values[id] == "false" || this._values[id] == "")) {
186 			return id;
187 		}
188 	}
189 	return null;
190 };
191 
192 DwtRadioButtonGroup.prototype._notifySelection = 
193 function(selEv) {
194     selEv.item = this;
195     selEv.detail = { id: this._selectedId, value: this._values[this._selectedId] };
196     this._eventMgr.notifyListeners(DwtEvent.SELECTION, selEv);
197 };
198 
199 DwtRadioButtonGroup.prototype._handleClick = 
200 function(event) {
201 	event = DwtUiEvent.getEvent(event);
202 
203 	var target = DwtUiEvent.getTarget(event);
204 	if (target && target.nodeName.match(/label/i)) {
205         target = document.getElementById(target.getAttribute(AjxEnv.isIE ? "htmlFor" : "for"));
206     }
207 
208 	var id = target.id;
209 	// NOTE: When you use the arrows on radio button groups in FF,
210 	//       the radio button that is being unselected is the target
211 	//       of the event. So we need to check to see if this target
212 	//       is the one that is checked.
213 	if (!target.checked) {
214 		for (id in this._radios) {
215 			if (this._radios[id].checked) {
216 				break;
217 			}
218 		}
219 	}
220 	if (id != this._selectedId) {
221 		this._selectedId = id;
222 	    var selEv = DwtShell.selectionEvent;
223 	    DwtUiEvent.copy(selEv, event);
224 		this._notifySelection(selEv);
225 	}
226 };
227