1/*! 2 * jQuery Selectbox plugin 0.1.3 3 * 4 * Copyright 2011, Dimitar Ivanov (http://www.bulgaria-web-developers.com/projects/javascript/selectbox/) 5 * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. 6 * 7 * Date: Wed Jul 29 23:20:57 2011 +0200 8 */ 9(function ($, undefined) { 10 var PROP_NAME = 'selectbox', 11 FALSE = false, 12 TRUE = true; 13 /** 14 * Selectbox manager. 15 * Use the singleton instance of this class, $.selectbox, to interact with the select box. 16 * Settings for (groups of) select boxes are maintained in an instance object, 17 * allowing multiple different settings on the same page 18 */ 19 function Selectbox() { 20 this._state = []; 21 this._defaults = { // Global defaults for all the select box instances 22 classHolder: "sbHolder", 23 classHolderDisabled: "sbHolderDisabled", 24 classSelector: "sbSelector", 25 classOptions: "sbOptions", 26 classGroup: "sbGroup", 27 classSub: "sbSub", 28 classDisabled: "sbDisabled", 29 classToggleOpen: "sbToggleOpen", 30 classToggle: "sbToggle", 31 speed: 200, 32 effect: "slide", // "slide" or "fade" 33 onChange: null, //Define a callback function when the selectbox is changed 34 onOpen: null, //Define a callback function when the selectbox is open 35 onClose: null //Define a callback function when the selectbox is closed 36 }; 37 } 38 39 $.extend(Selectbox.prototype, { 40 /** 41 * Is the first field in a jQuery collection open as a selectbox 42 * 43 * @param {Object} target 44 * @return {Boolean} 45 */ 46 _isOpenSelectbox: function (target) { 47 if (!target) { 48 return FALSE; 49 } 50 var inst = this._getInst(target); 51 return inst.isOpen; 52 }, 53 /** 54 * Is the first field in a jQuery collection disabled as a selectbox 55 * 56 * @param {HTMLElement} target 57 * @return {Boolean} 58 */ 59 _isDisabledSelectbox: function (target) { 60 if (!target) { 61 return FALSE; 62 } 63 var inst = this._getInst(target); 64 return inst.isDisabled; 65 }, 66 /** 67 * Attach the select box to a jQuery selection. 68 * 69 * @param {HTMLElement} target 70 * @param {Object} settings 71 */ 72 _attachSelectbox: function (target, settings) { 73 if (this._getInst(target)) { 74 return FALSE; 75 } 76 var $target = $(target), 77 self = this, 78 inst = self._newInst($target), 79 sbHolder, sbSelector, sbToggle, sbOptions, 80 s = FALSE, optGroup = $target.find("optgroup"), opts = $target.find("option"), olen = opts.length; 81 82 $target.attr("sb", inst.uid); 83 84 $.extend(inst.settings, self._defaults, settings); 85 self._state[inst.uid] = FALSE; 86 $target.hide(); 87 88 function closeOthers() { 89 var key, uid = this.attr("id").split("_")[1]; 90 for (key in self._state) { 91 if (key !== uid) { 92 if (self._state.hasOwnProperty(key)) { 93 if ($(":input[sb='" + key + "']")[0]) { 94 self._closeSelectbox($(":input[sb='" + key + "']")[0]); 95 } 96 } 97 } 98 } 99 } 100 101 sbHolder = $("<div>", { 102 "id": "sbHolder_" + inst.uid, 103 "class": inst.settings.classHolder 104 }); 105 106 sbSelector = $("<a>", { 107 "id": "sbSelector_" + inst.uid, 108 "href": "#", 109 "class": inst.settings.classSelector, 110 "click": function (e) { 111 e.preventDefault(); 112 closeOthers.apply($(this), []); 113 var uid = $(this).attr("id").split("_")[1]; 114 if (self._state[uid]) { 115 self._closeSelectbox(target); 116 } else { 117 self._openSelectbox(target); 118 } 119 } 120 }); 121 122 sbToggle = $("<a>", { 123 "id": "sbToggle_" + inst.uid, 124 "href": "#", 125 "class": inst.settings.classToggle, 126 "click": function (e) { 127 e.preventDefault(); 128 closeOthers.apply($(this), []); 129 var uid = $(this).attr("id").split("_")[1]; 130 if (self._state[uid]) { 131 self._closeSelectbox(target); 132 } else { 133 self._openSelectbox(target); 134 } 135 } 136 }); 137 sbToggle.appendTo(sbHolder); 138 139 sbOptions = $("<ul>", { 140 "id": "sbOptions_" + inst.uid, 141 "class": inst.settings.classOptions, 142 "css": { 143 "display": "none" 144 } 145 }); 146 147 $target.children().each(function(i) { 148 var that = $(this), li, config = {}; 149 if (that.is("option")) { 150 getOptions(that); 151 } else if (that.is("optgroup")) { 152 li = $("<li>"); 153 $("<span>", { 154 "text": that.attr("label") 155 }
155).addClass(inst.settings.classGroup).appendTo(li); 156 li.appendTo(sbOptions); 157 if (that.is(":disabled")) { 158 config.disabled = true; 159 } 160 config.sub = true; 161 getOptions(that.find("option"), config); 162 } 163 }); 164 165 function getOptions () { 166 var sub = arguments[1] && arguments[1].sub ? true : false, 167 disabled = arguments[1] && arguments[1].disabled ? true : false; 168 arguments[0].each(function (i) { 169 var that = $(this), 170 li = $("<li>"), 171 child; 172 if (that.is(":selected")) { 173 sbSelector.text(that.text()); 174 s = TRUE; 175 } 176 if (i === olen - 1) { 177 li.addClass("last"); 178 } 179 if (!that.is(":disabled") && !disabled) { 180 child = $("<a>", { 181 "href": "#" + that.val(), 182 "rel": that.val(), 183 "text": that.text(), 184 "click": function (e) { 185 e.preventDefault(); 186 var t = sbToggle, 187 uid = t.attr("id").split("_")[1]; 188 self._changeSelectbox(target, $(this).attr("rel"), $(this).text()); 189 self._closeSelectbox(target); 190 } 191 }); 192 if (sub) { 193 child.addClass(inst.settings.classSub); 194 } 195 child.appendTo(li); 196 } else { 197 child = $("<span>", { 198 "text": that.text() 199 }).addClass(inst.settings.classDisabled); 200 if (sub) { 201 child.addClass(inst.settings.classSub); 202 } 203 child.appendTo(li); 204 } 205 li.appendTo(sbOptions); 206 }); 207 } 208 209 if (!s) { 210 sbSelector.text(opts.first().text()); 211 } 212 213 $.data(target, PROP_NAME, inst); 214 215 sbSelector.appendTo(sbHolder); 216 sbOptions.appendTo(sbHolder); 217 sbHolder.insertAfter($target); 218 }, 219 /** 220 * Remove the selectbox functionality completely. This will return the element back to its pre-init state. 221 * 222 * @param {HTMLElement} target 223 */ 224 _detachSelectbox: function (target) { 225 var inst = this._getInst(target); 226 if (!inst) { 227 return FALSE; 228 } 229 $("#sbHolder_" + inst.uid).remove(); 230 $.data(target, PROP_NAME, null); 231 $(target).show(); 232 }, 233 /** 234 * Change selected attribute of the selectbox. 235 * 236 * @param {HTMLElement} target 237 * @param {String} value 238 * @param {String} text 239 */ 240 _changeSelectbox: function (target, value, text) { 241 var inst = this._getInst(target), 242 onChange = this._get(inst, 'onChange'); 243 $("#sbSelector_" + inst.uid).text(text); 244 $(target).find("option[value='" + value + "']").attr("selected", TRUE); 245 if (onChange) { 246 onChange.apply((inst.input ? inst.input[0] : null), [value, inst]); 247 } else if (inst.input) { 248 inst.input.trigger('change'); 249 } 250 }, 251 /** 252 * Enable the selectbox. 253 * 254 * @param {HTMLElement} target 255 */ 256 _enableSelectbox: function (target) { 257 var inst = this._getInst(target); 258 if (!inst || !inst.isDisabled) { 259 return FALSE; 260 } 261 $("#sbHolder_" + inst.uid).removeClass(inst.settings.classHolderDisabled); 262 inst.isDisabled = FALSE; 263 $.data(target, PROP_NAME, inst); 264 }, 265 /** 266 * Disable the selectbox. 267 * 268 * @param {HTMLElement} target 269 */ 270 _disableSelectbox: function (target) { 271 var inst = this._getInst(target); 272 if (!inst || inst.isDisabled) { 273 return FALSE; 274 } 275 $("#sbHolder_" + inst.uid).addClass(inst.settings.classHolderDisabled); 276 inst.isDisabled = TRUE; 277 $.data(target, PROP_NAME, inst); 278 }, 279 /** 280 * Get or set any selectbox option. If no value is specified, will act as a getter. 281 * 282 * @param {HTMLElement} target 283 * @param {String} name 284 * @param {Object} value 285 */ 286 _optionSelectbox: function (target, name, value) { 287 var inst = this._getInst(target); 288 if (!inst) { 289 return FALSE; 290 } 291 //TODO check name 292 inst[name] = value; 293 $.data(target, PROP_NAME, inst); 294 }, 295 /** 296 * Call up attached selectbox 297 * 298 * @param {HTMLElement} target 299 */ 300 _openSelectbox: function (target) { 301 var inst = this._getInst(target); 302 //if (!inst || this._state[inst.uid] || inst.isDisabled) { 303 if (!inst || inst.isOpen || inst.isDisabled) { 304 return; 305 } 306 var el = $("#sbOptions_" + inst.uid),
307 viewportHeight = parseInt($(window).height(), 10), 308 offset = $("#sbHolder_" + inst.uid).offset(), 309 scrollTop = $(window).scrollTop(), 310 height = el.prev().height(), 311 diff = viewportHeight - (offset.top - scrollTop) - height / 2, 312 onOpen = this._get(inst, 'onOpen'); 313 el.css({ 314 "top": height + "px", 315 "maxHeight": (diff - height) + "px" 316 }); 317 inst.settings.effect === "fade" ? el.fadeIn(inst.settings.speed) : el.slideDown(inst.settings.speed); 318 $("#sbToggle_" + inst.uid).addClass(inst.settings.classToggleOpen); 319 this._state[inst.uid] = TRUE; 320 inst.isOpen = TRUE; 321 if (onOpen) { 322 onOpen.apply((inst.input ? inst.input[0] : null), [inst]); 323 } 324 $.data(target, PROP_NAME, inst); 325 }, 326 /** 327 * Close opened selectbox 328 * 329 * @param {HTMLElement} target 330 */ 331 _closeSelectbox: function (target) { 332 var inst = this._getInst(target); 333 //if (!inst || !this._state[inst.uid]) { 334 if (!inst || !inst.isOpen) { 335 return; 336 } 337 var onClose = this._get(inst, 'onClose'); 338 inst.settings.effect === "fade" ? $("#sbOptions_" + inst.uid).fadeOut(inst.settings.speed) : $("#sbOptions_" + inst.uid).slideUp(inst.settings.speed); 339 $("#sbToggle_" + inst.uid).removeClass(inst.settings.classToggleOpen); 340 this._state[inst.uid] = FALSE; 341 inst.isOpen = FALSE; 342 if (onClose) { 343 onClose.apply((inst.input ? inst.input[0] : null), [inst]); 344 } 345 $.data(target, PROP_NAME, inst); 346 }, 347 /** 348 * Create a new instance object 349 * 350 * @param {HTMLElement} target 351 * @return {Object} 352 */ 353 _newInst: function(target) { 354 var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); 355 return { 356 id: id, 357 input: target, 358 uid: Math.floor(Math.random() * 99999999), 359 isOpen: FALSE, 360 isDisabled: FALSE, 361 settings: {} 362 }; 363 }, 364 /** 365 * Retrieve the instance data for the target control. 366 * 367 * @param {HTMLElement} target 368 * @return {Object} - the associated instance data 369 * @throws error if a jQuery problem getting data 370 */ 371 _getInst: function(target) { 372 try { 373 return $.data(target, PROP_NAME); 374 } 375 catch (err) { 376 throw 'Missing instance data for this selectbox'; 377 } 378 }, 379 /** 380 * Get a setting value, defaulting if necessary 381 * 382 * @param {Object} inst 383 * @param {String} name 384 * @return {Mixed} 385 */ 386 _get: function(inst, name) { 387 return inst.settings[name] !== undefined ? inst.settings[name] : this._defaults[name]; 388 } 389 }); 390 391 /** 392 * Invoke the selectbox functionality. 393 * 394 * @param {Object|String} options 395 * @return {Object} 396 */ 397 $.fn.selectbox = function (options) { 398 399 var otherArgs = Array.prototype.slice.call(arguments, 1); 400 if (typeof options == 'string' && options == 'isDisabled') { 401 return $.selectbox['_' + options + 'Selectbox'].apply($.selectbox, [this[0]].concat(otherArgs)); 402 } 403 404 if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string') { 405 return $.selectbox['_' + options + 'Selectbox'].apply($.selectbox, [this[0]].concat(otherArgs)); 406 } 407 408 return this.each(function() { 409 typeof options == 'string' ? 410 $.selectbox['_' + options + 'Selectbox'].apply($.selectbox, [this].concat(otherArgs)) : 411 $.selectbox._attachSelectbox(this, options); 412 }); 413 }; 414 415 $.selectbox = new Selectbox(); // singleton instance 416 $.selectbox.version = "0.1.3"; 417})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.