1+ /**
2+ * jQuery plugin to handle width overflow of bootstrap tabs in a manner similar to tab handling on Android.
3+ *
4+ * @version v1.1.2
5+ * @license https://github.com/strapless/layout/LICENSE
6+ * @author Aaron M Jones <am@jonesiscoding.com>
7+ */
8+ ( function ( $ ) {
9+
10+ $ . tabScroll = function ( element , options ) {
11+
12+ var defaults = {
13+ cls : {
14+ 'toggle' : 'dropdown-toggle' ,
15+ 'wrapper' : 'dropdown' ,
16+ 'dropdown' : 'dropdown-menu' ,
17+ 'open' : 'open' ,
18+ 'marker' : 'overflow-item'
19+ }
20+ } ;
21+
22+ var plugin = this ;
23+
24+ /**
25+ * @type object
26+ */
27+ plugin . settings = { } ;
28+
29+ var $el = $ ( element ) ;
30+
31+ plugin . init = function ( ) {
32+
33+ plugin . settings = $ . extend ( { } , defaults , options ) ;
34+
35+ $ ( window ) . afterwards ( 'resize' , function ( ) {
36+ plugin . toggleMarker ( plugin . hasOverflow ( ) ) ;
37+ } ) ;
38+
39+ $ ( document ) . on ( 'show.bs.dropdown' , '[data-overflow="true"]' , function ( e ) {
40+ var $dropdown = $ ( e . target ) . find ( plugin . settings . cls . dropdown ) ;
41+ var $trigger = $dropdown . parent ( '.' + plugin . settings . cls . wrapper ) . find ( '.' + plugin . settings . cls . toggle ) ;
42+ var top = $trigger . offset ( ) . top + $trigger . outerHeight ( ) ;
43+ var left = $trigger . offset ( ) . left ;
44+ $dropdown . appendTo ( 'body' ) . css ( { left : left + 'px' , top : top + 'px' , 'max-height' : 'calc(90vh - ' + top + 'px)' , 'overflow-y' : 'scroll' } ) ;
45+ $ ( 'body' ) . addClass ( plugin . settings . cls . open ) ;
46+ $ ( this ) . on ( 'hidden.bs.dropdown' , function ( ) {
47+ $dropdown . appendTo ( e . target ) . css ( { } ) ;
48+ $ ( 'body' ) . removeClass ( plugin . settings . cls . open ) ;
49+ } )
50+ } ) ;
51+
52+ if ( ! $ ( document ) . hasClass ( '.touch' ) ) {
53+ $el . on ( 'click' , '.' + plugin . settings . cls . marker , function ( e ) { plugin . onClick ( e ) ; } ) ;
54+ }
55+
56+ plugin . toggleMarker ( plugin . hasOverflow ( ) ) ;
57+ } ;
58+
59+ /**
60+ * @returns {boolean }
61+ */
62+ plugin . hasOverflow = function ( ) {
63+ var width = $el . innerWidth ( ) ;
64+ var childWidth = 0 ;
65+ $el . children ( 'li' ) . each ( function ( ) {
66+ childWidth = childWidth + $ ( this ) . innerWidth ( ) ;
67+ } ) ;
68+
69+ return ( width && width < childWidth ) ;
70+ } ;
71+
72+ /**
73+ * @param status
74+ */
75+ plugin . toggleMarker = function ( status ) {
76+ var sel = '.' + plugin . settings . cls . marker ;
77+ var $marker = $el . find ( sel ) ;
78+ var hasMarker = ( 0 === $marker . length ) ;
79+ if ( status !== false ) {
80+ if ( hasMarker ) {
81+ $marker = $ ( '<span></span>' ) ;
82+ $marker . addClass ( plugin . settings . cls . marker ) . appendTo ( $el ) ;
83+ $el . on ( 'scroll' , function ( ) {
84+ var left = $el . innerWidth ( ) + $el . scrollLeft ( ) ;
85+ $marker . css ( 'left' , left ) ;
86+ } ) ;
87+ } else {
88+ $marker . show ( ) ;
89+ }
90+ } else {
91+ if ( hasMarker ) {
92+ $marker . hide ( ) ;
93+ }
94+ }
95+ } ;
96+
97+ /**
98+ * @param e The click event.
99+ */
100+ plugin . onClick = function ( e ) {
101+ e . preventDefault ( ) ;
102+ var leftPos = $el . scrollLeft ( ) ;
103+ $el . animate ( { scrollLeft : leftPos + 200 } , 800 ) ;
104+ } ;
105+
106+ plugin . init ( ) ;
107+
108+ } ;
109+
110+ /**
111+ * @param options
112+ * @returns {* }
113+ */
114+ $ . fn . tabScroll = function ( options ) {
115+ return this . each ( function ( ) {
116+ if ( undefined === $ ( this ) . data ( 'tabScroll' ) ) {
117+ var plugin = new $ . tabScroll ( this , options ) ;
118+ $ ( this ) . data ( 'tabScroll' , plugin ) ;
119+ }
120+ } ) ;
121+ } ;
122+ } ) ( jQuery ) ;
0 commit comments