1 /* 2 * JBoss, Home of Professional Open Source 3 * Copyright ${year}, Red Hat, Inc. and individual contributors 4 * by the @authors tag. See the copyright.txt in the distribution for a 5 * full listing of individual contributors. 6 * 7 * This is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU Lesser General Public License as 9 * published by the Free Software Foundation; either version 2.1 of 10 * the License, or (at your option) any later version. 11 * 12 * This software is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this software; if not, write to the Free 19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 21 */ 22 23 (function ($, rf) { 24 25 rf.ui = rf.ui || {}; 26 27 /* SIMPLE INNER CLASS for handle switch operation*/ 28 function SwitchItems(comp) { 29 this.comp = comp; 30 } 31 32 SwitchItems.prototype = { 33 34 /** 35 * @param {TogglePanelItem} oldPanel 36 * @param {TogglePanelItem} newPanel 37 * 38 * @return {void} 39 * */ 40 exec : function (oldPanel, newPanel) { 41 if (newPanel.switchMode == "server") { 42 return this.execServer(oldPanel, newPanel); 43 } else if (newPanel.switchMode == "ajax") { 44 return this.execAjax(oldPanel, newPanel); 45 } else if (newPanel.switchMode == "client") { 46 return this.execClient(oldPanel, newPanel); 47 } else { 48 rf.log.error("SwitchItems.exec : unknown switchMode (" + this.comp.switchMode + ")"); 49 } 50 }, 51 52 /** 53 * @protected 54 * @param {TogglePanelItem} oldPanel 55 * @param {TogglePanelItem} newPanel 56 * 57 * @return {Boolean} false 58 * */ 59 execServer : function (oldPanel, newPanel) { 60 if (oldPanel) { 61 var continueProcess = oldPanel.__leave(); 62 if (!continueProcess) { 63 return false; 64 } 65 } 66 67 this.__setActiveItem(newPanel.getName()); 68 69 rf.submitForm(this.__getParentForm()); 70 71 return false; 72 }, 73 74 /** 75 * @protected 76 * @param {TogglePanelItem} oldPanel 77 * @param {TogglePanelItem} newPanel 78 * 79 * @return {Boolean} false 80 * */ 81 execAjax : function (oldPanel, newPanel) { 82 var options = $.extend({}, this.comp.options["ajax"], {}/*this.getParameters(newPanel)*/); 83 84 this.__setActiveItem(newPanel.getName()); 85 rf.ajax(this.comp.id, null, options); 86 87 if (oldPanel) { 88 this.__setActiveItem(oldPanel.getName()); 89 } 90 91 return false; 92 }, 93 94 /** 95 * @protected 96 * @param {TogglePanelItem} oldPanel 97 * @param {TogglePanelItem} newPanel 98 * 99 * @return {undefined} 100 * - false - if process has been terminated 101 * - true - in other cases 102 * */ 103 execClient : function (oldPanel, newPanel) { 104 if (oldPanel) { 105 var continueProcess = oldPanel.__leave(); 106 if (!continueProcess) { 107 return false; 108 } 109 } 110 111 this.__setActiveItem(newPanel.getName()); 112 113 newPanel.__enter(); 114 this.comp.__fireItemChange(oldPanel, newPanel); 115 116 return true; 117 }, 118 119 /** 120 * @private 121 * */ 122 __getParentForm : function () { 123 return $(rf.getDomElement(this.comp.id)).parents('form:first'); 124 }, 125 126 /** 127 * @private 128 * */ 129 __setActiveItem : function (name) { 130 rf.getDomElement(this.__getValueInputId()).value = name; 131 this.comp.activeItem = name; 132 }, 133 134 /** 135 * @private 136 * */ 137 __getValueInputId: function () { 138 return this.comp.id + "-value" 139 } 140 }; 141 142 /** 143 * @class TogglePanel 144 * @name TogglePanel 145 * 146 * @constructor 147 * @param {String} componentId - component id 148 * @param {Hash} options - params 149 * */ 150 rf.ui.TogglePanel = rf.BaseComponent.extendClass({ 151 152 // class name 153 name:"TogglePanel", 154 155 init : function (componentId, options) { 156 $super.constructor.call(this, componentId); 157 this.attachToDom(); 158 159 this.items = []; 160 161 this.options = $.extend(this.options, options || {}); 162 this.activeItem = this.options.activeItem; 163 164 this.__addUserEventHandler("itemchange"); 165 this.__addUserEventHandler("beforeitemchange"); 166 }, 167 168 /***************************** Public Methods ****************************************************************/ 169 170 /** 171 * @methodOf 172 * 173 * @name TogglePanel#getSelectItem 174 * 175 * @return {String} name of current selected panel item 176 */ 177 getSelectItem: function () { 178 return this.activeItem; 179 }, 180 181 /** 182 * @methodOf 183 * @name TogglePanel#switchToItem 184 * 185 * @param {String} name - panel item name to switch 186 * we can use meta names @first, @prev, @next and @last 187 * @return {Boolean} - false if something wrong and true if all is ok 188 */ 189 switchToItem: function (name) { 190 var newPanel = this.getNextItem(name); 191 if (newPanel == null) { 192 rf.log.warn("TogglePanel.switchToItems(" + name + "): item with name '" + name + "' not found"); 193 return false; 194 } 195 196 var oldPanel = this.__getItemByName(this.getSelectItem()); 197 198 var continueProcess = this.__fireBeforeItemChange(oldPanel, newPanel); 199 if (!continueProcess) { 200 rf.log.warn("TogglePanel.switchToItems(" + name + "): switch has been canceled by beforeItemChange event"); 201 return false 202 } 203 204 return this.__itemsSwitcher().exec(oldPanel, newPanel); 205 }, 206 207 /** 208 * @methodOf 209 * @name TogglePanel#getNextItem 210 * 211 * @param {String} name of TogglePanelItem or meta name (@first | @prev | @next | @last) 212 * @return {TogglePanelItem} null if item not found 213 */ 214 getNextItem : function (name) { 215 if (name) { 216 var newItemIndex = this.__ITEMS_META_NAMES[name]; 217 if (newItemIndex) { 218 return this.__getItem(newItemIndex(this)); 219 } else { 220 return this.__getItemByName(name); 221 } 222 } else { 223 return this.__getItemByName(this.nextItem()); 224 } 225 }, 226 227 /** 228 * please, remove this method when client side ajax events will be added 229 * 230 * */ 231 onCompleteHandler : function (newItemName) { 232 var oldItem = this.__getItemByName(this.activeItem); 233 var newItem = this.__getItemByName(newItemName); 234 235 // Don't do like this and remove it ASAP 236 this.__itemsSwitcher().execClient(oldItem, newItem); 237 $(document.getElementById(newItem.getTogglePanel().id)).trigger("resize"); 238 }, 239 240 /** 241 * @methodOf 242 * @name TogglePanel#getItems 243 * 244 * @return {TogglePanelItem[]} all defined panel items 245 */ 246 getItems : function () { 247 return this.items; 248 }, 249 250 /** 251 * @methodOf 252 * @name TogglePanel#getItemsNames 253 * 254 * @return {String[]} names of all defined items 255 */ 256 getItemsNames: function () { 257 var res = []; 258 for (var i = 0; i < this.items.length; i++) { 259 res.push(this.items[i].getName()); 260 } 261 262 return res; 263 }, 264 265 /** 266 * @methodOf 267 * @name TogglePanel#nextItem 268 * 269 * @param {String} [itemName = activeItem] 270 * @return {String} name of next panel item 271 */ 272 nextItem: function (itemName) { 273 var itemIndex = this.__getItemIndex(itemName || this.activeItem); 274 if (itemIndex == -1) { 275 return null; 276 } 277 278 return this.__getItemName(itemIndex + 1); 279 }, 280 281 /** 282 * @methodOf 283 * @name TogglePanel#firstItem 284 * 285 * @return {String} name of first panel item 286 */ 287 firstItem: function () { 288 return this.__getItemName(0); 289 }, 290 291 /** 292 * @methodOf 293 * @name TogglePanel#lastItem 294 * 295 * @return {String} name of last panel item 296 */ 297 lastItem: function () { 298 return this.__getItemName(this.items.length - 1); 299 }, 300 301 /** 302 * @methodOf 303 * @name TogglePanel#prevItem 304 * 305 * @param {String} itemName 306 * @return {String} name of prev panel item 307 * null if it is first item 308 */ 309 prevItem: function (itemName) { 310 var itemIndex = this.__getItemIndex(itemName || this.activeItem); 311 if (!this.options.cycledSwitching && itemIndex < 1) { 312 return null; 313 } 314 315 return this.__getItemName(itemIndex - 1); 316 }, 317 318 ///////////////////////////////////////////////////////////////////////////////// 319 //// Private 320 ///////////////////////////////////////////////////////////////////////////////// 321 322 /********************* Methods *************************/ 323 324 __itemsSwitcher : function () { 325 return new SwitchItems(this); 326 }, 327 328 __ITEMS_META_NAMES : (function () { 329 function goFrom(comp, ind, step) { 330 var res = ind; 331 while ((!comp.items[res] || comp.items[res].disabled) && res < comp.items.length && res > 0) { 332 res += step; 333 } 334 return res; 335 } 336 337 338 return { 339 "@first" : function (comp) { 340 return goFrom(comp, 0, 1); 341 }, 342 343 "@prev" : function (comp) { 344 return goFrom(comp, parseInt(comp.__getItemIndex(comp.activeItem)) - 1, -1); 345 }, 346 347 "@next" : function (comp) { 348 return goFrom(comp, parseInt(comp.__getItemIndex(comp.activeItem)) + 1, 1); 349 }, 350 351 "@last" : function (comp) { 352 return goFrom(comp, comp.items.length - 1, -1); 353 } 354 } 355 })(), 356 357 /** 358 * @private 359 * */ 360 __getItemIndex : function (itemName) { 361 var item; 362 for (var i = 0; i < this.items.length; i++) { 363 item = this.items[i]; 364 if (!item.disabled && item.getName() === itemName) { 365 return i; 366 } 367 } 368 369 rf.log.info("TogglePanel.getItemIndex: item with name '" + itemName + "' not found"); 370 return -1; 371 }, 372 373 /** 374 * @private 375 * */ 376 __addUserEventHandler : function (name) { 377 var handler = this.options["on" + name]; 378 if (handler) { 379 rf.Event.bindById(this.id, name, handler); 380 } 381 }, 382 383 /** 384 * @private 385 * @param {Number} index - array index 386 * 387 * @return {TogglePanelItem} 388 * null - if item not found 389 * */ 390 __getItem : function (index) { 391 if (this.options.cycledSwitching) { 392 var size = this.items.length; 393 return this.items[(size + index) % size] 394 } else if (index >= 0 && index < this.items.length) { 395 return this.items[index] 396 } else { 397 return null; 398 } 399 }, 400 401 __getItemByName : function (name) { 402 return this.__getItem(this.__getItemIndex(name)); 403 }, 404 405 __getItemName : function (index) { 406 var item = this.__getItem(index); 407 if (item == null) { 408 return null; 409 } 410 411 return item.getName(); 412 }, 413 414 /** 415 * Fire Concealable Event 416 * */ 417 418 __fireItemChange : function (oldItem, newItem) { 419 return new rf.Event.fireById(this.id, "itemchange", { 420 id: this.id, 421 oldItem : oldItem, 422 newItem : newItem 423 }); 424 }, 425 426 __fireBeforeItemChange : function (oldItem, newItem) { 427 return rf.Event.fireById(this.id, "beforeitemchange", { 428 id: this.id, 429 oldItem : oldItem, 430 newItem : newItem 431 }); 432 } 433 }); 434 435 // define super class link 436 var $super = rf.ui.TogglePanel.$super; 437 })(RichFaces.jQuery, RichFaces); 438