1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 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) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * 26 * @private 27 */ 28 DwtPropertySheet = function(parent, className, posStyle, labelSide) { 29 if (arguments.length == 0) return; 30 className = className || "DwtPropertySheet"; 31 DwtComposite.call(this, {parent:parent, className:className, posStyle:posStyle}); 32 33 this._labelSide = labelSide || DwtPropertySheet.DEFAULT; 34 35 this._propertyIdCount = 0; 36 this._propertyList = []; 37 this._propertyMap = {}; 38 39 this._tabGroup = new DwtTabGroup(this.toString()); 40 41 this._tableEl = document.createElement("TABLE"); 42 // Cellspacing needed for IE in quirks mode 43 this._tableEl.cellSpacing = 6; 44 45 var element = this.getHtmlElement(); 46 element.appendChild(this._tableEl); 47 this._setAllowSelection(); 48 } 49 50 DwtPropertySheet.prototype = new DwtComposite; 51 DwtPropertySheet.prototype.constructor = DwtPropertySheet; 52 53 DwtPropertySheet.prototype.toString = 54 function() { 55 return "DwtPropertySheet"; 56 } 57 58 // Constants 59 60 DwtPropertySheet.RIGHT = "right"; 61 DwtPropertySheet.LEFT = "left"; 62 DwtPropertySheet.DEFAULT = DwtPropertySheet.LEFT; 63 64 // Data 65 66 DwtPropertySheet.prototype._labelCssClass = "Label"; 67 DwtPropertySheet.prototype._valueCssClass = "Field"; 68 69 // Public methods 70 71 /** 72 * Adds a property. 73 * 74 * @param label [string] The property label. The value is used to set the 75 * inner HTML of the property label cell. 76 * @param value The property value. If the value is an instance of DwtControl 77 * the element returned by <code>getHtmlElement</code> is used; 78 * if the value is an instance of Element, it is added directly; 79 * anything else is set as the inner HTML of the property value 80 * cell. 81 * @param required [boolean] Determines if the property should be marked as 82 * required. This is denoted by an asterisk next to the label. 83 */ 84 DwtPropertySheet.prototype.addProperty = function(label, value, required) { 85 86 var index = this._tableEl.rows.length; 87 88 var row = this._tableEl.insertRow(-1); 89 row.vAlign = this._vAlign ? this._vAlign : "top"; 90 91 var labelId = Dwt.getNextId(), 92 valueId = Dwt.getNextId(), 93 tabValue; // element or control that can be a tab group member 94 95 if (this._labelSide == DwtPropertySheet.LEFT) { 96 this._insertLabel(row, label, required, labelId, valueId); 97 tabValue = this._insertValue(row, value, required, labelId, valueId); 98 } 99 else { 100 this._insertValue(row, value, required, labelId, valueId); 101 tabValue = this._insertLabel(row, label, required, labelId, valueId); 102 } 103 104 var id = this._propertyIdCount++; 105 var property = { 106 id: id, 107 index: index, 108 row: row, 109 visible: true, 110 labelId: labelId, 111 valueId: valueId, 112 tabValue: tabValue 113 }; 114 this._propertyList.push(property); 115 this._propertyMap[id] = property; 116 return id; 117 }; 118 119 DwtPropertySheet.prototype._insertLabel = function(row, label, required, labelId, valueId) { 120 121 var labelCell = row.insertCell(-1); 122 labelCell.className = this._labelCssClass; 123 labelCell.id = labelId; 124 labelCell.setAttribute("for", valueId); 125 if (this._labelSide != DwtPropertySheet.LEFT) { 126 labelCell.width = "100%"; 127 labelCell.style.textAlign = "left"; 128 } 129 labelCell.innerHTML = label; 130 if (required) { 131 var asterisk = this._tableEl.ownerDocument.createElement("SUP"); 132 asterisk.innerHTML = "*"; 133 labelCell.insertBefore(asterisk, labelCell.firstChild); 134 } 135 }; 136 137 DwtPropertySheet.prototype._insertValue = function(row, value, required, labelId, valueId) { 138 139 var valueCell = row.insertCell(-1); 140 valueCell.className = this._valueCssClass; 141 valueCell.id = valueId; 142 143 if (!value) { 144 valueCell.innerHTML = " "; 145 } 146 else if (value.isDwtControl) { 147 valueCell.appendChild(value.getHtmlElement()); 148 this._tabGroup.addMember(value); 149 var input = value.getInputElement && value.getInputElement(); 150 if (input) { 151 input.setAttribute('aria-labelledby', labelId); 152 } 153 } 154 else if (value.nodeType == AjxUtil.ELEMENT_NODE) { 155 valueCell.appendChild(value); 156 this._addTabGroupMemberEl(valueCell); 157 value.setAttribute('aria-labelledby', labelId); 158 } 159 else { 160 valueCell.innerHTML = String(value); 161 this._addTabGroupMemberEl(valueCell); 162 valueCell.setAttribute('aria-labelledby', labelId); 163 value = valueCell; 164 } 165 166 return value; 167 }; 168 169 /** 170 * Add element's leaf children to tabgroup. 171 * 172 * @param element HTML element. 173 */ 174 DwtPropertySheet.prototype._addTabGroupMemberEl = function(element, isTabStop) { 175 176 var obj = this; 177 178 // recursive function to add leaf nodes 179 function addChildren(el) { 180 if (el.children.length > 0) { 181 AjxUtil.foreach(el.children, function(child){ 182 addChildren(child); 183 }); 184 } 185 else { 186 if (AjxUtil.isBoolean(isTabStop)) { 187 obj.noTab = !isTabStop; 188 } 189 else { 190 // add leaf to tabgroup 191 obj._makeFocusable(el); 192 obj._tabGroup.addMember(el); 193 } 194 } 195 } 196 197 addChildren(element, isTabStop); 198 }; 199 200 DwtPropertySheet.prototype.getTabGroupMember = function() { 201 return this._tabGroup; 202 }; 203 204 DwtPropertySheet.prototype.getProperty = function(id) { 205 return this._propertyMap[id]; 206 }; 207 208 DwtPropertySheet.prototype.removeProperty = function(id) { 209 var prop = this._propertyMap[id]; 210 if (prop) { 211 var propIndex = prop.index; 212 if (prop.visible) { 213 var tableIndex = this.__getTableIndex(propIndex); 214 var row = this._tableEl.rows[tableIndex]; 215 row.parentNode.removeChild(row); 216 } 217 prop.row = null; 218 for (var i = propIndex + 1; i < this._propertyList.length; i++) { 219 this._propertyList[i].index--; 220 } 221 this._propertyList.splice(propIndex, 1); 222 delete this._propertyMap[id]; 223 } 224 }; 225 226 DwtPropertySheet.prototype.setPropertyVisible = function(id, visible) { 227 228 var prop = this._propertyMap[id]; 229 if (prop && prop.visible !== visible) { 230 prop.visible = visible; 231 Dwt.setVisible(this._tableEl.rows[prop.index], visible); 232 var tabValue = prop.tabValue; 233 if (tabValue.isDwtControl) { 234 tabValue.noTab = !visible; 235 } 236 else { 237 this._addTabGroupMemberEl(tabValue, !visible) 238 } 239 } 240 }; 241