1 /*
  2  * ***** BEGIN LICENSE BLOCK *****
  3  * Zimbra Collaboration Suite Web Client
  4  * Copyright (C) 2015, 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) 2015, 2016 Synacor, Inc. All Rights Reserved.
 21  * ***** END LICENSE BLOCK *****
 22  */
 23 
 24 /**
 25  * @overview
 26  *
 27  * This file contains a class for an option dialog; a message dialog asking a
 28  * question and providing a radio group of answers.
 29  */
 30 
 31 /**
 32  * @class
 33  *
 34  * Creates a new option dialog.
 35  *
 36  * @author Dan Villiom Podlaski Christiansen
 37  *
 38  * @param {hash}		params			a hash of parameters
 39  * @param {DwtComposite}	params.parent		the parent widget (the shell)
 40  * @param {string}	params.className 		the CSS class
 41  * @param {array}	params.options				the options?
 42  * @param {string}	params.message 		the message/question to display
 43  * @param {string}	params.title 		dialog title
 44  *
 45  * @extends	DwtMessageDialog
 46  */
 47 DwtOptionDialog = function(params) {
 48 	if (arguments.length == 0) { return; }
 49 
 50 	params.buttons =
 51 		params.buttons || [DwtDialog.OK_BUTTON, DwtDialog.CANCEL_BUTTON];
 52 
 53 	DwtMessageDialog.call(this, params);
 54 
 55 	var options = params.options || [];
 56 
 57 	this._options = [];
 58 	this._selectedIdx = 0;
 59 
 60 	this._buttonContainer = document.createElement('FIELDSET');
 61 	this._buttonContainer.setAttribute('role', 'radiogroup');
 62 
 63 	this._getContentDiv().appendChild(this._buttonContainer);
 64 
 65 	for (var i = 0; i < options.length; i++) {
 66 		var option = AjxUtil.hashCopy(options[i]);
 67 		option.index = i;
 68 
 69 		var checked = (i === 0);
 70 
 71 		var button = option.button = new DwtRadioButton({
 72 			parent: this,
 73 			parentElement: this._buttonContainer,
 74 			id: [this.getHTMLElId(), name, 'button'].join('_'),
 75 			name: option.name,
 76 			value: option.value || option.name,
 77 			checked: checked
 78 		});
 79 
 80 		if (option.text) {
 81 			button.setText(option.text);
 82 		}
 83 
 84 		button.getInputElement().setAttribute('aria-setsize', options.length);
 85 		button.getInputElement().setAttribute('aria-posinset', i + 1);
 86 
 87 		button.addSelectionListener(this._selectionListener.bind(this, i));
 88 
 89 		this._options.push(option);
 90 	}
 91 
 92 	if (params.message) {
 93 		this.setMessage(params.message, null, params.title);
 94 	} else if (params.title) {
 95 		this.setTitle(params.title);
 96 	}
 97 };
 98 
 99 DwtOptionDialog.prototype = new DwtMessageDialog;
100 DwtOptionDialog.prototype.constructor = DwtOptionDialog;
101 DwtOptionDialog.prototype.isDwtOptionDialog = true;
102 
103 DwtOptionDialog.prototype.toString = function() {
104 	return "DwtOptionDialog";
105 };
106 
107 DwtOptionDialog.prototype.getKeyMapName =
108 function() {
109 	return DwtKeyMap.MAP_OPTION_DIALOG;
110 };
111 
112 DwtOptionDialog.prototype._getDefaultStyle = function() {
113 	return DwtMessageDialog.PLAIN_STYLE;
114 }
115 
116 DwtOptionDialog.prototype._updateSelection = function(idx, focus) {
117 
118 	if (!AjxUtil.isNumber(idx) || idx < 0 || idx >= this._options.length) {
119 		return false;
120 	}
121 
122 	this._selectedIdx = idx;
123 
124 	for (var i = 0; i < this._options.length; i++) {
125 		this._options[i].button.setSelected(i === idx);
126 	}
127 
128 	if (focus) {
129 		this._options[idx].button.focus();
130 	}
131 
132 	return true;
133 };
134 
135 DwtOptionDialog.prototype._getOptionByName = function(name) {
136 	for (var i = 0; i < this._options.length; i++) {
137 		if (this._options[i].name === name) {
138 			return this._options[i];
139 		}
140 	}
141 
142 	return null;
143 };
144 
145 DwtOptionDialog.prototype._selectionListener = function(idx, ev) {
146 	if (!ev.detail) {
147 		return;
148 	}
149 
150 	this._updateSelection(idx);
151 };
152 
153 DwtOptionDialog.prototype.getSelection = function() {
154 	var option = this._options[this._selectedIdx];
155 	return option.button ? option.button.getValue() : null;
156 };
157 
158 DwtOptionDialog.prototype.setSelection = function(name) {
159 	var option = this._getOptionByName(name);
160 	this._updateSelection(option && option.index);
161 };
162 
163 DwtOptionDialog.prototype.getButton = function(name) {
164 	var option = this._getOptionByName(name);
165 	return option && option.button;
166 };
167 
168 DwtOptionDialog.prototype.handleKeyAction =
169 function(actionCode, ev) {
170 	switch (actionCode) {
171 	case DwtKeyMap.NEXT:
172 		return this._updateSelection(this._selectedIdx + 1, true);
173 
174 	case DwtKeyMap.PREV:
175 		return this._updateSelection(this._selectedIdx - 1, true);
176 
177 	default:
178 		return DwtMessageDialog.prototype.handleKeyAction.apply(this, arguments);
179 	}
180 };
181 
182 DwtOptionDialog.prototype.popup =
183 function(loc) {
184 	DwtMessageDialog.prototype.popup.call(this, loc);
185 
186 	this._updateSelection(0, true);
187 };
188