1 (function ($, rf) { 2 3 rf.ui = rf.ui || {}; 4 5 rf.ui.OrderingList = function(id, options) { 6 var mergedOptions = $.extend({}, defaultOptions, options); 7 $super.constructor.call(this, id, mergedOptions); 8 this.namespace = this.namespace || "." + rf.Event.createNamespace(this.name, this.id); 9 this.attachToDom(); 10 mergedOptions['scrollContainer'] = $(document.getElementById(id + "Items")); 11 this.orderingList = $(document.getElementById(id)); 12 this.list = new rf.ui.ListMulti(id+ "List", mergedOptions); 13 var hiddenId = mergedOptions['hiddenId'] ===null ? id + "SelValue" : mergedOptions['hiddenId']; 14 this.hiddenValues = $(document.getElementById(hiddenId)); 15 this.selectItemCss = mergedOptions['selectItemCss']; 16 this.disabled = mergedOptions.disabled; 17 18 this.upButton = $('.rf-ord-up', this.orderingList); 19 this.upButton.bind("click", $.proxy(this.up, this)); 20 this.upTopButton = $('.rf-ord-up-tp', this.orderingList); 21 this.upTopButton.bind("click", $.proxy(this.upTop, this)); 22 this.downButton = $('.rf-ord-dn', this.orderingList); 23 this.downButton.bind("click", $.proxy(this.down, this)); 24 this.downBottomButton = $('.rf-ord-dn-bt', this.orderingList); 25 this.downBottomButton.bind("click", $.proxy(this.downBottom, this)); 26 27 this.focused = false; 28 this.keepingFocus = false; 29 bindFocusEventHandlers.call(this, mergedOptions); 30 31 if (mergedOptions['onmoveitems'] && typeof mergedOptions['onmoveitems'] == 'function') { 32 rf.Event.bind(this.list, "moveitems", mergedOptions['onmoveitems']); 33 } 34 rf.Event.bind(this.list, "moveitems", $.proxy(this.toggleButtons, this)); 35 36 rf.Event.bind(this.list, "selectItem", $.proxy(this.toggleButtons, this)); 37 rf.Event.bind(this.list, "unselectItem", $.proxy(this.toggleButtons, this)); 38 39 rf.Event.bind(this.list, "keydown" + this.list.namespace, $.proxy(this.__keydownHandler, this)); 40 41 if (options['onchange'] && typeof options['onchange'] == 'function') { 42 rf.Event.bind(this, "change" + this.namespace, options['onchange']); 43 } 44 45 // TODO: Is there a "Richfaces way" of executing a method after page load? 46 $(document).ready($.proxy(this.toggleButtons, this)); 47 }; 48 rf.BaseComponent.extend(rf.ui.OrderingList); 49 var $super = rf.ui.OrderingList.$super; 50 51 var defaultOptions = { 52 defaultLabel: "", 53 itemCss: "rf-ord-opt", 54 selectItemCss: "rf-ord-sel", 55 listCss: "rf-ord-lst-cord", 56 clickRequiredToSelect: true, 57 disabled : false, 58 hiddenId : null 59 }; 60 61 var bindFocusEventHandlers = function (options) { 62 if (options['onfocus'] && typeof options['onfocus'] == 'function') { 63 rf.Event.bind(this, "listfocus" + this.namespace, options['onfocus']); 64 } 65 if (options['onblur'] && typeof options['onblur'] == 'function') { 66 rf.Event.bind(this, "listblur" + this.namespace, options['onblur']); 67 } 68 69 var focusEventHandlers = {}; 70 focusEventHandlers["listfocus" + this.list.namespace] = $.proxy(this.__focusHandler, this); 71 focusEventHandlers["listblur" + this.list.namespace] = $.proxy(this.__blurHandler, this); 72 rf.Event.bind(this.list, focusEventHandlers, this); 73 74 focusEventHandlers = {}; 75 focusEventHandlers["focus" + this.namespace] = $.proxy(this.__focusHandler, this); 76 focusEventHandlers["blur" + this.namespace] = $.proxy(this.__blurHandler, this); 77 rf.Event.bind(this.upButton, focusEventHandlers, this); 78 rf.Event.bind(this.upTopButton, focusEventHandlers, this); 79 rf.Event.bind(this.downButton, focusEventHandlers, this); 80 rf.Event.bind(this.downBottomButton, focusEventHandlers, this); 81 }; 82 83 84 $.extend(rf.ui.OrderingList.prototype, (function () { 85 86 return { 87 name : "ordList", 88 defaultLabelClass : "rf-ord-dflt-lbl", 89 90 getName: function() { 91 return this.name; 92 }, 93 getNamespace: function() { 94 return this.namespace; 95 }, 96 97 __focusHandler: function(e) { 98 this.keepingFocus = this.focused; 99 if (! this.focused) { 100 this.focused = true; 101 rf.Event.fire(this, "listfocus" + this.namespace, e); 102 } 103 }, 104 105 __blurHandler: function(e) { 106 var that = this; 107 this.timeoutId = window.setTimeout(function() { 108 if (!that.keepingFocus) { // If no other orderingList "sub" component has grabbed the focus during the timeout 109 that.focused = false; 110 rf.Event.fire(that, "listblur" + that.namespace, e); 111 } 112 that.keepingFocus = false; 113 }, 200); 114 }, 115 116 __keydownHandler: function(e) { 117 if (e.isDefaultPrevented()) return; 118 if (! e.metaKey) return; 119 120 var code; 121 if (e.keyCode) { 122 code = e.keyCode; 123 } else if (e.which) { 124 code = e.which; 125 } 126 127 switch (code) { 128 case rf.KEYS.DOWN: 129 e.preventDefault(); 130 this.down(); 131 break; 132 133 case rf.KEYS.UP: 134 e.preventDefault(); 135 this.up(); 136 break; 137 138 case rf.KEYS.HOME: 139 e.preventDefault(); 140 this.upTop(); 141 break; 142 143 case rf.KEYS.END: 144 e.preventDefault(); 145 this.downBottom(); 146 break; 147 148 default: 149 break; 150 } 151 return; 152 }, 153 154 getList: function() { 155 return this.list; 156 }, 157 158 up: function() { 159 this.keepingFocus = true; 160 this.list.setFocus(); 161 var items = this.list.getSelectedItems(); 162 this.list.move(items, -1); 163 this.encodeHiddenValues(); 164 }, 165 166 down: function() { 167 this.keepingFocus = true; 168 this.list.setFocus(); 169 var items = this.list.getSelectedItems(); 170 this.list.move(items, 1); 171 this.encodeHiddenValues(); 172 }, 173 174 upTop: function() { 175 this.keepingFocus = true; 176 this.list.setFocus(); 177 var selectedItems = this.list.getSelectedItems(); 178 var index = this.list.items.index(selectedItems.first()); 179 this.list.move(selectedItems, -index); 180 this.encodeHiddenValues(); 181 }, 182 183 downBottom: function() { 184 this.keepingFocus = true; 185 this.list.setFocus(); 186 var selectedItems = this.list.getSelectedItems(); 187 var index = this.list.items.index(selectedItems.last()); 188 this.list.move(selectedItems, (this.list.items.length -1) - index); 189 this.encodeHiddenValues(); 190 }, 191 192 encodeHiddenValues: function() { 193 var oldValues = this.hiddenValues.val(); 194 var newValues = this.list.csvEncodeValues(); 195 if (oldValues !== newValues) { 196 this.hiddenValues.val(newValues); 197 rf.Event.fire(this, "change" + this.namespace, {oldValues : oldValues, newValues : newValues}); 198 } 199 }, 200 201 toggleButtons: function() { 202 var list = this.list.__getItems(); 203 if (this.disabled || this.list.getSelectedItems().length === 0) { 204 this.__disableButton(this.upButton); 205 this.__disableButton(this.upTopButton); 206 this.__disableButton(this.downButton); 207 this.__disableButton(this.downBottomButton); 208 } else { 209 if (this.list.items.index(this.list.getSelectedItems().first()) === 0) { 210 this.__disableButton(this.upButton); 211 this.__disableButton(this.upTopButton); 212 } else { 213 this.__enableButton(this.upButton); 214 this.__enableButton(this.upTopButton); 215 } 216 if (this.list.items.index(this.list.getSelectedItems().last()) === (this.list.items.length - 1)) { 217 this.__disableButton(this.downButton); 218 this.__disableButton(this.downBottomButton); 219 } else { 220 this.__enableButton(this.downButton); 221 this.__enableButton(this.downBottomButton); 222 } 223 } 224 }, 225 226 __disableButton: function (button) { 227 if (! button.hasClass('rf-ord-btn-dis')) { 228 button.addClass('rf-ord-btn-dis') 229 } 230 if (! button.attr('disabled')) { 231 button.attr('disabled', true); 232 } 233 }, 234 235 __enableButton: function(button) { 236 if (button.hasClass('rf-ord-btn-dis')) { 237 button.removeClass('rf-ord-btn-dis') 238 } 239 if (button.attr('disabled')) { 240 button.attr('disabled', false); 241 } 242 } 243 }; 244 })()); 245 246 })(RichFaces.jQuery, window.RichFaces); 247