1 /*
  2  * ***** BEGIN LICENSE BLOCK *****
  3  * Zimbra Collaboration Suite Web Client
  4  * Copyright (C) 2005, 2006, 2007, 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) 2005, 2006, 2007, 2009, 2010, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved.
 21  * ***** END LICENSE BLOCK *****
 22  */
 23 
 24 
 25 /**
 26  * @constructor
 27  * @class 
 28  * This class is an example of putting a custom widget in a {@link XForm}.
 29  * 
 30  * @param	{array}	attributes		the attributes
 31  * @private
 32  */
 33 ButtonGrid = function(attributes) {
 34 	XFG.assignUniqueId(this, "__BUTTON_GRID__");
 35 
 36 	// copy any props passed in into the object
 37 	for (var prop in attributes) {
 38 		this[prop] = attributes[prop];
 39 	}
 40 	// handle any props that need special care
 41 	if (this.onChange) this.setOnChange(this.onChange);
 42 
 43 	// initialize to an empty array for value
 44 	this.value = [];
 45 	
 46 	
 47 }
 48 var BGP = ButtonGrid.prototype;
 49 BGP.choices = null;
 50 BGP.numCols = 4;
 51 BGP.cssClass = "xform_button_grid_medium";
 52 BGP.onChange = null;
 53 BGP.multiple = true;
 54 BGP.addBracketingCells = false;
 55 
 56 BGP.setOnChange = function (onChange) {
 57 	if (onChange && typeof onChange == "string") {
 58 		onChange = new Function("value, event", onChange);	
 59 	}
 60 	this.onChange = onChange;
 61 }
 62 
 63 
 64 BGP.getValue = function() {
 65 	return this.value;
 66 }
 67 
 68 BGP.setValue = function(value) {
 69 	if (value == null) value = [];
 70 	if (typeof value == "string") value = value.split(",");
 71 	this.value = value;
 72 	
 73 	this.showValue();
 74 }
 75 
 76 BGP.showValue = function() {
 77 	var value = this.value;
 78 	if (value == null) value = "";
 79 
 80 	// assumes value is a comma-delimited string or an array
 81 	if (typeof value == "string") value = value.split(",");
 82 	
 83 	// hack up value to make searching for a particular option value easier
 84 	var uniqueStartStr = "{|[", uniqueEndStr = "]|}";
 85 	value = uniqueStartStr + value.join(uniqueEndStr + uniqueStartStr) + uniqueEndStr;
 86 	var choices = this.choices;
 87 	for (var i = 0; i < choices.length; i++) {
 88 		var element = XFG.getEl(this.getButtonId(i));
 89 		var isPresent = (value.indexOf(uniqueStartStr + choices[i].value + uniqueEndStr) > -1);
 90 		if (isPresent) {
 91 			XFG.showSelected(element);
 92 		} else {
 93 			XFG.hideSelected(element);
 94 		}
 95 	}	
 96 }
 97 
 98 BGP.toggleValue = function(value, element) {
 99 	if (this.multiple) {
100 		if (this.valueIsSelected(value)) {
101 			this.deselectValue(value, element);
102 		} else {
103 			this.selectValue(value, element);
104 		}
105 	} else {
106 		this.value = value;
107 	}
108 	return this.value;
109 }
110 
111 BGP.valueIsSelected = function(value) {
112 	for (var i = 0; i < this.value.length; i++) {
113 		if (this.value[i] == value) return true;
114 	}
115 }
116 
117 BGP.selectValue = function(value, element) {
118 	if (!this.valueIsSelected(value)) {
119 		this.value.push(value);
120 	}
121 	if (element) XFG.showSelected(element);
122 }
123 
124 BGP.deselectValue = function(value, element) {
125 	if (this.valueIsSelected(value)) {
126 		for (var i = 0; i < this.value.length; i++) {
127 			if (this.value[i] == value) {
128 				this.value = this.value.slice(0, i).concat(this.value.slice(i+1, this.value.length));
129 			}
130 		}
131 	}
132 	if (element) XFG.hideSelected(element);
133 }
134 
135 BGP.getButtonId = function (btnNum) {
136 	return this.__id + "_button_" + btnNum;
137 }
138 
139 
140 BGP.onButtonClick = function(choiceValue, element, event) {
141 	var newValue = this.toggleValue(choiceValue, element);
142 	if (this.onChange) {
143 		this.onChange(newValue, event);
144 	}
145 }
146 
147 BGP.getHTML = function () {
148 	if (this.choices == null) return (this.__HTMLOutput = null);
149 
150 	var buffer = new AjxBuffer();
151 	
152 	// write HTML for this element
153 	var buttonCssClass = this.cssClass + "_button";
154 	buffer.append("<table class=\"", this.cssClass, "_table\">");
155 	var i = 0;
156 	var numRows = Math.ceil(this.choices.length / this.numCols);
157 	for (var r = 0; r < numRows; r++) {
158 		buffer.append("<tr>\r");
159 		if (this.addBracketingCells) {
160 			buffer.append("\t<td width=50%><div class=", this.cssClass + "_start></div></td>");
161 		}
162 		for (var c = 0; c < this.numCols; c++) {
163 			var choice = this.choices[i];
164 			if (typeof choice == "string") {
165 				choice = this.choices[i] = {value:choice, label:choice};
166 			}
167 			buffer.append("<td class=", this.cssClass + "_td ><div id=", this.getButtonId(i), " class=", buttonCssClass, //(this.valueIsSelected(choice.value) ? "_selected" : ""),
168 								" onclick=\"XFG.cacheGet('", this.__id, "').onButtonClick('",choice.value,"',this,event);\">", 
169 								choice.label,
170 						"</div></td>");
171 			i++;
172 			if (i >= this.choices.length) break;
173 		}
174 		if (this.addBracketingCells) {
175 			buffer.append("<td width=50%><div class=", this.cssClass + "_end></div></td>");
176 		}
177 		buffer.append("</tr>");
178 	}
179 	buffer.append("</table>");
180 	this.__HTMLOutput = buffer.toString();
181 	return this.__HTMLOutput;
182 }
183 
184 
185 BGP.insertIntoXForm = function (form, item, element) {
186 	element.innerHTML = this.getHTML();
187 }
188 
189 BGP.updateChoicesHTML = function(labels) {
190 	var i = 0;
191 	for (var r = 0; r < numRows; r++) {
192 		for (var c = 0; c < this.numCols; c++) {
193 			var btn = document.getElementById(this.getButtonId(i));
194 			if(btn) {
195 				btn.innerHTML =labels[i].label;
196 			}
197 			i++;
198 			if (i >= labels.length) break;
199 		}
200 	}
201 }
202 
203 BGP.updateInXForm = function (form, item, value, element) {
204 	var valueStr = (value instanceof Array ? value.join(",") : value);
205 	if (!form.forceUpdate && this.__lastDisplayValue == valueStr) return;
206 	
207 	this.setValue(value);
208 	this.__lastDisplayValue = valueStr;
209 }
210 
211