From f450b6cae21acc12dd96e1a50a7e444e54fceedb Mon Sep 17 00:00:00 2001 From: Acemir Sousa Mendes Date: Tue, 6 May 2014 17:20:01 -0300 Subject: [PATCH 1/2] Improved 'disabled' suport + Improved support 'disabled' for both instances .dk_container select { position: absolute; - top: -99999em; + // top: -99999em; visibility: hidden; } diff --git a/dropkick.css b/dropkick.css index f54b9c4b..595269fd 100644 --- a/dropkick.css +++ b/dropkick.css @@ -18,9 +18,13 @@ -webkit-border-radius: 5px; } .dk_container:focus { outline: 0; } + .dk_container[disabled] { + opacity:.4; } .dk_container a { cursor: pointer; text-decoration: none; } + .dk_container[disabled] a { + cursor: not-allowed; } .dk_toggle { border: 1px solid #ccc; @@ -101,7 +105,7 @@ cursor: default; } .dk_options .disabled a { color: #aaa; } - .dk_options .disabled:hover, .dk_options .disabled:hover a + .dk_options .disabled:hover, .dk_options .disabled:hover a, .dk_options .disabled:focus, .dk_options .disabled:focus a { cursor: default; background-color: #fff; @@ -155,7 +159,7 @@ .dk_container select { position: absolute; - top: -99999em; + /*top: -99999em;*/ /* IE was sending window to top on label click */ visibility: hidden; } .dk_mobile { diff --git a/dropkick.scss b/dropkick.scss index 45c35e1b..fa5e7cb5 100644 --- a/dropkick.scss +++ b/dropkick.scss @@ -23,10 +23,16 @@ &:focus { outline: 0; } + &[disabled] { + opacity:.4; + } a { cursor: pointer; text-decoration: none; } + &[disabled] a { + cursor: not-allowed; + } } // Opens the dropdown and holds the menu label @@ -130,7 +136,7 @@ a { color: #aaa; } - &:hover, &:hover a + &:hover, &:hover a, &:focus, &:focus a { cursor: default; background-color: #fff; @@ -203,7 +209,7 @@ // Hides only dropkick - - - - - - - +
+ +
- + -
+

Creating custom themes

-
-
- -
-
+
+ +
-
+ -
+

Label behaviour

-
-
- - -
-
-
- - +
+ + +
+ + +
+

Disabled <select>

+
+ +
+
+
+

Disabled <option>

+
+ +
+
+ + + diff --git a/jquery.dropkick-min.js b/jquery.dropkick-min.js index ce523d31..612b7380 100644 --- a/jquery.dropkick-min.js +++ b/jquery.dropkick-min.js @@ -1,5 +1,5 @@ /* - * DropKick 1.4-dev + * DropKick 1.5-dev * * Highly customizable lists * https://github.com/robdel12/DropKick @@ -151,7 +151,7 @@ letter = String.fromCharCode(code), options = $dk.find('.dk_options'), open = $dk.hasClass('dk_open'), - lis = options.find('li'), + lis = options.find('li:not(.disabled)'), current = $dk.find('.dk_option_current'), first = lis.first(), last = lis.last(), @@ -185,7 +185,7 @@ break; case keyMap.up: - prev = current.prev('li'); + prev = current.prevAll('li:not(.disabled)').first(); if (open) { if (prev.length) { setCurrent(prev, $dk, e); @@ -200,7 +200,7 @@ case keyMap.down: if (open) { - next = current.next('li').first(); + next = current.nextAll('li:not(.disabled)').first(); if (next.length) { setCurrent(next, $dk, e); } else { @@ -322,6 +322,9 @@ // Check if we have a tabindex set or not set to 0 tabindex = $select.attr('tabindex') || '0', + // Check if the select is disabled at the moment + disabled = !!$select.attr('disabled'), + // The completed dk_container element $dk = false, @@ -355,6 +358,13 @@ }); } + if (disabled) { + $dk.attr({ + disabled:'disabled', + tabindex:-1 + }); + } + // Hide the element, else retrun a built clone if (init == false) { toReturn[i] = $clone[0]; } else { @@ -530,8 +541,25 @@ } }); + }; - return $(toReturn); + methods.disable = function(bool) { + return this.each(function(){ + var + data = $(this).data('dropkick'), + $select = data.$select, + $dk = data.$dk + ; + + // If explicitly false, enable instead + if (bool == false) { + $select.removeAttr('disabled'); + $dk.removeAttr('disabled').attr({tabindex:data.tabindex}); + } else { + $select.attr({disabled:'disabled'}); + $dk.attr({disabled:'disabled',tabindex:-1}); + } + }); }; // Expose the plugin @@ -585,7 +613,7 @@ }); // Globally handle a click outside of the dropdown list by closing it. - $(document).on('click', null, function (e) { + $(document).on('click', null, function(e) { var $eTarget = $(e.target), $dk @@ -599,7 +627,7 @@ closeDropdown($dk); } else { $opened && closeDropdown($opened); - openDropdown($dk,e); + !$dk.attr('disabled') && openDropdown($dk,e); } // Avoids duplication of call to _openDropdown return false; From 22010a3d3297de10e74129c2892254bcac49b4b3 Mon Sep 17 00:00:00 2001 From: Acemir Sousa Mendes Date: Tue, 6 May 2014 20:44:34 -0300 Subject: [PATCH 2/2] Added optgroup support --- dropkick.css | 23 +++++++++++++-- dropkick.scss | 5 ++++ example/example.css | 8 +++++ example/examples.html | 53 ++++++++++++++++++++++++++++++++- jquery.dropkick-min.js | 2 +- jquery.dropkick.js | 67 ++++++++++++++++++++++++++++++------------ 6 files changed, 134 insertions(+), 24 deletions(-) diff --git a/dropkick.css b/dropkick.css index 595269fd..baf7f245 100644 --- a/dropkick.css +++ b/dropkick.css @@ -103,14 +103,31 @@ border-bottom: none; } .dk_options .disabled { cursor: default; } - .dk_options .disabled a { + .dk_options .disabled a, + .dk_options .dk_optgroup.disabled > span { color: #aaa; } - .dk_options .disabled:hover, .dk_options .disabled:hover a, - .dk_options .disabled:focus, .dk_options .disabled:focus a { + .dk_options .disabled:hover a, + .dk_options .disabled:focus a { cursor: default; background-color: #fff; border-bottom-color: #999; text-shadow: none; } + .dk_options .dk_optgroup { + padding-left: 5px; + background: #ddd; + } + .dk_options .dk_optgroup > span { + display: block; + padding: 5px 10px 5px 5px; + font-style: italic; + color: #444; + background: #ddd; + border-bottom: ; + } + .dk_options .dk_optgroup.disabled, + .dk_options .dk_optgroup.disabled > span { + background: #eee; + } .dk_options_inner { max-height: 250px; diff --git a/dropkick.scss b/dropkick.scss index fa5e7cb5..0e148fe8 100644 --- a/dropkick.scss +++ b/dropkick.scss @@ -197,6 +197,11 @@ a, a:link, a:visited{ display: block; } + .dk_optgroup { + > span { + + } + } } .dk_options_inner { diff --git a/example/example.css b/example/example.css index 8d76470c..a810e6a2 100644 --- a/example/example.css +++ b/example/example.css @@ -118,6 +118,14 @@ ul { line-height: 2.25em; } + .example button { + border: 1px solid #ccc; + color: #333; + padding: 7px 10px; + text-shadow: #fff 1px 1px 0; + border-radius: 5px; + } + fieldset { border: none; diff --git a/example/examples.html b/example/examples.html index 0a59a7b7..e80e48d2 100644 --- a/example/examples.html +++ b/example/examples.html @@ -10,7 +10,7 @@ - + @@ -179,6 +204,9 @@

Disabled <select>

+
+ +
@@ -196,6 +224,29 @@

Disabled <option>

+
+

With <optgroup>

+
+ +
+
+ diff --git a/jquery.dropkick-min.js b/jquery.dropkick-min.js index 612b7380..3cae2317 100644 --- a/jquery.dropkick-min.js +++ b/jquery.dropkick-min.js @@ -7,4 +7,4 @@ * Created by: Jamie Lottering * * -*/(function(e,t,n){"use strict";var i=navigator.userAgent.match(/MSIE ([0-9]{1,}[\.0-9]{0,})/),a=!!i,o=a&&parseFloat(i[1])<7,r=navigator.userAgent.match(/iPad|iPhone|Android|IEMobile|BlackBerry/i),d={},l=[],s={left:37,up:38,right:39,down:40,enter:13,tab:9,zero:48,z:90,last:221},c=['"].join(""),p='
  • {{ text }}
  • ',u={startSpeed:400,theme:!1,changes:!1,syncReverse:!0,nativeMobile:!0,autoWidth:!0},k=null,f=null,h=function(e,t,n){var i=e.attr("data-dk-dropdown-value"),a=e.text(),o=t.data("dropkick"),r=o.$select;n=n||!1,t.find(".dk_label").text(a),n?r.val(i):r.val(i).trigger("change"),!o.settings.change||n||o.settings.syncReverse||o.settings.change.call(r,i,a)},v=function(e){e.removeClass("dk_open dk_open_top"),k=null},g=function(n){if(n.data("dropkick").settings.fixedMove)return"up"==n.data("dropkick").settings.fixedMove?!1:!0;var i=n.find(".dk_toggle"),a=n.find(".dk_options").outerHeight(),o=e(t).height()-i.outerHeight()-i.offset().top+e(t).scrollTop(),r=i.offset().top-e(t).scrollTop();return r>a?o>a:!0},_=function(e,t,n){var i=e.find(".dk_options_inner"),a=t.prevAll("li").outerHeight()*t.prevAll("li").length,o=i.scrollTop(),r=i.height()+i.scrollTop()-t.outerHeight();(n&&"keydown"===n.type||o>a||a>r)&&i.scrollTop(a)},b=function(e,t){var n=g(e),i=n?"dk_open":"dk_open_top dk_open";e.find(".dk_options").css({top:n?e.find(".dk_toggle").outerHeight()-1:"",bottom:n?"":e.find(".dk_toggle").outerHeight()-1}),k=e.addClass(i),_(e,e.find(".dk_option_current"),t)},m=function(e,t,n){t.find(".dk_option_current").removeClass("dk_option_current"),e.addClass("dk_option_current"),_(t,e,n)},w=function(t,n){var i,a,o,r,d,l,c,p=t.keyCode,u=n.data("dropkick"),k=String.fromCharCode(p),f=n.find(".dk_options"),g=n.hasClass("dk_open"),_=f.find("li:not(.disabled)"),w=n.find(".dk_option_current"),x=_.first(),C=_.last();switch(p){case s.enter:g?w.hasClass("disabled")||(h(w.find("a"),n),v(n)):b(n,t),t.preventDefault();break;case s.tab:g&&(w.length&&h(w.find("a"),n),v(n));break;case s.up:a=w.prevAll("li:not(.disabled)").first(),g?a.length?m(a,n,t):m(C,n,t):b(n,t),t.preventDefault();break;case s.down:g?(i=w.nextAll("li:not(.disabled)").first(),i.length?m(i,n,t):m(x,n,t)):b(n,t),t.preventDefault()}if(p>=s.zero&&p<=s.z){for(o=(new Date).getTime(),null===u.finder||void 0===u.finder?(u.finder=k.toUpperCase(),u.timer=o):o>parseInt(u.timer,10)+1e3?(u.finder=k.toUpperCase(),u.timer=o):(u.finder=u.finder+k.toUpperCase(),u.timer=o),r=_.find("a"),d=0,l=r.length;l>d;d++)if(c=e(r[d]),0===c.html().toUpperCase().indexOf(u.finder)){h(c,n),m(c.parent(),n,t);break}n.data("dropkick",u)}},x=function(t){return e.trim(t).length>0?t:!1},C=function(t,n){var i,a,o,r,d,l=t.replace("{{ id }}",n.id).replace("{{ label }}",n.label).replace("{{ tabindex }}",n.tabindex),s=[];if(n.options&&n.options.length)for(a=0,o=n.options.length;o>a;a++)r=e(n.options[a]),d=0===a&&void 0!==r.attr("selected")&&void 0!==r.attr("disabled")?null:p.replace("{{ value }}",r.val()).replace("{{ current }}",x(r.val())===n.value?"dk_option_current":"").replace("{{ disabled }}",void 0!==r.attr("disabled")?"disabled":"").replace("{{ text }}",e.trim(r.html())),s[s.length]=d;return i=e(l),i.find(".dk_options_inner").html(s.join("")),i};o||(n.documentElement.className=n.documentElement.className+" dk_fouc"),d.init=function(t){return t=e.extend({},u,t),c=t.dropdownTemplate?t.dropdownTemplate:c,p=t.optionTemplate?t.optionTemplate:p,this.each(function(){var n,i,a=e(this),o=a.find(":selected").first(),d=a.find("option"),s=a.data("dropkick")||{},p=a.attr("id")||a.attr("name"),u=t.width||a.outerWidth(),k=a.attr("tabindex")||"0",h=!!a.attr("disabled"),v=!1;return s.id?a:(s.settings=t,s.tabindex=k,s.id=p,s.$original=o,s.$select=a,s.value=x(a.val())||x(o.attr("value")),s.label=o.text(),s.options=d,v=C(c,s),s.settings.autoWidth&&v.find(".dk_toggle").css({width:u+"px"}),h&&v.attr({disabled:"disabled",tabindex:-1}),a.before(v).appendTo(v),v.fadeIn(t.startSpeed),n=t.theme||"default",v.addClass("dk_theme_"+n),s.theme=n,s.$dk=v,a.data("dropkick",s),v.addClass(a.attr("class")),v.data("dropkick",s),l[l.length]=a,v.on("focus.dropkick",function(){f=v.attr("disabled")?null:v.addClass("dk_focus")}).on("blur.dropkick",function(){v.removeClass("dk_focus"),f=null}),r&&s.settings.nativeMobile&&v.addClass("dk_mobile"),s.settings.syncReverse&&a.on("change",function(t){var n=a.val(),i=e('a[data-dk-dropdown-value="'+n+'"]',v),o=i.text();v.find(".dk_label").text(o),m(i.parent(),v,t),s.settings.change&&s.settings.change.call(a,n,o)}),i=a.attr("form")?e("#"+a.attr("form").replace(" ",", #")):a.closest("form"),void(i.length&&i.on("reset",function(){a.dropkick("reset")})))})},d.theme=function(t){var n=e(this).data("dropkick"),i=n.$dk,a="dk_theme_"+n.theme;i.removeClass(a).addClass("dk_theme_"+t),n.theme=t},d.reset=function(t){return this.each(function(){var n=e(this).data("dropkick"),i=n.$dk,a=e('a[data-dk-dropdown-value="'+n.$original.attr("value")+'"]',i);n.$original.prop("selected",!0),m(a.parent(),i),h(a,i,!t)})},d.setValue=function(t){return this.each(function(){var n=e(this).data("dropkick").$dk,i=e('.dk_options a[data-dk-dropdown-value="'+t+'"]',n);i.length?h(i,n)|m(i.parent(),n):console.warn("There is no option with this value in "+n.selector)})},d.refresh=function(t){return this.each(function(){var n,i,a=e(this).data("dropkick"),o=a.$select,r=a.$dk;a.options=o.find("option"),i=C(c,a).find(".dk_options_inner"),r.find(".dk_options_inner").replaceWith(i),a.$original.parent().length||(a.$original=o.find(":selected").first(),a.label=a.$original.text()),n=e('a[data-dk-dropdown-value="'+o.val()+'"]',r),m(n.parent(),r),h(n,r,!t)})},d.destroy=function(){return this.each(function(){var t=e(this).data("dropkick");t.$dk.before(function(){return t.$select.removeData("dropkick")}).remove()})},d.clone=function(t,n,i){var a=[];e.each(this,function(o){var r=e(this).data("dropkick"),d=r.settings,l=r.$select.clone();d.autoWidth&&(d.width=r.$dk.find(".dk_label").width()),n&&l.attr({id:n}),i&&l.attr({name:i}),l.removeData("dropkick"),0==t?a[o]=l[0]:(l.dropkick(d),a[o]=l.data("dropkick").$dk[0])})},d.disable=function(t){return this.each(function(){var n=e(this).data("dropkick"),i=n.$select,a=n.$dk;0==t?(i.removeAttr("disabled"),a.removeAttr("disabled").attr({tabindex:n.tabindex})):(i.attr({disabled:"disabled"}),a.attr({disabled:"disabled",tabindex:-1}))})},e.fn.dropkick=function(e){if(!o){if(d[e])return d[e].apply(this,Array.prototype.slice.call(arguments,1));if("object"==typeof e||!e)return d.init.apply(this,arguments)}},e(function(){e(n).on(a?"mousedown":"click",".dk_options a",function(){var t=e(this),n=t.parent(),i=t.parents(".dk_container").first();return n.hasClass("disabled")||(n.hasClass("dk_option_current")||(h(t,i),m(t.parent(),i)),v(i)),!1}),e(n).on("keydown.dk_nav",function(e){var t;k?t=k:f&&(t=f),t&&w(e,t)}),e(n).on("click",null,function(t){var n,i=e(t.target);if(k&&0===i.closest(".dk_container").length)v(k);else{if(i.is(".dk_toggle, .dk_label"))return n=i.parents(".dk_container").first(),n.hasClass("dk_open")?v(n):(k&&v(k),!n.attr("disabled")&&b(n,t)),!1;i.attr("for")&&e("#dk_container_"+i.attr("for"))[0]&&e("#dk_container_"+i.attr("for")).trigger("focus.dropkick")}});var i="onwheel"in t?"wheel":"onmousewheel"in n?"mousewheel":"MouseScrollEvent"in t?"DOMMouseScroll MozMousePixelScroll":!1;i&&e(n).on(i,".dk_options_inner",function(e){var t=e.originalEvent.wheelDelta||-e.originalEvent.deltaY||-e.originalEvent.detail;return a?(this.scrollTop-=Math.round(t/10),!1):t>0&&this.scrollTop<=0||0>t&&this.scrollTop>=this.scrollHeight-this.offsetHeight?!1:!0})})})(jQuery,window,document); \ No newline at end of file +*/(function(t,e,i){"use strict";var n=navigator.userAgent.match(/MSIE ([0-9]{1,}[\.0-9]{0,})/),o=!!n,a=o&&parseFloat(n[1])<7,d=navigator.userAgent.match(/iPad|iPhone|Android|IEMobile|BlackBerry/i),r={},l=[],s={left:37,up:38,right:39,down:40,enter:13,tab:9,zero:48,z:90,last:221},p=['"].join(""),c='
  • {{ text }}
  • ',u='
  • {{ text }}',k={startSpeed:400,theme:!1,changes:!1,syncReverse:!0,nativeMobile:!0,autoWidth:!0},f=null,h=null,g=function(t,e,i){var n=t.attr("data-dk-dropdown-value"),o=t.text(),a=e.data("dropkick"),d=a.$select;i=i||!1,e.find(".dk_label").text(o?o:" "),i?d.val(n):d.val(n).trigger("change"),!a.settings.change||i||a.settings.syncReverse||a.settings.change.call(d,n,o)},_=function(t){t.removeClass("dk_open dk_open_top"),f=null},v=function(i){if(i.data("dropkick").settings.fixedMove)return"up"==i.data("dropkick").settings.fixedMove?!1:!0;var n=i.find(".dk_toggle"),o=i.find(".dk_options").outerHeight(),a=t(e).height()-n.outerHeight()-n.offset().top+t(e).scrollTop(),d=n.offset().top-t(e).scrollTop();return d>o?a>o:!0},b=function(t,e,i){var n=t.find(".dk_options_inner"),o=e.prevAll("li").outerHeight()*e.prevAll("li").length,a=n.scrollTop(),d=n.height()+n.scrollTop()-e.outerHeight();e.closest(".dk_optgroup",n).length&&(o+=e.closest(".dk_optgroup",n).prevAll("li").outerHeight()*e.closest(".dk_optgroup",n).prevAll("li").length),(i&&"keydown"===i.type||a>o||o>d)&&n.scrollTop(o)},m=function(t,e){var i=v(t),n=i?"dk_open":"dk_open_top dk_open";t.find(".dk_options").css({top:i?t.find(".dk_toggle").outerHeight()-1:"",bottom:i?"":t.find(".dk_toggle").outerHeight()-1}),f=t.addClass(n),b(t,t.find(".dk_option_current"),e)},C=function(t,e,i){e.find(".dk_option_current").removeClass("dk_option_current"),t.addClass("dk_option_current"),b(e,t,i)},x=function(e,i){var n,o,a,d,r,l,p,c=e.keyCode,u=i.data("dropkick"),k=String.fromCharCode(c),f=i.find(".dk_options"),h=i.hasClass("dk_open"),v=f.find("li:not(.disabled)"),b=i.find(".dk_option_current"),x=v.first().hasClass("dk_optgroup")?v.first().find("li:not(.disabled)").first():v.first(),w=v.last().hasClass("dk_optgroup")?v.last().find("li:not(.disabled)").last():v.last();switch(c){case s.enter:h?b.hasClass("disabled")||(g(b.find("a"),i),_(i)):m(i,e),e.preventDefault();break;case s.tab:h&&(b.length&&g(b.find("a"),i),_(i));break;case s.up:h?(o=b.prevAll("li:not(.disabled)").first(),o.hasClass("dk_optgroup")&&(o=o.find("li:not(.disabled)").last()),!o.length&&b.closest(".dk_optgroup").length&&(o=b.closest(".dk_optgroup").prevAll("li:not(.disabled)").first().hasClass("dk_optgroup")?b.closest(".dk_optgroup").prevAll("li:not(.disabled)").first().find("li:not(.disabled)").last():b.closest(".dk_optgroup").prevAll("li:not(.disabled)").first()),o.length?C(o,i,e):C(w,i,e)):m(i,e),e.preventDefault();break;case s.down:h?(n=b.nextAll("li:not(.disabled)").first(),n.hasClass("dk_optgroup")&&(n=n.find("li:not(.disabled)").first()),!n.length&&b.closest(".dk_optgroup").length&&(n=b.closest(".dk_optgroup").nextAll("li:not(.disabled)").first().hasClass("dk_optgroup")?b.closest(".dk_optgroup").nextAll("li:not(.disabled)").first().find("li:not(.disabled)").first():b.closest(".dk_optgroup").nextAll("li:not(.disabled)").first()),n.length?C(n,i,e):C(x,i,e)):m(i,e),e.preventDefault()}if(c>=s.zero&&c<=s.z){for(a=(new Date).getTime(),null===u.finder||void 0===u.finder?(u.finder=k.toUpperCase(),u.timer=a):a>parseInt(u.timer,10)+1e3?(u.finder=k.toUpperCase(),u.timer=a):(u.finder=u.finder+k.toUpperCase(),u.timer=a),d=v.find("a"),r=0,l=d.length;l>r;r++)if(p=t(d[r]),0===p.html().toUpperCase().indexOf(u.finder)&&!p.closest(".dk_optgroup",f).hasClass("disabled")){g(p,i),C(p.parent(),i,e);break}i.data("dropkick",u)}},w=function(e){return t.trim(e).length>0?e:!1},$=function(e,i){var n,o,a,d,r,l=function(e){return c.replace("{{ value }}",e.val()).replace("{{ current }}",w(e.val())===i.value?"dk_option_current":"").replace("{{ disabled }}",void 0!==e.attr("disabled")?"disabled":"").replace("{{ text }}",t.trim(e.html())?t.trim(e.html()):" ")},s=e.replace("{{ id }}",i.id).replace("{{ label }}",i.label).replace("{{ tabindex }}",i.tabindex),p=[];if(i.options&&i.options.length)for(o=0,a=i.options.length;a>o;o++){if(d=t(i.options[o]),d.is("option"))r=0===o&&void 0!==d.attr("selected")&&void 0!==d.attr("disabled")?null:l(d);else if(d.is("optgroup")){if(r=u.replace("{{ text }}",d.attr("label")||"---").replace("{{ disabled }}",void 0!==d.attr("disabled")?" disabled":""),t(i.options[o]).children().length){r+="
      ";for(var k=0,f=t(i.options[o]).children().length;f>k;k++){var h=t(i.options[o]).children().eq(k);r+=l(h)}r+="
    "}r+="
  • "}p[p.length]=r}return n=t(s),n.find(".dk_options_inner").html(p.join("")),n};a||(i.documentElement.className=i.documentElement.className+" dk_fouc"),r.init=function(e){return e=t.extend({},k,e),p=e.dropdownTemplate?e.dropdownTemplate:p,c=e.optionTemplate?e.optionTemplate:c,this.each(function(){var i,n,o=t(this),a=o.find(":selected").first(),r=o.children(),s=o.data("dropkick")||{},c=o.attr("id")||o.attr("name"),u=e.width||o.outerWidth(),k=o.attr("tabindex")||"0",f=!!o.attr("disabled"),g=!1;return s.id?o:(s.settings=e,s.tabindex=k,s.id=c,s.$original=a,s.$select=o,s.value=w(o.val())||w(a.attr("value")),s.label=a.text()?a.text():" ",s.options=r,g=$(p,s),s.settings.autoWidth&&g.find(".dk_toggle").css({width:u+"px"}),f&&g.attr({disabled:"disabled",tabindex:-1}),o.before(g).appendTo(g),g.fadeIn(e.startSpeed),i=e.theme||"default",g.addClass("dk_theme_"+i),s.theme=i,s.$dk=g,o.data("dropkick",s),g.addClass(o.attr("class")),g.data("dropkick",s),l[l.length]=o,g.on("focus.dropkick",function(){h=g.attr("disabled")?null:g.addClass("dk_focus")}).on("blur.dropkick",function(){g.removeClass("dk_focus"),h=null}),d&&s.settings.nativeMobile&&g.addClass("dk_mobile"),s.settings.syncReverse&&o.on("change",function(e){var i=o.val(),n=t('a[data-dk-dropdown-value="'+i+'"]',g),a=n.text();g.find(".dk_label").text(a?a:" "),C(n.parent(),g,e),s.settings.change&&s.settings.change.call(o,i,a)}),n=o.attr("form")?t("#"+o.attr("form").replace(" ",", #")):o.closest("form"),void(n.length&&n.on("reset",function(){o.dropkick("reset")})))})},r.theme=function(e){var i=t(this).data("dropkick"),n=i.$dk,o="dk_theme_"+i.theme;n.removeClass(o).addClass("dk_theme_"+e),i.theme=e},r.reset=function(e){return this.each(function(){var i=t(this).data("dropkick"),n=i.$dk,o=t('a[data-dk-dropdown-value="'+i.$original.attr("value")+'"]',n);i.$original.prop("selected",!0),C(o.parent(),n),g(o,n,!e)})},r.setValue=function(e){return this.each(function(){var i=t(this).data("dropkick").$dk,n=t('.dk_options a[data-dk-dropdown-value="'+e+'"]',i);n.length?g(n,i)|C(n.parent(),i):console.warn("There is no option with this value in "+i.selector)})},r.refresh=function(e){return this.each(function(){var i,n,o=t(this).data("dropkick"),a=o.$select,d=o.$dk;o.options=a.children(),n=$(p,o).find(".dk_options_inner"),d.find(".dk_options_inner").replaceWith(n),o.$original.parent().length||(o.$original=a.find(":selected").first(),o.label=o.$original.text()),i=t('a[data-dk-dropdown-value="'+a.val()+'"]',d),C(i.parent(),d),g(i,d,!e)})},r.destroy=function(){return this.each(function(){var e=t(this).data("dropkick");e.$dk.before(function(){return e.$select.removeData("dropkick")}).remove()})},r.clone=function(e,i,n){var o=[];t.each(this,function(a){var d=t(this).data("dropkick"),r=d.settings,l=d.$select.clone();r.autoWidth&&(r.width=d.$dk.find(".dk_label").width()),i&&l.attr({id:i}),n&&l.attr({name:n}),l.removeData("dropkick"),0==e?o[a]=l[0]:(l.dropkick(r),o[a]=l.data("dropkick").$dk[0])})},r.disable=function(e){return this.each(function(){var i=t(this).data("dropkick"),n=i.$select,o=i.$dk;0==e?(n.removeAttr("disabled"),o.removeAttr("disabled").attr({tabindex:i.tabindex})):(o.hasClass("dk_open")&&_(o),n.attr({disabled:"disabled"}),o.attr({disabled:"disabled",tabindex:-1}))})},t.fn.dropkick=function(t){if(!a){if(r[t])return r[t].apply(this,Array.prototype.slice.call(arguments,1));if("object"==typeof t||!t)return r.init.apply(this,arguments)}},t(function(){t(i).on(o?"mousedown":"click",".dk_options a",function(){var e=t(this),i=e.parent(),n=e.parents(".dk_container").first();return i.hasClass("disabled")||i.closest(".dk_optgroup",n).hasClass("disabled")||(i.hasClass("dk_option_current")||(g(e,n),C(e.parent(),n)),_(n)),!1}),t(i).on("keydown.dk_nav",function(t){var e;f?e=f:h&&(e=h),e&&x(t,e)}),t(i).on("click",null,function(e){var i,n=t(e.target);if(f&&0===n.closest(".dk_container").length)_(f);else{if(n.is(".dk_toggle, .dk_label"))return i=n.parents(".dk_container").first(),i.hasClass("dk_open")?_(i):(f&&_(f),!i.attr("disabled")&&m(i,e)),!1;n.attr("for")&&t("#dk_container_"+n.attr("for"))[0]&&t("#dk_container_"+n.attr("for")).trigger("focus.dropkick")}});var n="onwheel"in e?"wheel":"onmousewheel"in i?"mousewheel":"MouseScrollEvent"in e?"DOMMouseScroll MozMousePixelScroll":!1;n&&t(i).on(n,".dk_options_inner",function(t){var e=t.originalEvent.wheelDelta||-t.originalEvent.deltaY||-t.originalEvent.detail;return o?(this.scrollTop-=Math.round(e/10),!1):e>0&&this.scrollTop<=0||0>e&&this.scrollTop>=this.scrollHeight-this.offsetHeight?!1:!0})})})(jQuery,window,document); \ No newline at end of file diff --git a/jquery.dropkick.js b/jquery.dropkick.js index 998dae0e..8c89b2ce 100644 --- a/jquery.dropkick.js +++ b/jquery.dropkick.js @@ -50,6 +50,8 @@ // HTML template for dropdown options optionTemplate = '
  • {{ text }}
  • ', + optgroupTemplate = '
  • {{ text }}', + // Some nice default values defaults = { @@ -79,7 +81,7 @@ reset = reset || false; - $dk.find('.dk_label').text(label); + $dk.find('.dk_label').text(!!label?label:' '); !reset ? $select.val(value).trigger('change') : $select.val(value); // Let it act like a normal select when needed @@ -117,6 +119,10 @@ maxHeight = wrapper.height() + wrapper.scrollTop() - anchor.outerHeight() ; + if (anchor.closest('.dk_optgroup',wrapper).length) { + height = height + anchor.closest('.dk_optgroup',wrapper).prevAll('li').outerHeight() * anchor.closest('.dk_optgroup',wrapper).prevAll('li').length; + } + if ( (e && e.type === 'keydown') || (height < minHeight || height > maxHeight) ) { wrapper.scrollTop(height); // A more direct approach } @@ -153,8 +159,8 @@ open = $dk.hasClass('dk_open'), lis = options.find('li:not(.disabled)'), current = $dk.find('.dk_option_current'), - first = lis.first(), - last = lis.last(), + first = lis.first().hasClass('dk_optgroup') ? lis.first().find('li:not(.disabled)').first() : lis.first(), + last = lis.last().hasClass('dk_optgroup') ? lis.last().find('li:not(.disabled)').last() : lis.last(), next, prev, now, @@ -185,8 +191,12 @@ break; case keyMap.up: - prev = current.prevAll('li:not(.disabled)').first(); if (open) { + prev = current.prevAll('li:not(.disabled)').first(); + if (prev.hasClass('dk_optgroup')) prev = prev.find('li:not(.disabled)').last(); + if (!prev.length && current.closest('.dk_optgroup').length) { + prev = current.closest('.dk_optgroup').prevAll('li:not(.disabled)').first().hasClass('dk_optgroup') ? current.closest('.dk_optgroup').prevAll('li:not(.disabled)').first().find('li:not(.disabled)').last() : current.closest('.dk_optgroup').prevAll('li:not(.disabled)').first(); + } if (prev.length) { setCurrent(prev, $dk, e); } else { @@ -201,6 +211,10 @@ case keyMap.down: if (open) { next = current.nextAll('li:not(.disabled)').first(); + if (next.hasClass('dk_optgroup')) next = next.find('li:not(.disabled)').first(); + if (!next.length && current.closest('.dk_optgroup').length) { + next = current.closest('.dk_optgroup').nextAll('li:not(.disabled)').first().hasClass('dk_optgroup') ? current.closest('.dk_optgroup').nextAll('li:not(.disabled)').first().find('li:not(.disabled)').first() : current.closest('.dk_optgroup').nextAll('li:not(.disabled)').first(); + } if (next.length) { setCurrent(next, $dk, e); } else { @@ -236,7 +250,7 @@ list = lis.find('a'); for(i = 0, l = list.length; i < l; i++){ $a = $(list[i]); - if ($a.html().toUpperCase().indexOf(data.finder) === 0) { + if ($a.html().toUpperCase().indexOf(data.finder) === 0 && !$a.closest('.dk_optgroup',options).hasClass('disabled')) { updateFields($a, $dk); setCurrent($a.parent(), $dk, e); break; @@ -254,6 +268,13 @@ build = function (tpl, view) { var // Template for the dropdown + buildOption = function($el) { + return optionTemplate.replace('{{ value }}', $el.val()) + .replace('{{ current }}', (notBlank($el.val()) === view.value) ? 'dk_option_current' : '') + .replace('{{ disabled }}', ($el.attr('disabled') !== undefined) ? 'disabled' : '') + .replace('{{ text }}', !!$.trim($el.html()) ? $.trim($el.html()) : ' ' ) + ; + }, template = tpl.replace('{{ id }}', view.id).replace('{{ label }}', view.label).replace('{{ tabindex }}', view.tabindex), // Holder of the dropdowns options options = [], @@ -267,15 +288,22 @@ if (view.options && view.options.length) { for (i = 0, l = view.options.length; i < l; i++) { $option = $(view.options[i]); - - (i === 0 && $option.attr('selected') !== undefined && $option.attr('disabled') !== undefined)? - oTemplate = null - : - oTemplate = optionTemplate.replace('{{ value }}', $option.val()) - .replace('{{ current }}', (notBlank($option.val()) === view.value) ? 'dk_option_current' : '') - .replace('{{ disabled }}', ($option.attr('disabled') !== undefined) ? 'disabled' : '') - .replace('{{ text }}', $.trim($option.html())) - ; + + if ($option.is('option')) { + oTemplate = (i === 0 && $option.attr('selected') !== undefined && $option.attr('disabled') !== undefined) ? null : buildOption($option); + } else if ($option.is('optgroup')) { + oTemplate = optgroupTemplate.replace('{{ text }}', $option.attr('label') || '---').replace('{{ disabled }}', ($option.attr('disabled') !== undefined) ? ' disabled' : ''); + if ($(view.options[i]).children().length) { + oTemplate += '
      '; + for (var j = 0, m = $(view.options[i]).children().length; j < m; j++ ) { + var $optoption = $(view.options[i]).children().eq(j); + oTemplate += buildOption($optoption); + } + oTemplate += '
    '; + } + oTemplate += '
  • ' + + } options[options.length] = oTemplate; } @@ -308,7 +336,7 @@ $original = $select.find(':selected').first(), // Save all of the