1+ /*!
2+ * SmartMenus jQuery Plugin Bootstrap Addon - v0.3.1 - November 1, 2016
3+ * http://www.smartmenus.org/
4+ *
5+ * Copyright Vasil Dinkov, Vadikom Web Ltd.
6+ * http://vadikom.com
7+ *
8+ * Licensed MIT
9+ */
10+
11+ ( function ( factory ) {
12+ if ( typeof define === 'function' && define . amd ) {
13+ // AMD
14+ define ( [ 'jquery' , 'jquery.smartmenus' ] , factory ) ;
15+ } else if ( typeof module === 'object' && typeof module . exports === 'object' ) {
16+ // CommonJS
17+ module . exports = factory ( require ( 'jquery' ) ) ;
18+ } else {
19+ // Global jQuery
20+ factory ( jQuery ) ;
21+ }
22+ } ( function ( $ ) {
23+
24+ $ . extend ( $ . SmartMenus . Bootstrap = { } , {
25+ keydownFix : false ,
26+ init : function ( ) {
27+ // init all navbars that don't have the "data-sm-skip" attribute set
28+ var $navbars = $ ( 'ul.navbar-nav:not([data-sm-skip])' ) ;
29+ $navbars . each ( function ( ) {
30+ var $this = $ ( this ) ,
31+ obj = $this . data ( 'smartmenus' ) ;
32+ // if this navbar is not initialized
33+ if ( ! obj ) {
34+ $this . smartmenus ( {
35+
36+ // these are some good default options that should work for all
37+ // you can, of course, tweak these as you like
38+ subMenusSubOffsetX : 2 ,
39+ subMenusSubOffsetY : - 6 ,
40+ subIndicators : false ,
41+ collapsibleShowFunction : null ,
42+ collapsibleHideFunction : null ,
43+ rightToLeftSubMenus : $this . hasClass ( 'navbar-right' ) ,
44+ bottomToTopSubMenus : $this . closest ( '.navbar' ) . hasClass ( 'navbar-fixed-bottom' )
45+ } )
46+ . bind ( {
47+ // set/unset proper Bootstrap classes for some menu elements
48+ 'show.smapi' : function ( e , menu ) {
49+ var $menu = $ ( menu ) ,
50+ $scrollArrows = $menu . dataSM ( 'scroll-arrows' ) ;
51+ if ( $scrollArrows ) {
52+ // they inherit border-color from body, so we can use its background-color too
53+ $scrollArrows . css ( 'background-color' , $ ( document . body ) . css ( 'background-color' ) ) ;
54+ }
55+ $menu . parent ( ) . addClass ( 'open' ) ;
56+ } ,
57+ 'hide.smapi' : function ( e , menu ) {
58+ $ ( menu ) . parent ( ) . removeClass ( 'open' ) ;
59+ }
60+ } ) ;
61+
62+ function onInit ( ) {
63+ // set Bootstrap's "active" class to SmartMenus "current" items (should someone decide to enable markCurrentItem: true)
64+ $this . find ( 'a.current' ) . parent ( ) . addClass ( 'active' ) ;
65+ // remove any Bootstrap required attributes that might cause conflicting issues with the SmartMenus script
66+ $this . find ( 'a.has-submenu' ) . each ( function ( ) {
67+ var $this = $ ( this ) ;
68+ if ( $this . is ( '[data-toggle="dropdown"]' ) ) {
69+ $this . dataSM ( 'bs-data-toggle-dropdown' , true ) . removeAttr ( 'data-toggle' ) ;
70+ }
71+ if ( $this . is ( '[role="button"]' ) ) {
72+ $this . dataSM ( 'bs-role-button' , true ) . removeAttr ( 'role' ) ;
73+ }
74+ } ) ;
75+ }
76+
77+ onInit ( ) ;
78+
79+ function onBeforeDestroy ( ) {
80+ $this . find ( 'a.current' ) . parent ( ) . removeClass ( 'active' ) ;
81+ $this . find ( 'a.has-submenu' ) . each ( function ( ) {
82+ var $this = $ ( this ) ;
83+ if ( $this . dataSM ( 'bs-data-toggle-dropdown' ) ) {
84+ $this . attr ( 'data-toggle' , 'dropdown' ) . removeDataSM ( 'bs-data-toggle-dropdown' ) ;
85+ }
86+ if ( $this . dataSM ( 'bs-role-button' ) ) {
87+ $this . attr ( 'role' , 'button' ) . removeDataSM ( 'bs-role-button' ) ;
88+ }
89+ } ) ;
90+ }
91+
92+ obj = $this . data ( 'smartmenus' ) ;
93+
94+ // custom "isCollapsible" method for Bootstrap
95+ obj . isCollapsible = function ( ) {
96+ return ! / ^ ( l e f t | r i g h t ) $ / . test ( this . $firstLink . parent ( ) . css ( 'float' ) ) ;
97+ } ;
98+
99+ // custom "refresh" method for Bootstrap
100+ obj . refresh = function ( ) {
101+ $ . SmartMenus . prototype . refresh . call ( this ) ;
102+ onInit ( ) ;
103+ // update collapsible detection
104+ detectCollapsible ( true ) ;
105+ } ;
106+
107+ // custom "destroy" method for Bootstrap
108+ obj . destroy = function ( refresh ) {
109+ onBeforeDestroy ( ) ;
110+ $ . SmartMenus . prototype . destroy . call ( this , refresh ) ;
111+ } ;
112+
113+ // keep Bootstrap's default behavior for parent items when the "data-sm-skip-collapsible-behavior" attribute is set to the ul.navbar-nav
114+ // i.e. use the whole item area just as a sub menu toggle and don't customize the carets
115+ if ( $this . is ( '[data-sm-skip-collapsible-behavior]' ) ) {
116+ $this . bind ( {
117+ // click the parent item to toggle the sub menus (and reset deeper levels and other branches on click)
118+ 'click.smapi' : function ( e , item ) {
119+ if ( obj . isCollapsible ( ) ) {
120+ var $item = $ ( item ) ,
121+ $sub = $item . parent ( ) . dataSM ( 'sub' ) ;
122+ if ( $sub && $sub . dataSM ( 'shown-before' ) && $sub . is ( ':visible' ) ) {
123+ obj . itemActivate ( $item ) ;
124+ obj . menuHide ( $sub ) ;
125+ return false ;
126+ }
127+ }
128+ }
129+ } ) ;
130+ }
131+
132+ // onresize detect when the navbar becomes collapsible and add it the "sm-collapsible" class
133+ var winW ;
134+ function detectCollapsible ( force ) {
135+ var newW = obj . getViewportWidth ( ) ;
136+ if ( newW != winW || force ) {
137+ var $carets = $this . find ( '.caret' ) ;
138+ if ( obj . isCollapsible ( ) ) {
139+ $this . addClass ( 'sm-collapsible' ) ;
140+ // set "navbar-toggle" class to carets (so they look like a button) if the "data-sm-skip-collapsible-behavior" attribute is not set to the ul.navbar-nav
141+ if ( ! $this . is ( '[data-sm-skip-collapsible-behavior]' ) ) {
142+ $carets . addClass ( 'navbar-toggle sub-arrow' ) ;
143+ }
144+ } else {
145+ $this . removeClass ( 'sm-collapsible' ) ;
146+ if ( ! $this . is ( '[data-sm-skip-collapsible-behavior]' ) ) {
147+ $carets . removeClass ( 'navbar-toggle sub-arrow' ) ;
148+ }
149+ }
150+ winW = newW ;
151+ }
152+ }
153+ detectCollapsible ( ) ;
154+ $ ( window ) . bind ( 'resize.smartmenus' + obj . rootId , detectCollapsible ) ;
155+ }
156+ } ) ;
157+ // keydown fix for Bootstrap 3.3.5+ conflict
158+ if ( $navbars . length && ! $ . SmartMenus . Bootstrap . keydownFix ) {
159+ // unhook BS keydown handler for all dropdowns
160+ $ ( document ) . off ( 'keydown.bs.dropdown.data-api' , '.dropdown-menu' ) ;
161+ // restore BS keydown handler for dropdowns that are not inside SmartMenus navbars
162+ if ( $ . fn . dropdown && $ . fn . dropdown . Constructor ) {
163+ $ ( document ) . on ( 'keydown.bs.dropdown.data-api' , '.dropdown-menu:not([id^="sm-"])' , $ . fn . dropdown . Constructor . prototype . keydown ) ;
164+ }
165+ $ . SmartMenus . Bootstrap . keydownFix = true ;
166+ }
167+ }
168+ } ) ;
169+
170+ // init ondomready
171+ $ ( $ . SmartMenus . Bootstrap . init ) ;
172+
173+ return $ ;
174+ } ) ) ;
0 commit comments