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 
 24 (function ($, rf) {
 25 
 26     rf.ui = rf.ui || {};
 27 
 28     var __DEFAULT_OPTIONS = {
 29         disabled : false,
 30         selectable: true,
 31         unselectable: false,
 32         mode: "client",
 33         stylePrefix: "rf-pm-itm",
 34         itemStep: 20
 35     };
 36 
 37     var SELECT_ITEM = {
 38 
 39         /**
 40          *
 41          * @return {void}
 42          * */
 43         exec : function (item) {
 44 
 45             if (item.expanded) {
 46                 var flag = item.options.expandEvent == item.options.collapseEvent && item.options.collapseEvent == "click";
 47                 if (flag && item.__fireEvent("beforeswitch") == false) return false;
 48                 if (!item.expanded()) {
 49                     if (item.options.expandEvent == "click" && item.__fireEvent("beforeexpand") == false) return false;
 50                 } else {
 51                     if (item.options.collapseEvent == "click" && item.__fireEvent("beforecollapse") == false) return false;
 52                 }
 53             }
 54 
 55             var mode = item.mode;
 56             if (mode == "server") {
 57                 return this.execServer(item);
 58             } else if (mode == "ajax") {
 59                 return this.execAjax(item);
 60             } else if (mode == "client" || mode == "none") {
 61                 return this.execClient(item);
 62             } else {
 63                 rf.log.error("SELECT_ITEM.exec : unknown mode (" + mode + ")");
 64             }
 65         },
 66 
 67         /**
 68          * @protected
 69          *
 70          * @return {Boolean} false
 71          * */
 72         execServer : function (item) {
 73             item.__changeState();
 74             //TODO nick - 'target' attribute?
 75 
 76             var params = {};
 77             params[item.__panelMenu().id] = item.itemName; // TODO
 78             params[item.id] = item.id;
 79 
 80             $.extend(params, item.options["ajax"]["parameters"] || {});
 81 
 82             rf.submitForm(this.__getParentForm(item), params);
 83 
 84             return false;
 85         },
 86 
 87         /**
 88          * @protected
 89          *
 90          * @return {Boolean} false
 91          * */
 92         execAjax : function (item) {
 93             var oldItem = item.__changeState();
 94             //TODO nick - check for interaction with queue
 95             rf.ajax(item.id, null, $.extend({}, item.options["ajax"], {}));
 96             item.__restoreState(oldItem);
 97 
 98             return true;
 99         },
100 
101         /**
102          * @protected
103          *
104          * @return {undefined}
105          *             - false - if process has been terminated
106          *             - true  - in other cases
107          * */
108         execClient : function (item) {
109             var panelMenu = item.__rfPanelMenu();
110             var prevItem = panelMenu.getSelectedItem();
111             if (prevItem) {
112                 prevItem.unselect();
113             }
114 
115             panelMenu.selectedItem(item.itemName);
116 
117             item.__select();
118             var result = item.__fireSelect();
119 
120             if (item.__switch) {
121                 var mode = item.mode;
122                 if (mode == "client" || mode == "none") {
123                     item.__switch(!item.expanded());
124                 }
125             }
126 
127             return result;
128         },
129 
130         /**
131          * @private
132          * */
133         __getParentForm : function (item) {
134             return $($(rf.getDomElement(item.id)).parents("form")[0]);
135         }
136     };
137 
138     rf.ui.PanelMenuItem = rf.BaseComponent.extendClass({
139             // class name
140             name:"PanelMenuItem",
141 
142             /**
143              * @class PanelMenuItem
144              * @name PanelMenuItem
145              *
146              * @constructor
147              * @param {String} componentId - component id
148              * @param {Hash} options - params
149              * */
150             init : function (componentId, options) {
151                 $super.constructor.call(this, componentId);
152                 var rootElt = $(this.attachToDom());
153 
154                 this.options = $.extend(this.options, __DEFAULT_OPTIONS, options || {});
155 
156                 this.mode = this.options.mode;
157                 this.itemName = this.options.name;
158                 var panelMenu = this.__rfPanelMenu();
159                 panelMenu.addItem(this);
160 
161                 // todo move it
162                 this.selectionClass = this.options.stylePrefix + "-sel";
163 
164                 if (!this.options.disabled) {
165                     var item = this;
166 
167                     if (this.options.selectable) {
168                         this.__header().bind("click", function() {
169                             if (item.__rfPanelMenu().selectedItem() == item.id) {
170                                 if (item.options.unselectable) {
171                                     return item.unselect();
172                                 }
173 
174                                 // we shouldn't select one item several times
175                             } else {
176                                 return item.select();
177                             }
178                         });
179                     }
180                 }
181 
182                 item = this;
183                 $(this.__panelMenu()).ready(function () {
184                     item.__renderNestingLevel();
185                 });
186 
187                 this.__addUserEventHandler("select");
188                 this.__addUserEventHandler("beforeselect");
189             },
190 
191             /***************************** Public Methods  ****************************************************************/
192 
193             selected : function () {
194                 return this.__header().hasClass(this.selectionClass);
195             },
196 
197             /**
198              * @methodOf
199              * @name PanelMenuItem#select
200              *
201              * TODO ...
202              *
203              * @return {void} TODO ...
204              */
205             select: function () {
206                 var continueProcess = this.__fireBeforeSelect();
207                 if (!continueProcess) {
208                     return false;
209                 }
210 
211                 return SELECT_ITEM.exec(this)
212             },
213 
214             /**
215              * please, remove this method when client side ajax events will be added
216              *
217              * */
218             onCompleteHandler : function () {
219                 SELECT_ITEM.execClient(this);
220             },
221 
222             unselect: function () {
223                 var panelMenu = this.__rfPanelMenu();
224                 if (panelMenu.selectedItem() == this.itemName) {
225                     panelMenu.selectedItem(null);
226                 } else {
227                     rf.log.warn("You tried to unselect item (name=" + this.itemName + ") that isn't seleted")
228                 }
229 
230                 this.__unselect();
231 
232                 return this.__fireUnselect();
233             },
234 
235             /***************************** Private Methods ****************************************************************/
236             __rfParentItem : function () {
237                 var res = this.__item().parents(".rf-pm-gr")[0];
238                 if (!res) {
239                     res = this.__item().parents(".rf-pm-top-gr")[0];
240                 }
241 
242                 if (!res) {
243                     res = this.__panelMenu();
244                 }
245 
246                 return res ? rf.component(res) : null;
247             },
248 
249             __getNestingLevel : function () {
250                 if (!this.nestingLevel) {
251                     var parentItem = this.__rfParentItem();
252                     if (parentItem && parentItem.__getNestingLevel) {
253                         this.nestingLevel = parentItem.__getNestingLevel() + 1;
254                     } else {
255                         this.nestingLevel = 0;
256                     }
257                 }
258 
259                 return this.nestingLevel;
260             },
261 
262             __renderNestingLevel : function () {
263                 this.__item().find("td").first().css("padding-left", this.options.itemStep * this.__getNestingLevel());
264             },
265 
266             __panelMenu : function () {
267                 return this.__item().parents(".rf-pm")[0];
268             },
269 
270             __rfPanelMenu : function () {
271                 return rf.component(this.__panelMenu());
272             },
273 
274             __changeState : function () {
275                 return this.__rfPanelMenu().selectedItem(this.itemName);
276             },
277 
278             __restoreState : function (state) {
279                 if (state) {
280                     this.__rfPanelMenu().selectedItem(state);
281                 }
282             },
283 
284             __item : function () {
285                 return $(rf.getDomElement(this.id));
286             },
287 
288             __header : function () {
289                 return this.__item();
290             },
291 
292             __isSelected: function() {
293                 return this.__header().hasClass(this.selectionClass);
294             },
295 
296             __select: function () {
297                 this.__header().addClass(this.selectionClass);
298             },
299 
300             __unselect: function () {
301                 this.__header().removeClass(this.selectionClass);
302             },
303 
304             __fireBeforeSelect : function () {
305                 return rf.Event.fireById(this.id, "beforeselect", {
306                         item: this
307                     });
308             },
309 
310             __fireSelect : function () {
311                 return rf.Event.fireById(this.id, "select", {
312                         item: this
313                     });
314             },
315 
316             __fireUnselect : function () {
317                 return rf.Event.fireById(this.id, "unselect", {
318                         item: this
319                     });
320             },
321 
322             __fireEvent : function (eventType, event) {
323                 return this.invokeEvent(eventType, rf.getDomElement(this.id), event, {id: this.id, item: this});
324             },
325 
326             /**
327              * @private
328              * */
329             __addUserEventHandler : function (name) {
330                 var handler = this.options["on" + name];
331                 if (handler) {
332                     rf.Event.bindById(this.id, name, handler);
333                 }
334             },
335 
336             __rfTopGroup : function () {
337                 var res = this.__item().parents(".rf-pm-top-gr")[0];
338                 return res ? res : null;
339             },
340 
341             destroy: function () {
342                 var panelMenu = this.__rfPanelMenu();
343                 if (panelMenu) {
344                     panelMenu.deleteItem(this);
345                 }
346 
347                 $super.destroy.call(this);
348             }
349         });
350 
351     // define super class link
352     var $super = rf.ui.PanelMenuItem.$super;
353 })(RichFaces.jQuery, RichFaces);
354