From d0a640fa2970341f5a76b9854ae2bc2e5e9ccc79 Mon Sep 17 00:00:00 2001 From: Chuck Scott Date: Tue, 12 Apr 2016 16:09:01 -0400 Subject: [PATCH] Replaced multiselect jQuery code with something that works better for layout. Updated picklists that use it. --- .../OtherScriptTried/multiselect.css | 101 +++ .../OtherScriptTried/multiselect.js | 557 +++++++++++++++++ js/multiselect/multiselect.css | 124 +--- js/multiselect/multiselect.js | 573 +----------------- views/admin/members/list.html | 32 +- 5 files changed, 710 insertions(+), 677 deletions(-) create mode 100644 js/multiselect/OtherScriptTried/multiselect.css create mode 100644 js/multiselect/OtherScriptTried/multiselect.js diff --git a/js/multiselect/OtherScriptTried/multiselect.css b/js/multiselect/OtherScriptTried/multiselect.css new file mode 100644 index 00000000..e8b35824 --- /dev/null +++ b/js/multiselect/OtherScriptTried/multiselect.css @@ -0,0 +1,101 @@ +.ms-options-wrap, +.ms-options-wrap * { + box-sizing: border-box; +} + +.ms-options-wrap > button:focus, +.ms-options-wrap > button { + position: relative; + width: 100%; + text-align: left; + border: 1px solid #aaa; + background-color: #fff; + padding: 5px 20px 5px 5px; + margin-top: 1px; + font-size: 13px; + color: #aaa; + outline: none; + white-space: nowrap; +} + +.ms-options-wrap > button:after { + content: ' '; + height: 0; + position: absolute; + top: 50%; + right: 5px; + width: 0; + border: 6px solid rgba(0, 0, 0, 0); + border-top-color: #999; + margin-top: -3px; +} + +.ms-options-wrap > .ms-options { + position: absolute; + left: 0; + width: 100%; + margin-top: 1px; + margin-bottom: 20px; + background: white; + z-index: 2000; + border: 1px solid #aaa; +} + +.ms-options-wrap > .ms-options > .ms-search input { + width: 100%; + padding: 4px 5px; + border: none; + border-bottom: 1px groove; + outline: none; +} + +.ms-options-wrap > .ms-options .ms-selectall { + display: inline-block; + font-size: .9em; + text-transform: lowercase; + text-decoration: none; +} +.ms-options-wrap > .ms-options .ms-selectall:hover { + text-decoration: underline; +} + +.ms-options-wrap > .ms-options > .ms-selectall.global { + margin: 4px 5px; +} + +.ms-options-wrap > .ms-options > ul { + line-height: .2em; +} + +.ms-options-wrap > .ms-options > ul > li.optgroup { + padding: 5px; +} +.ms-options-wrap > .ms-options > ul > li.optgroup + li.optgroup { + border-top: 1px solid #aaa; +} + +.ms-options-wrap > .ms-options > ul > li.optgroup .label { + display: block; + padding: 5px 0 0 0; + font-weight: bold; +} + +.ms-options-wrap > .ms-options > ul label { + position: relative; + display: inline-block; + width: 100%; + padding: 4px; + margin: 1px 0; +} + +.ms-options-wrap > .ms-options > ul li.selected label, +.ms-options-wrap > .ms-options > ul label:hover { + background-color: #efefef; +} + +.ms-options-wrap > .ms-options > ul input[type="checkbox"] { + margin-right: 5px; + position: absolute; + left: 4px; +/* top: 7px; */ +} \ No newline at end of file diff --git a/js/multiselect/OtherScriptTried/multiselect.js b/js/multiselect/OtherScriptTried/multiselect.js new file mode 100644 index 00000000..c71cdaf9 --- /dev/null +++ b/js/multiselect/OtherScriptTried/multiselect.js @@ -0,0 +1,557 @@ +/** + * Display a nice easy to use multiselect list + * @Version: 2.0 + * @Author: Patrick Springstubbe + * @Contact: @JediNobleclem + * @Website: springstubbe.us + * @Source: https://github.com/nobleclem/jQuery-MultiSelect + * @Notes: If select list is hidden on page load use the jquery.actual plugin + * to resolve issues with preselected items placeholder text + * https://github.com/dreamerslab/jquery.actual + * + * Usage: + * $('select[multiple]').multiselect(); + * $('select[multiple]').multiselect({ placeholder: 'Select options' }); + * $('select[multiple]').multiselect('reload'); + * $('select[multiple]').multiselect( 'loadOption', [{ + * name : 'Option Name 1', + * value : 'option-value-1', + * checked: false + * },{ + * name : 'Option Name 2', + * value : 'option-value-2', + * checked: false + * }]); + * + **/ +(function($){ + var defaults = { + placeholder : 'Select options', // text to use in dummy input + columns : 1, // how many columns should be use to show options + search : false, // include option search box + // search filter options + searchOptions : { + 'default' : 'Search', // search input placeholder text + showOptGroups: false, // show option group titles if no options remaining + onSearch : function( element ){} // fires on keyup before search on options happens + }, + selectAll : false, // add select all option + selectGroup : false, // select entire optgroup + minHeight : 200, // minimum height of option overlay + maxHeight : null, // maximum height of option overlay + showCheckbox : true, // display the checkbox to the user + jqActualOpts : {}, // options for jquery.actual + + // Callbacks + onLoad : function( element ) { // fires at end of list initialization + $(element).hide(); + }, + onOptionClick : function( element, option ){}, // fires when an option is clicked + + // @NOTE: these are for future development + maxWidth : null, // maximum width of option overlay (or selector) + minSelect : false, // minimum number of items that can be selected + maxSelect : false, // maximum number of items that can be selected + }; + + var msCounter = 1; + var placeWidth = 0; + + function MultiSelect( element, options ) + { + this.element = element; + this.options = $.extend( {}, defaults, options ); + this.load(); + } + + MultiSelect.prototype = { + /* LOAD CUSTOM MULTISELECT DOM/ACTIONS */ + load: function() { + var instance = this; + + // make sure this is a select list and not loaded + if( (instance.element.nodeName != 'SELECT') || $(instance.element).hasClass('jqmsLoaded') ) { + return true; + } + + // sanity check so we don't double load on a select element + $(instance.element).addClass('jqmsLoaded'); + + // add option container + $(instance.element).after('
    '); + var placeholder = $(instance.element).next('.ms-options-wrap').find('> button:first-child'); + var optionsWrap = $(instance.element).next('.ms-options-wrap').find('> .ms-options'); + var optionsList = optionsWrap.find('> ul'); + var hasOptGroup = $(instance.element).find('optgroup').length ? true : false; + + var maxWidth = null; + if( typeof instance.options.width == 'number' ) { + optionsWrap.parent().css( 'position', 'relative' ); + maxWidth = instance.options.width; + } + else if( typeof instance.options.width == 'string' ) { + $( instance.options.width ).css( 'position', 'relative' ); + maxWidth = '100%'; + } + else { + optionsWrap.parent().css( 'position', 'relative' ); + } + + var maxHeight = ($(window).height() - optionsWrap.offset().top - 20); + if( instance.options.maxHeight ) { + maxHeight = ($(window).height() - optionsWrap.offset().top - 20); + maxHeight = maxHeight < instance.options.minHeight ? instance.options.minHeight : maxheight; + } + + maxHeight = maxHeight < instance.options.minHeight ? instance.options.minHeight : maxHeight; + + optionsWrap.css({ + maxWidth : maxWidth, + minHeight: instance.options.minHeight, + maxHeight: maxHeight, + overflow : 'auto' + }).hide(); + + // isolate options scroll + // @source: https://github.com/nobleclem/jQuery-IsolatedScroll + optionsWrap.bind( 'touchmove mousewheel DOMMouseScroll', function ( e ) { + if( ($(this).outerHeight() < $(this)[0].scrollHeight) ) { + var e0 = e.originalEvent, + delta = e0.wheelDelta || -e0.detail; + + if( ($(this).outerHeight() + $(this)[0].scrollTop) > $(this)[0].scrollHeight ) { + e.preventDefault(); + this.scrollTop += ( delta < 0 ? 1 : -1 ); + } + } + }); + + // hide options menus if click happens off of the list placeholder button + $(document).off('click.ms-hideopts').on('click.ms-hideopts', function( event ){ + if( !$(event.target).closest('.ms-options-wrap').length ) { + $('.ms-options-wrap > .ms-options:visible').hide(); + } + }); + + // disable button action + placeholder.bind('mousedown',function( event ){ + // ignore if its not a left click + if( event.which != 1 ) { + return true; + } + + // hide other menus before showing this one + $('.ms-options-wrap > .ms-options:visible').each(function(){ + if( $(this).parent().prev()[0] != optionsWrap.parent().prev()[0] ) { + $(this).hide(); + } + }); + + // show/hide options + optionsWrap.toggle(); + + // recalculate height + if( optionsWrap.is(':visible') ) { + optionsWrap.css( 'maxHeight', '' ); + + var maxHeight = ($(window).height() - optionsWrap.offset().top - 20); + if( instance.options.maxHeight ) { + maxHeight = ($(window).height() - optionsWrap.offset().top - 20); + maxHeight = maxHeight < instance.options.minHeight ? instance.options.minHeight : maxheight; + } + maxHeight = maxHeight < instance.options.minHeight ? instance.options.minHeight : maxHeight; + + optionsWrap.css( 'maxHeight', maxHeight ); + } + }).click(function( event ){ event.preventDefault(); }); + + // add placeholder copy + if( instance.options.placeholder ) { + placeholder.text( instance.options.placeholder ); + } + + // add search box + if( instance.options.search ) { + optionsList.before(''); + + var search = optionsWrap.find('.ms-search input'); + search.on('keyup', function(){ + // ignore keystrokes that don't make a difference + if( $(this).data('lastsearch') == $(this).val() ) { + return true; + } + + $(this).data('lastsearch', $(this).val() ); + + // USER CALLBACK + if( typeof instance.options.searchOptions.onSearch == 'function' ) { + instance.options.searchOptions.onSearch( instance.element ); + } + + // search non optgroup li's + optionsList.find('li:not(.optgroup)').each(function(){ + var optText = $(this).text(); + + // show option if string exists + if( optText.toLowerCase().indexOf( search.val().toLowerCase() ) > -1 ) { + $(this).show(); + } + // don't hide selected items + else if( !$(this).hasClass('selected') ) { + $(this).hide(); + } + + // hide / show optgroups depending on if options within it are visible + if( !instance.options.searchOptions.showOptGroups && $(this).closest('li.optgroup') ) { + $(this).closest('li.optgroup').show(); + + if( $(this).closest('li.optgroup').find('li:visible').length ) { + $(this).closest('li.optgroup').show(); + } + else { + $(this).closest('li.optgroup').hide(); + } + } + }); + }); + } + + // add global select all options + if( instance.options.selectAll ) { + optionsList.before('Select all/none'); + } + + // handle select all option + optionsWrap.on('click', '.ms-selectall', function( event ){ + event.preventDefault(); + + if( $(this).hasClass('global') ) { + // check if any selected if so then select them + if( optionsList.find('li:not(.optgroup)').filter(':not(.selected)').length ) { + optionsList.find('li:not(.optgroup)').filter(':not(.selected)').find('input[type="checkbox"]').trigger('click'); + } + // deselect everything + else { + optionsList.find('li:not(.optgroup).selected input[type="checkbox"]').trigger('click'); + } + } + else if( $(this).closest('li').hasClass('optgroup') ) { + var optgroup = $(this).closest('li.optgroup'); + + // check if any selected if so then select them + if( optgroup.find('li:not(.selected)').length ) { + optgroup.find('li:not(.selected) input[type="checkbox"]').trigger('click'); + } + // deselect everything + else { + optgroup.find('li.selected input[type="checkbox"]').trigger('click'); + } + } + }); + + // add options to wrapper + var options = []; + $(instance.element).children().each(function(){ + if( this.nodeName == 'OPTGROUP' ) { + var groupOptions = []; + + $(this).children('option').each(function(){ + groupOptions[ $(this).val() ] = { + name : $(this).text(), + value : $(this).val(), + checked: $(this).prop( 'selected' ) + }; + }); + + options.push({ + label : $(this).attr('label'), + options: groupOptions + }); + } + else if( this.nodeName == 'OPTION' ) { + options.push({ + name : $(this).text(), + value : $(this).val(), + checked: $(this).prop( 'selected' ) + }); + } + else { + // bad option + return true; + } + }); + instance.loadOptions( options ); + + // COLUMNIZE + if( hasOptGroup ) { + // float non grouped options + optionsList.find('> li:not(.optgroup)').css({ + float: 'left', + width: (100 / instance.options.columns) +'%' + }); + + // add CSS3 column styles + optionsList.find('li.optgroup').css({ + clear: 'both' + }).find('> ul').css({ + 'column-count' : instance.options.columns, + 'column-gap' : 0, + '-webkit-column-count': instance.options.columns, + '-webkit-column-gap' : 0, + '-moz-column-count' : instance.options.columns, + '-moz-column-gap' : 0 + }); + + // for crappy IE versions float grouped options + if( this._ieVersion() && (this._ieVersion() < 10) ) { + optionsList.find('li.optgroup > ul > li').css({ + float: 'left', + width: (100 / instance.options.columns) +'%' + }); + } + } + else { + // add CSS3 column styles + optionsList.css({ + 'column-count' : instance.options.columns, + 'column-gap' : 0, + '-webkit-column-count': instance.options.columns, + '-webkit-column-gap' : 0, + '-moz-column-count' : instance.options.columns, + '-moz-column-gap' : 0 + }); + + // for crappy IE versions float grouped options + if( this._ieVersion() && (this._ieVersion() < 10) ) { + optionsList.find('> li').css({ + float: 'left', + width: (100 / instance.options.columns) +'%' + }); + } + } + + // BIND SELECT ACTION + optionsWrap.on( 'click', 'input[type="checkbox"]', function(){ + $(this).closest( 'li' ).toggleClass( 'selected' ); + + var select = optionsWrap.parent().prev(); + + // toggle clicked option + select.find('option[value="'+ $(this).val() +'"]').prop( + 'selected', $(this).is(':checked') + ).closest('select').trigger('change'); + + if( typeof instance.options.onOptionClick == 'function' ) { + instance.options.onOptionClick(); + } + + instance._updatePlaceholderText(); + }); + + // hide native select list + if( typeof instance.options.onLoad === 'function' ) { + instance.options.onLoad( instance.element ); + } + else { + $(instance.element).hide(); + } + }, + + /* LOAD SELECT OPTIONS */ + loadOptions: function( options, overwrite ) { + overwrite = (typeof overwrite == 'boolean') ? overwrite : true; + + var instance = this; + var optionsList = $(instance.element).next('.ms-options-wrap').find('> .ms-options > ul'); + + if( overwrite ) { + optionsList.find('> li').remove(); + } + + for( var key in options ) { + var thisOption = options[ key ]; + var container = $('
  • '); + + // optgroup + if( thisOption.hasOwnProperty('options') ) { + container.addClass('optgroup'); + container.append(''+ thisOption.label +''); + container.find('> .label').css({ + clear: 'both' + }); + + if( instance.options.selectGroup ) { + container.append('Select all') + } + + container.append(''); + + for( var gKey in thisOption.options ) { + var thisGOption = thisOption.options[ gKey ]; + var gContainer = $('
  • ').addClass('ms-reflow'); + + instance._addOption( gContainer, thisGOption ); + + container.find('> ul').append( gContainer ); + } + } + // option + else if( thisOption.hasOwnProperty('value') ) { + container.addClass('ms-reflow') + + instance._addOption( container, thisOption ); + } + + optionsList.append( container ); + } + + optionsList.find('.ms-reflow input[type="checkbox"]').each(function( idx ){ + if( $(this).css('display').match(/block$/) ) { + var checkboxWidth = $(this).outerWidth(); + checkboxWidth = checkboxWidth ? checkboxWidth : 15; + + $(this).closest('label').css( + 'padding-left', + (parseInt( $(this).closest('label').css('padding-left') ) * 2) + checkboxWidth + ); + + $(this).closest('.ms-reflow').removeClass('ms-reflow'); + } + }); + + instance._updatePlaceholderText(); + }, + + /* RESET THE DOM */ + unload: function() { + $(this.element).next('.ms-options-wrap').remove(); + $(this.element).show(function(){ + $(this).css('display','').removeClass('jqmsLoaded'); + }); + }, + + /* RELOAD JQ MULTISELECT LIST */ + reload: function() { + // remove existing options + $(this.element).next('.ms-options-wrap').remove(); + $(this.element).removeClass('jqmsLoaded'); + + // load element + this.load(); + }, + + /** PRIVATE FUNCTIONS **/ + // update selected placeholder text + _updatePlaceholderText: function(){ + var instance = this; + var placeholder = $(instance.element).next('.ms-options-wrap').find('> button:first-child'); + var optionsWrap = $(instance.element).next('.ms-options-wrap').find('> .ms-options'); + var select = optionsWrap.parent().prev(); + + // get selected options + var selOpts = []; + select.find('option:selected').each(function(){ + selOpts.push( $(this).text() ); + }); + + // UPDATE PLACEHOLDER TEXT WITH OPTIONS SELECTED + placeholder.text( selOpts.join( ', ' ) ); + var copy = placeholder.clone().css({ + display : 'inline', + width : 'auto', + visibility: 'hidden' + }).appendTo( optionsWrap.parent() ); + + // if the jquery.actual plugin is loaded use it to get the widths + var copyWidth = (typeof $.fn.actual !== 'undefined') ? copy.actual( 'width', instance.options.jqActualOpts ) : copy.width(); +// var placeWidth = (typeof $.fn.actual !== 'undefined') ? placeholder.actual( 'width', instance.options.jqActualOpts ) : placeholder.width(); + + // Hacked placeWidth to function for me - CPS + if (placeWidth == 0) { + placeWidth = (typeof $.fn.actual !== 'undefined') ? placeholder.actual( 'width', instance.options.jqActualOpts ) : placeholder.width(); + if (instance.options.maxWidth < placeWidth) { + placeWidth = instance.options.maxWidth; + } + } + + // if copy is larger than button width use "# selected" + if( copyWidth > placeWidth ) { + placeholder.text( selOpts.length +' selected' ); + } + // if options selected then use those + else if( selOpts.length ) { + placeholder.text( selOpts.join( ', ' ) ); + } + // replace placeholder text + else { + placeholder.text( instance.options.placeholder ); + } + + // remove dummy element + copy.remove(); + }, + + // Add option to the custom dom list + _addOption: function( container, option ) { + container.text( option.name ); + container.prepend( + $('') + .val( option.value ) + .attr( 'title', option.name ) + .attr( 'id', 'ms-opt-'+ msCounter ) + ); + + if( option.checked ) { + container.addClass('default'); + container.addClass('selected'); + container.find( 'input[type="checkbox"]' ).prop( 'checked', true ); + } + + var label = $('').attr( 'for', 'ms-opt-'+ msCounter ); + container.wrapInner( label ); + + + if( !this.options.showCheckbox ) { + container.find('input[id="ms-opt-'+ msCounter +'"]').hide(); + } + + msCounter = msCounter + 1; + }, + + // check ie version + _ieVersion: function() { + var myNav = navigator.userAgent.toLowerCase(); + return (myNav.indexOf('msie') != -1) ? parseInt(myNav.split('msie')[1]) : false; + } + }; + + // ENABLE JQUERY PLUGIN FUNCTION + $.fn.multiselect = function( options ){ + var args = arguments; + var ret; + + // menuize each list + if( (options === undefined) || (typeof options === 'object') ) { + return this.each(function(){ + if( !$.data( this, 'plugin_multiselect' ) ) { + $.data( this, 'plugin_multiselect', new MultiSelect( this, options ) ); + } + }); + } else if( (typeof options === 'string') && (options[0] !== '_') && (options !== 'init') ) { + this.each(function(){ + var instance = $.data( this, 'plugin_multiselect' ); + + if( instance instanceof MultiSelect && typeof instance[ options ] === 'function' ) { + ret = instance[ options ].apply( instance, Array.prototype.slice.call( args, 1 ) ); + } + + // special destruct handler + if( options === 'unload' ) { + $.data( this, 'plugin_multiselect', null ); + } + }); + + return ret; + } + }; +}(jQuery)); \ No newline at end of file diff --git a/js/multiselect/multiselect.css b/js/multiselect/multiselect.css index e8b35824..080ecd74 100644 --- a/js/multiselect/multiselect.css +++ b/js/multiselect/multiselect.css @@ -1,101 +1,23 @@ -.ms-options-wrap, -.ms-options-wrap * { - box-sizing: border-box; -} - -.ms-options-wrap > button:focus, -.ms-options-wrap > button { - position: relative; - width: 100%; - text-align: left; - border: 1px solid #aaa; - background-color: #fff; - padding: 5px 20px 5px 5px; - margin-top: 1px; - font-size: 13px; - color: #aaa; - outline: none; - white-space: nowrap; -} - -.ms-options-wrap > button:after { - content: ' '; - height: 0; - position: absolute; - top: 50%; - right: 5px; - width: 0; - border: 6px solid rgba(0, 0, 0, 0); - border-top-color: #999; - margin-top: -3px; -} - -.ms-options-wrap > .ms-options { - position: absolute; - left: 0; - width: 100%; - margin-top: 1px; - margin-bottom: 20px; - background: white; - z-index: 2000; - border: 1px solid #aaa; -} - -.ms-options-wrap > .ms-options > .ms-search input { - width: 100%; - padding: 4px 5px; - border: none; - border-bottom: 1px groove; - outline: none; -} - -.ms-options-wrap > .ms-options .ms-selectall { - display: inline-block; - font-size: .9em; - text-transform: lowercase; - text-decoration: none; -} -.ms-options-wrap > .ms-options .ms-selectall:hover { - text-decoration: underline; -} - -.ms-options-wrap > .ms-options > .ms-selectall.global { - margin: 4px 5px; -} - -.ms-options-wrap > .ms-options > ul { - line-height: .2em; -} - -.ms-options-wrap > .ms-options > ul > li.optgroup { - padding: 5px; -} -.ms-options-wrap > .ms-options > ul > li.optgroup + li.optgroup { - border-top: 1px solid #aaa; -} - -.ms-options-wrap > .ms-options > ul > li.optgroup .label { - display: block; - padding: 5px 0 0 0; - font-weight: bold; -} - -.ms-options-wrap > .ms-options > ul label { - position: relative; - display: inline-block; - width: 100%; - padding: 4px; - margin: 1px 0; -} - -.ms-options-wrap > .ms-options > ul li.selected label, -.ms-options-wrap > .ms-options > ul label:hover { - background-color: #efefef; -} - -.ms-options-wrap > .ms-options > ul input[type="checkbox"] { - margin-right: 5px; - position: absolute; - left: 4px; -/* top: 7px; */ -} \ No newline at end of file +.ui-multiselect { padding:2px 0 2px 4px; text-align:left } +.ui-multiselect span.ui-icon { float:right } +.ui-multiselect-single .ui-multiselect-checkboxes input { position:absolute !important; top: auto !important; left:-9999px; } +.ui-multiselect-single .ui-multiselect-checkboxes label { padding:5px !important } + +.ui-multiselect-header { margin-bottom:3px; padding:3px 0 3px 4px } +.ui-multiselect-header ul { font-size:0.9em } +.ui-multiselect-header ul li { float:left; padding:0 10px 0 0 } +.ui-multiselect-header a { text-decoration:none } +.ui-multiselect-header a:hover { text-decoration:underline } +.ui-multiselect-header span.ui-icon { float:left } +.ui-multiselect-header li.ui-multiselect-close { float:right; text-align:right; padding-right:0 } + +.ui-multiselect-menu { display:none; padding:3px; position:absolute; z-index:10000; text-align: left } +.ui-multiselect-checkboxes { position:relative /* fixes bug in IE6/7 */; overflow-y:scroll } +.ui-multiselect-checkboxes label { cursor:default; display:block; border:1px solid transparent; padding:3px 1px } +.ui-multiselect-checkboxes label input { position:relative; top:1px } +.ui-multiselect-checkboxes li { clear:both; font-size:0.9em; padding-right:3px } +.ui-multiselect-checkboxes li.ui-multiselect-optgroup-label { text-align:center; font-weight:bold; border-bottom:1px solid } +.ui-multiselect-checkboxes li.ui-multiselect-optgroup-label a { display:block; padding:3px; margin:1px 0; text-decoration:none } + +/* remove label borders in IE6 because IE6 does not support transparency */ +* html .ui-multiselect-checkboxes label { border:n \ No newline at end of file diff --git a/js/multiselect/multiselect.js b/js/multiselect/multiselect.js index c71cdaf9..eb723671 100644 --- a/js/multiselect/multiselect.js +++ b/js/multiselect/multiselect.js @@ -1,557 +1,20 @@ -/** - * Display a nice easy to use multiselect list - * @Version: 2.0 - * @Author: Patrick Springstubbe - * @Contact: @JediNobleclem - * @Website: springstubbe.us - * @Source: https://github.com/nobleclem/jQuery-MultiSelect - * @Notes: If select list is hidden on page load use the jquery.actual plugin - * to resolve issues with preselected items placeholder text - * https://github.com/dreamerslab/jquery.actual +/* + * jQuery MultiSelect UI Widget 1.13 + * Copyright (c) 2012 Eric Hynds * - * Usage: - * $('select[multiple]').multiselect(); - * $('select[multiple]').multiselect({ placeholder: 'Select options' }); - * $('select[multiple]').multiselect('reload'); - * $('select[multiple]').multiselect( 'loadOption', [{ - * name : 'Option Name 1', - * value : 'option-value-1', - * checked: false - * },{ - * name : 'Option Name 2', - * value : 'option-value-2', - * checked: false - * }]); + * http://www.erichynds.com/jquery/jquery-ui-multiselect-widget/ * - **/ -(function($){ - var defaults = { - placeholder : 'Select options', // text to use in dummy input - columns : 1, // how many columns should be use to show options - search : false, // include option search box - // search filter options - searchOptions : { - 'default' : 'Search', // search input placeholder text - showOptGroups: false, // show option group titles if no options remaining - onSearch : function( element ){} // fires on keyup before search on options happens - }, - selectAll : false, // add select all option - selectGroup : false, // select entire optgroup - minHeight : 200, // minimum height of option overlay - maxHeight : null, // maximum height of option overlay - showCheckbox : true, // display the checkbox to the user - jqActualOpts : {}, // options for jquery.actual - - // Callbacks - onLoad : function( element ) { // fires at end of list initialization - $(element).hide(); - }, - onOptionClick : function( element, option ){}, // fires when an option is clicked - - // @NOTE: these are for future development - maxWidth : null, // maximum width of option overlay (or selector) - minSelect : false, // minimum number of items that can be selected - maxSelect : false, // maximum number of items that can be selected - }; - - var msCounter = 1; - var placeWidth = 0; - - function MultiSelect( element, options ) - { - this.element = element; - this.options = $.extend( {}, defaults, options ); - this.load(); - } - - MultiSelect.prototype = { - /* LOAD CUSTOM MULTISELECT DOM/ACTIONS */ - load: function() { - var instance = this; - - // make sure this is a select list and not loaded - if( (instance.element.nodeName != 'SELECT') || $(instance.element).hasClass('jqmsLoaded') ) { - return true; - } - - // sanity check so we don't double load on a select element - $(instance.element).addClass('jqmsLoaded'); - - // add option container - $(instance.element).after('
      '); - var placeholder = $(instance.element).next('.ms-options-wrap').find('> button:first-child'); - var optionsWrap = $(instance.element).next('.ms-options-wrap').find('> .ms-options'); - var optionsList = optionsWrap.find('> ul'); - var hasOptGroup = $(instance.element).find('optgroup').length ? true : false; - - var maxWidth = null; - if( typeof instance.options.width == 'number' ) { - optionsWrap.parent().css( 'position', 'relative' ); - maxWidth = instance.options.width; - } - else if( typeof instance.options.width == 'string' ) { - $( instance.options.width ).css( 'position', 'relative' ); - maxWidth = '100%'; - } - else { - optionsWrap.parent().css( 'position', 'relative' ); - } - - var maxHeight = ($(window).height() - optionsWrap.offset().top - 20); - if( instance.options.maxHeight ) { - maxHeight = ($(window).height() - optionsWrap.offset().top - 20); - maxHeight = maxHeight < instance.options.minHeight ? instance.options.minHeight : maxheight; - } - - maxHeight = maxHeight < instance.options.minHeight ? instance.options.minHeight : maxHeight; - - optionsWrap.css({ - maxWidth : maxWidth, - minHeight: instance.options.minHeight, - maxHeight: maxHeight, - overflow : 'auto' - }).hide(); - - // isolate options scroll - // @source: https://github.com/nobleclem/jQuery-IsolatedScroll - optionsWrap.bind( 'touchmove mousewheel DOMMouseScroll', function ( e ) { - if( ($(this).outerHeight() < $(this)[0].scrollHeight) ) { - var e0 = e.originalEvent, - delta = e0.wheelDelta || -e0.detail; - - if( ($(this).outerHeight() + $(this)[0].scrollTop) > $(this)[0].scrollHeight ) { - e.preventDefault(); - this.scrollTop += ( delta < 0 ? 1 : -1 ); - } - } - }); - - // hide options menus if click happens off of the list placeholder button - $(document).off('click.ms-hideopts').on('click.ms-hideopts', function( event ){ - if( !$(event.target).closest('.ms-options-wrap').length ) { - $('.ms-options-wrap > .ms-options:visible').hide(); - } - }); - - // disable button action - placeholder.bind('mousedown',function( event ){ - // ignore if its not a left click - if( event.which != 1 ) { - return true; - } - - // hide other menus before showing this one - $('.ms-options-wrap > .ms-options:visible').each(function(){ - if( $(this).parent().prev()[0] != optionsWrap.parent().prev()[0] ) { - $(this).hide(); - } - }); - - // show/hide options - optionsWrap.toggle(); - - // recalculate height - if( optionsWrap.is(':visible') ) { - optionsWrap.css( 'maxHeight', '' ); - - var maxHeight = ($(window).height() - optionsWrap.offset().top - 20); - if( instance.options.maxHeight ) { - maxHeight = ($(window).height() - optionsWrap.offset().top - 20); - maxHeight = maxHeight < instance.options.minHeight ? instance.options.minHeight : maxheight; - } - maxHeight = maxHeight < instance.options.minHeight ? instance.options.minHeight : maxHeight; - - optionsWrap.css( 'maxHeight', maxHeight ); - } - }).click(function( event ){ event.preventDefault(); }); - - // add placeholder copy - if( instance.options.placeholder ) { - placeholder.text( instance.options.placeholder ); - } - - // add search box - if( instance.options.search ) { - optionsList.before(''); - - var search = optionsWrap.find('.ms-search input'); - search.on('keyup', function(){ - // ignore keystrokes that don't make a difference - if( $(this).data('lastsearch') == $(this).val() ) { - return true; - } - - $(this).data('lastsearch', $(this).val() ); - - // USER CALLBACK - if( typeof instance.options.searchOptions.onSearch == 'function' ) { - instance.options.searchOptions.onSearch( instance.element ); - } - - // search non optgroup li's - optionsList.find('li:not(.optgroup)').each(function(){ - var optText = $(this).text(); - - // show option if string exists - if( optText.toLowerCase().indexOf( search.val().toLowerCase() ) > -1 ) { - $(this).show(); - } - // don't hide selected items - else if( !$(this).hasClass('selected') ) { - $(this).hide(); - } - - // hide / show optgroups depending on if options within it are visible - if( !instance.options.searchOptions.showOptGroups && $(this).closest('li.optgroup') ) { - $(this).closest('li.optgroup').show(); - - if( $(this).closest('li.optgroup').find('li:visible').length ) { - $(this).closest('li.optgroup').show(); - } - else { - $(this).closest('li.optgroup').hide(); - } - } - }); - }); - } - - // add global select all options - if( instance.options.selectAll ) { - optionsList.before('Select all/none'); - } - - // handle select all option - optionsWrap.on('click', '.ms-selectall', function( event ){ - event.preventDefault(); - - if( $(this).hasClass('global') ) { - // check if any selected if so then select them - if( optionsList.find('li:not(.optgroup)').filter(':not(.selected)').length ) { - optionsList.find('li:not(.optgroup)').filter(':not(.selected)').find('input[type="checkbox"]').trigger('click'); - } - // deselect everything - else { - optionsList.find('li:not(.optgroup).selected input[type="checkbox"]').trigger('click'); - } - } - else if( $(this).closest('li').hasClass('optgroup') ) { - var optgroup = $(this).closest('li.optgroup'); - - // check if any selected if so then select them - if( optgroup.find('li:not(.selected)').length ) { - optgroup.find('li:not(.selected) input[type="checkbox"]').trigger('click'); - } - // deselect everything - else { - optgroup.find('li.selected input[type="checkbox"]').trigger('click'); - } - } - }); - - // add options to wrapper - var options = []; - $(instance.element).children().each(function(){ - if( this.nodeName == 'OPTGROUP' ) { - var groupOptions = []; - - $(this).children('option').each(function(){ - groupOptions[ $(this).val() ] = { - name : $(this).text(), - value : $(this).val(), - checked: $(this).prop( 'selected' ) - }; - }); - - options.push({ - label : $(this).attr('label'), - options: groupOptions - }); - } - else if( this.nodeName == 'OPTION' ) { - options.push({ - name : $(this).text(), - value : $(this).val(), - checked: $(this).prop( 'selected' ) - }); - } - else { - // bad option - return true; - } - }); - instance.loadOptions( options ); - - // COLUMNIZE - if( hasOptGroup ) { - // float non grouped options - optionsList.find('> li:not(.optgroup)').css({ - float: 'left', - width: (100 / instance.options.columns) +'%' - }); - - // add CSS3 column styles - optionsList.find('li.optgroup').css({ - clear: 'both' - }).find('> ul').css({ - 'column-count' : instance.options.columns, - 'column-gap' : 0, - '-webkit-column-count': instance.options.columns, - '-webkit-column-gap' : 0, - '-moz-column-count' : instance.options.columns, - '-moz-column-gap' : 0 - }); - - // for crappy IE versions float grouped options - if( this._ieVersion() && (this._ieVersion() < 10) ) { - optionsList.find('li.optgroup > ul > li').css({ - float: 'left', - width: (100 / instance.options.columns) +'%' - }); - } - } - else { - // add CSS3 column styles - optionsList.css({ - 'column-count' : instance.options.columns, - 'column-gap' : 0, - '-webkit-column-count': instance.options.columns, - '-webkit-column-gap' : 0, - '-moz-column-count' : instance.options.columns, - '-moz-column-gap' : 0 - }); - - // for crappy IE versions float grouped options - if( this._ieVersion() && (this._ieVersion() < 10) ) { - optionsList.find('> li').css({ - float: 'left', - width: (100 / instance.options.columns) +'%' - }); - } - } - - // BIND SELECT ACTION - optionsWrap.on( 'click', 'input[type="checkbox"]', function(){ - $(this).closest( 'li' ).toggleClass( 'selected' ); - - var select = optionsWrap.parent().prev(); - - // toggle clicked option - select.find('option[value="'+ $(this).val() +'"]').prop( - 'selected', $(this).is(':checked') - ).closest('select').trigger('change'); - - if( typeof instance.options.onOptionClick == 'function' ) { - instance.options.onOptionClick(); - } - - instance._updatePlaceholderText(); - }); - - // hide native select list - if( typeof instance.options.onLoad === 'function' ) { - instance.options.onLoad( instance.element ); - } - else { - $(instance.element).hide(); - } - }, - - /* LOAD SELECT OPTIONS */ - loadOptions: function( options, overwrite ) { - overwrite = (typeof overwrite == 'boolean') ? overwrite : true; - - var instance = this; - var optionsList = $(instance.element).next('.ms-options-wrap').find('> .ms-options > ul'); - - if( overwrite ) { - optionsList.find('> li').remove(); - } - - for( var key in options ) { - var thisOption = options[ key ]; - var container = $('
    • '); - - // optgroup - if( thisOption.hasOwnProperty('options') ) { - container.addClass('optgroup'); - container.append(''+ thisOption.label +''); - container.find('> .label').css({ - clear: 'both' - }); - - if( instance.options.selectGroup ) { - container.append('Select all') - } - - container.append(''); - - for( var gKey in thisOption.options ) { - var thisGOption = thisOption.options[ gKey ]; - var gContainer = $('
    • ').addClass('ms-reflow'); - - instance._addOption( gContainer, thisGOption ); - - container.find('> ul').append( gContainer ); - } - } - // option - else if( thisOption.hasOwnProperty('value') ) { - container.addClass('ms-reflow') - - instance._addOption( container, thisOption ); - } - - optionsList.append( container ); - } - - optionsList.find('.ms-reflow input[type="checkbox"]').each(function( idx ){ - if( $(this).css('display').match(/block$/) ) { - var checkboxWidth = $(this).outerWidth(); - checkboxWidth = checkboxWidth ? checkboxWidth : 15; - - $(this).closest('label').css( - 'padding-left', - (parseInt( $(this).closest('label').css('padding-left') ) * 2) + checkboxWidth - ); - - $(this).closest('.ms-reflow').removeClass('ms-reflow'); - } - }); - - instance._updatePlaceholderText(); - }, - - /* RESET THE DOM */ - unload: function() { - $(this.element).next('.ms-options-wrap').remove(); - $(this.element).show(function(){ - $(this).css('display','').removeClass('jqmsLoaded'); - }); - }, - - /* RELOAD JQ MULTISELECT LIST */ - reload: function() { - // remove existing options - $(this.element).next('.ms-options-wrap').remove(); - $(this.element).removeClass('jqmsLoaded'); - - // load element - this.load(); - }, - - /** PRIVATE FUNCTIONS **/ - // update selected placeholder text - _updatePlaceholderText: function(){ - var instance = this; - var placeholder = $(instance.element).next('.ms-options-wrap').find('> button:first-child'); - var optionsWrap = $(instance.element).next('.ms-options-wrap').find('> .ms-options'); - var select = optionsWrap.parent().prev(); - - // get selected options - var selOpts = []; - select.find('option:selected').each(function(){ - selOpts.push( $(this).text() ); - }); - - // UPDATE PLACEHOLDER TEXT WITH OPTIONS SELECTED - placeholder.text( selOpts.join( ', ' ) ); - var copy = placeholder.clone().css({ - display : 'inline', - width : 'auto', - visibility: 'hidden' - }).appendTo( optionsWrap.parent() ); - - // if the jquery.actual plugin is loaded use it to get the widths - var copyWidth = (typeof $.fn.actual !== 'undefined') ? copy.actual( 'width', instance.options.jqActualOpts ) : copy.width(); -// var placeWidth = (typeof $.fn.actual !== 'undefined') ? placeholder.actual( 'width', instance.options.jqActualOpts ) : placeholder.width(); - - // Hacked placeWidth to function for me - CPS - if (placeWidth == 0) { - placeWidth = (typeof $.fn.actual !== 'undefined') ? placeholder.actual( 'width', instance.options.jqActualOpts ) : placeholder.width(); - if (instance.options.maxWidth < placeWidth) { - placeWidth = instance.options.maxWidth; - } - } - - // if copy is larger than button width use "# selected" - if( copyWidth > placeWidth ) { - placeholder.text( selOpts.length +' selected' ); - } - // if options selected then use those - else if( selOpts.length ) { - placeholder.text( selOpts.join( ', ' ) ); - } - // replace placeholder text - else { - placeholder.text( instance.options.placeholder ); - } - - // remove dummy element - copy.remove(); - }, - - // Add option to the custom dom list - _addOption: function( container, option ) { - container.text( option.name ); - container.prepend( - $('') - .val( option.value ) - .attr( 'title', option.name ) - .attr( 'id', 'ms-opt-'+ msCounter ) - ); - - if( option.checked ) { - container.addClass('default'); - container.addClass('selected'); - container.find( 'input[type="checkbox"]' ).prop( 'checked', true ); - } - - var label = $('').attr( 'for', 'ms-opt-'+ msCounter ); - container.wrapInner( label ); - - - if( !this.options.showCheckbox ) { - container.find('input[id="ms-opt-'+ msCounter +'"]').hide(); - } - - msCounter = msCounter + 1; - }, - - // check ie version - _ieVersion: function() { - var myNav = navigator.userAgent.toLowerCase(); - return (myNav.indexOf('msie') != -1) ? parseInt(myNav.split('msie')[1]) : false; - } - }; - - // ENABLE JQUERY PLUGIN FUNCTION - $.fn.multiselect = function( options ){ - var args = arguments; - var ret; - - // menuize each list - if( (options === undefined) || (typeof options === 'object') ) { - return this.each(function(){ - if( !$.data( this, 'plugin_multiselect' ) ) { - $.data( this, 'plugin_multiselect', new MultiSelect( this, options ) ); - } - }); - } else if( (typeof options === 'string') && (options[0] !== '_') && (options !== 'init') ) { - this.each(function(){ - var instance = $.data( this, 'plugin_multiselect' ); - - if( instance instanceof MultiSelect && typeof instance[ options ] === 'function' ) { - ret = instance[ options ].apply( instance, Array.prototype.slice.call( args, 1 ) ); - } - - // special destruct handler - if( options === 'unload' ) { - $.data( this, 'plugin_multiselect', null ); - } - }); - - return ret; - } - }; -}(jQuery)); \ No newline at end of file + * Depends: + * - jQuery 1.4.2+ + * - jQuery UI 1.8 widget factory + * + * Optional: + * - jQuery UI effects + * - jQuery UI position utility + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + */ +(function(d){var k=0;d.widget("ech.multiselect",{options:{header:!0,height:175,minWidth:225,classes:"",checkAllText:"Check all",uncheckAllText:"Uncheck all",noneSelectedText:"Select options",selectedText:"# selected",selectedList:0,show:null,hide:null,autoOpen:!1,multiple:!0,position:{}},_create:function(){var a=this.element.hide(),b=this.options;this.speed=d.fx.speeds._default;this._isOpen=!1;a=(this.button=d('')).addClass("ui-multiselect ui-widget ui-state-default ui-corner-all").addClass(b.classes).attr({title:a.attr("title"),"aria-haspopup":!0,tabIndex:a.attr("tabIndex")}).insertAfter(a);(this.buttonlabel=d("")).html(b.noneSelectedText).appendTo(a);var a=(this.menu=d("
      ")).addClass("ui-multiselect-menu ui-widget ui-widget-content ui-corner-all").addClass(b.classes).appendTo(document.body),c=(this.header=d("
      ")).addClass("ui-widget-header ui-corner-all ui-multiselect-header ui-helper-clearfix").appendTo(a);(this.headerLinkContainer=d("
        ")).addClass("ui-helper-reset").html(function(){return!0===b.header?'
      • '+b.checkAllText+'
      • '+b.uncheckAllText+"
      • ":"string"===typeof b.header?"
      • "+b.header+"
      • ":""}).append('
      • ').appendTo(c);(this.checkboxContainer=d("
          ")).addClass("ui-multiselect-checkboxes ui-helper-reset").appendTo(a);this._bindEvents();this.refresh(!0);b.multiple||a.addClass("ui-multiselect-single")},_init:function(){!1===this.options.header&&this.header.hide();this.options.multiple||this.headerLinkContainer.find(".ui-multiselect-all, .ui-multiselect-none").hide();this.options.autoOpen&&this.open();this.element.is(":disabled")&&this.disable()},refresh:function(a){var b=this.element,c=this.options,f=this.menu,h=this.checkboxContainer,g=[],e="",i=b.attr("id")||k++;b.find("option").each(function(b){d(this);var a=this.parentNode,f=this.innerHTML,h=this.title,k=this.value,b="ui-multiselect-"+(this.id||i+"-option-"+b),l=this.disabled,n=this.selected,m=["ui-corner-all"],o=(l?"ui-multiselect-disabled ":" ")+this.className,j;"OPTGROUP"===a.tagName&&(j=a.getAttribute("label"),-1===d.inArray(j,g)&&(e+='
        • '+j+"
        • ",g.push(j)));l&&m.push("ui-state-disabled");n&&!c.multiple&&m.push("ui-state-active");e+='
        • ';e+='
        • "});h.html(e);this.labels=f.find("label");this.inputs=this.labels.children("input");this._setButtonWidth();this._setMenuWidth();this.button[0].defaultValue=this.update();a||this._trigger("refresh")},update:function(){var a=this.options,b=this.inputs,c=b.filter(":checked"),f=c.length,a=0===f?a.noneSelectedText:d.isFunction(a.selectedText)?a.selectedText.call(this,f,b.length,c.get()):/\d/.test(a.selectedList)&&0 - - - - - - - - - - -
          Members Found:{$memberCount}Categories: - {foreach from=$categories item=v} {/foreach} - - Show Archived:Pending Only:Text Search:
          + + + Show Archived: + Pending Only: + Text Search: +

          List of Members

          @@ -120,13 +116,7 @@ }); // Expand multi-select on hover - $('#filterCategories').multiselect({ - columns: 1, - placeholder: 'Click to select categories', - search: 1, - selectAll: true, - maxWidth: 200 - }); + $('#filterCategories').multiselect(); }); -- 2.17.1