├── .gitignore
├── LICENSE
├── README.md
├── _config.yml
├── bower.json
├── dist
├── jquery.scrolling-tabs.css
├── jquery.scrolling-tabs.js
├── jquery.scrolling-tabs.min.css
└── jquery.scrolling-tabs.min.js
├── gulpfile.js
├── package.json
├── run
├── data-driven-mult.html
├── data-driven-rtl.html
├── data-driven.html
├── index.html
├── markup-only-mult.html
├── markup-only-rtl.html
├── markup-only-svg.html
├── markup-only-with-click-target.html
└── markup-only.html
├── src
├── js
│ ├── _main.js
│ ├── api.js
│ ├── buildTabs.js
│ ├── constants.js
│ ├── elementsHandler.js
│ ├── eventHandlers.js
│ ├── header.js
│ ├── scrollMovement.js
│ ├── scrollingTabsControl.js
│ ├── smartresize.js
│ ├── tabListeners.js
│ └── usage.js
└── scss
│ └── jquery.scrolling-tabs.scss
└── st-screenshot1.png
/.gitignore:
--------------------------------------------------------------------------------
1 | .jshintrc
2 | .project
3 | .sass-cache
4 | *.rb
5 | .DS_Store
6 | node_modules
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Mike Jacobson
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | jquery-bootstrap-scrolling-tabs
2 | ================================
3 |
4 | jQuery plugin for making Bootstrap 3 Tabs scroll horizontally rather than wrap.
5 |
6 | Here's what they look like:
7 |
8 | 
9 |
10 |
11 | And here are plunks showing them working with:
12 |
13 | * HTML-defined Tabs
14 | * Data-driven Tabs
15 |
16 | Or if you prefer CodePen:
17 |
18 | * HTML-defined Tabs
19 | * Data-driven Tabs
20 |
21 |
22 |
23 | Use Cases
24 | ---------
25 | * [Use Case #1: Wrap HTML-defined Tabs](#uc1)
26 | * [Use Case #2: Create Data-driven Tabs](#uc2)
27 |
28 |
29 |
30 | Optional Features
31 | -----------------
32 | There are also optional features available:
33 | * [Reverse Scroll](#reverseScroll)
34 | * [Force Scroll to Tab Edge](#scrollToTabEdge)
35 | * [Disable Scroll Arrows on Fully Scrolled](#disableScrollArrowsOnFullyScrolled)
36 | * [Handle Delayed Scrollbar](#handleDelayedScrollbar)
37 | * [Width Multiplier](#widthMultiplier)
38 | * [Tab Click Handler](#tabClickHandler)
39 | * [Custom Scroll Arrow classes](#cssClassArrows)
40 | * [Custom Scroll Arrow content](#customArrowsContent)
41 | * [Custom Tab LI content](#customTabLiContent)
42 | * [Tab LI and Anchor Post-Processors](#postProcessors)
43 | * [Enable Horizontal Swiping for Touch Screens](#enableSwiping)
44 | * [Enable Right-to-Left Language Support](#enableRtlSupport)
45 |
46 |
47 | Usage
48 | -----
49 | 1. Download it or install it using bower: `bower install jquery-bootstrap-scrolling-tabs` or npm: `npm install jquery-bootstrap-scrolling-tabs`
50 | 2. Include `dist/jquery.scrolling-tabs.min.css` (or `dist/jquery.scrolling-tabs.css`) on your page *after* Bootstrap's CSS
51 | 3. Include `dist/jquery.scrolling-tabs.min.js` (or `dist/jquery.scrolling-tabs.js`) on your page (make sure that jQuery is included before it, of course)
52 |
53 |
54 | Breaking Change for v2.0.0: Only affects swiping for touch screens
55 | --
56 | Swiping functionality is now handled via code rather than the browser's built-in scrolling with a scrollbar due to conflicts that occurred if, on a touch screen, you performed a combination of swiping and pressing the scroll arrows.
57 | If you enabled swiping by passing in option `enableSwiping: true`, this change should not break anything, and should, in fact, fix a problem. However, if instead you enabled swiping by manually adding CSS class `scrtabs-allow-scrollbar` to a parent element of the scrolling tabs, that will no longer trigger a horizontal scrollbar for the tabs, so swiping will not be active. To enable swiping, you will need to pass in option `enableSwiping: true`.
58 |
59 | Breaking Change for v1.0.0
60 | --
61 | * The plugin files, `jquery.scrolling-tabs.js` and `jquery.scrolling-tabs.css`, have been moved from the project root into `/dist/`.
62 |
63 | Possible Breaking Change for v1.0.0
64 | --
65 | * The jQuery dependency has been bumped from `<3.0.0` to `<4.0.0`.
66 |
67 | Overview
68 | --------
69 | If you're using Bootstrap Tabs (`nav-tabs`) and you don't want them to wrap if the page is too narrow to accommodate them all in one row, you can use this plugin to keep them in a row that scrolls horizontally without a scrollbar.
70 |
71 | It adjusts itself on window resize (debounced to prevent resize event wackiness), so if the window is widened enough to accommodate all tabs, scrolling will deactivate and the scroll arrows will disappear. (And, of course, vice versa if the window is narrowed.)
72 |
73 | Note: Similar to [Bootstrap tabs](https://getbootstrap.com/docs/3.3/javascript/#tabs), nested tabs are not supported.
74 |
75 | Use Cases
76 | ---------
77 | #### Use Case #1: HTML-defined Tabs
78 |
79 | If your `nav-tabs` markup looks like this:
80 | ```html
81 |
82 |
98 | ```
99 |
100 | you can wrap the tabs in the scroller like this:
101 | ```javascript
102 | $('.nav-tabs').scrollingTabs();
103 | ```
104 |
105 |
106 | ##### Bootstrap 4 Support
107 |
108 | If you're using Bootstrap 4, you need to pass in option `bootstrapVersion: 4` (the default is `3`):
109 | ```javascript
110 | $('.nav-tabs').scrollingTabs({
111 | bootstrapVersion: 4
112 | });
113 | ```
114 | Bootstrap 4 handles some things differently than 3 (e.g., the `active` class gets applied to the tab's `li > a` element rather than the `li` itself)
115 |
116 | ##### reverseScroll Option
117 |
118 | You can also pass in the `reverseScroll` option:
119 | ```javascript
120 | $('.nav-tabs').scrollingTabs({
121 | reverseScroll: true
122 | });
123 | ```
124 | This will reverse the direction the tabs slide when you click a scroll arrow. More details [here](#reverseScroll).
125 |
126 |
127 | ##### scrollToTabEdge Option
128 |
129 | You can also pass in the `scrollToTabEdge` option:
130 | ```javascript
131 | $('.nav-tabs').scrollingTabs({
132 | scrollToTabEdge: true
133 | });
134 | ```
135 | This will force the scrolling to always end with a tab edge aligned with the left scroll arrow. More details [here](#scrollToTabEdge).
136 |
137 |
138 | ##### disableScrollArrowsOnFullyScrolled Option
139 |
140 | You can also pass in the `disableScrollArrowsOnFullyScrolled` option:
141 | ```javascript
142 | $('.nav-tabs').scrollingTabs({
143 | disableScrollArrowsOnFullyScrolled: true
144 | });
145 | ```
146 | If you're using the default scroll setting, this will cause the left scroll arrow to disable when the tabs are scrolled fully left (on page load, for example), and the right scroll arrow to disable when the tabs are scrolled fully right.
147 |
148 | If you have the `reverseScroll` option set to `true`, the opposite arrows will disable.
149 |
150 |
151 | ##### widthMultiplier Option
152 |
153 | You can also pass in the `widthMultiplier` option:
154 | ```javascript
155 | $('.nav-tabs').scrollingTabs({
156 | widthMultiplier: 0.5
157 | });
158 | ```
159 | Pass in a value less than 1 if you want the tabs container to be less than the full width of its parent element. For example, if you want the tabs container to be half the width of its parent, pass in `0.5`.
160 |
161 |
162 | ##### tabClickHandler Option
163 |
164 | You can also use the `tabClickHandler` option to pass in a callback function to execute any time a tab is clicked:
165 | ```javascript
166 | $('.nav-tabs').scrollingTabs({
167 | tabClickHandler: function (e) {
168 | var clickedTabElement = this;
169 | }
170 | });
171 | ```
172 | The callback function is simply passed as the event handler to jQuery's .on(), so the function will receive the jQuery event as an argument, and 'this' inside the function will be the clicked tab's anchor element.
173 |
174 |
175 |
176 | ##### Preventing Flash of Unwrapped Tabs
177 |
178 | To prevent a flash of the tabs on page load/refresh before they get wrapped
179 | inside the scroller, you can hide your `.nav-tabs` and `.tab-content` with
180 | some CSS (`display: none`).
181 |
182 | The plugin will automatically unhide the `.nav-tabs` when they're ready,
183 | and you can hook into the [`ready.scrtabs` event](#events) (which gets fired when
184 | the tabs are ready) to unhide your `.tab-content`:
185 |
186 | ```javascript
187 | $('.nav-tabs')
188 | .scrollingTabs()
189 | .on('ready.scrtabs', function() {
190 | $('.tab-content').show();
191 | });
192 | ```
193 |
194 |
195 |
196 | ##### Forcing a Refresh
197 |
198 | The scrolling container should automatically refresh itself on window resize, but to manually force a refresh you can call the plugin's `refresh` method:
199 | ```javascript
200 | $('.nav-tabs').scrollingTabs('refresh');
201 | ```
202 |
203 | ##### Forcing a Scroll to the Active Tab
204 |
205 | On window resize, the scrolling container should automatically scroll to the active tab if it's offscreen, but you can also programmatically force a scroll to the active tab any time (if, for example, you're programmatically setting the active tab) by calling the plugin's `scrollToActiveTab` method:
206 | ```javascript
207 | $('.nav-tabs').scrollingTabs('scrollToActiveTab');
208 | ```
209 |
210 |
211 | #### Use Case #2: Data-driven Tabs
212 |
213 | If your tabs are data-driven rather than defined in your markup, you just need to pass your tabs array to the plugin and it will generate the tab elements for you.
214 |
215 | So your tabs data should look something like this (note that the tab titles can contain HTML):
216 | ```javascript
217 | var myTabs = [
218 | { paneId: 'tab01', title: 'Tab 1 of 12', content: 'Tab Number 1 Content', active: true, disabled: false },
219 | { paneId: 'tab02', title: 'Tab 2 of 12', content: 'Tab Number 2 Content', active: false, disabled: false },
220 | { paneId: 'tab03', title: 'Tab 3 of 12', content: 'Tab Number 3 Content', active: false, disabled: false },
221 | { paneId: 'tab04', title: 'Tab 4 of 12', content: 'Tab Number 4 Content', active: false, disabled: false },
222 | { paneId: 'tab05', title: 'Tab 5 of 12', content: 'Tab Number 5 Content', active: false, disabled: false }
223 | ];
224 |
225 | ```
226 |
227 | You would then need a target element to append the tabs and panes to, like this:
228 |
229 | ```html
230 |
231 |
232 | ```
233 |
234 |
235 | Then just call the plugin on that element, passing a settings object with a `tabs` property pointing to your tabs array:
236 |
237 | ```javascript
238 | $('#tabs-inside-here').scrollingTabs({
239 | tabs: myTabs
240 | });
241 |
242 | ```
243 |
244 | ##### Required Tab Data Properties
245 |
246 | Each tab object in the array must have a property for
247 | * the tab title (text or HTML)
248 | * the ID of its target pane (text)
249 | * its active state (bool)
250 |
251 | Optionally, it can also have a boolean for its `disabled` state.
252 |
253 |
254 | ##### 'Content' Property for Tab Panes
255 |
256 | If you want the plugin to generate the tab panes also, include a `content` property on the tab objects.
257 |
258 | If your tab objects have a `content` property but you *don't* want the plugin to generate the panes, pass in plugin option `ignoreTabPanes: true` when calling the plugin.
259 |
260 | ```javascript
261 | $('#tabs-inside-here').scrollingTabs({
262 | tabs: myTabs,
263 | ignoreTabPanes: true
264 | });
265 |
266 | ```
267 |
268 | ##### Custom Tab Data Property Names
269 |
270 | By default, the plugin assumes those properties will be named `title`, `paneId`, `active`, `disabled`, and `content`, but if you want to use different property names, you can pass your property names in as properties on the settings object:
271 |
272 | ```javascript
273 | $('#tabs-inside-here').scrollingTabs({
274 | tabs: myTabs, // required,
275 | propTitle: 'myTitle', // required if not 'title'
276 | propPaneId: 'myPaneId', // required if not 'paneId'
277 | propActive: 'myActive', // required if not 'active'
278 | propDisabled: 'myDisabled', // required if not 'disabled'
279 | propContent: 'myContent' // required if not 'content'
280 | });
281 | ```javascript
282 |
283 |
284 |
285 | So, for example, if your tab objects used the property name `label` for their titles instead of `title`, you would need to pass property `propTitle: 'label'` in your settings object.
286 |
287 | ```javascript
288 | $('#tabs-inside-here').scrollingTabs({
289 | tabs: myTabs,
290 | propTitle: 'label'
291 | });
292 |
293 | ```
294 |
295 | ##### scrollToTabEdge Option
296 |
297 | And just like in Use Case #1, you can also pass in the `scrollToTabEdge` option if you want to force the scrolling to always end with a tab edge aligned with the left scroll arrow:
298 |
299 | ```javascript
300 | $('#tabs-inside-here').scrollingTabs({
301 | tabs: myTabs,
302 | scrollToTabEdge: true
303 | });
304 | ```
305 |
306 | You can also pass in the `disableScrollArrowsOnFullyScrolled` option if you want the scroll arrow to disable when the tabs are fully scrolled in that direction:
307 |
308 | ```javascript
309 | $('#tabs-inside-here').scrollingTabs({
310 | tabs: myTabs,
311 | disableScrollArrowsOnFullyScrolled: true
312 | });
313 | ```
314 |
315 |
316 | ##### Refreshing after Tab Data Change
317 |
318 | On `tabs` data change, just call the plugin's `refresh` method to refresh the tabs on the page:
319 | ```javascript
320 | $('#tabs-inside-here').scrollingTabs('refresh');
321 | ```
322 |
323 |
324 | ##### forceActiveTab Option
325 |
326 | On `tabs` data change, if you want the active tab to be set based on the updated tabs data (i.e., you want to override the current active tab setting selected by the user), for example, if you added a new tab and you want it to be the active tab, pass the `forceActiveTab` flag on refresh:
327 | ```javascript
328 | $('#tabs-inside-here').scrollingTabs('refresh', {
329 | forceActiveTab: true
330 | });
331 | ```
332 |
333 | #### Reverse Scroll
334 |
335 | By default, on page load, if there are tabs hidden off the right side of the page, you would click the right scroll arrow to slide those tabs into view (and vice versa for the left scroll arrow, of course, if there are tabs hidden off the left side of the page).
336 |
337 | You can reverse the direction the tabs slide when an arrow is clicked by passing in option `reverseScroll: true`:
338 |
339 | ```javascript
340 | $('#tabs-inside-here').scrollingTabs({
341 | tabs: myTabs,
342 | reverseScroll: true
343 | });
344 | ```
345 |
346 | This might be the more intuitive behavior for mobile devices.
347 |
348 |
349 | #### Force Scroll to Tab Edge
350 |
351 | If you want to ensure the scrolling always ends with a tab edge aligned with the left scroll arrow so there won't be a partially hidden tab, pass in option `scrollToTabEdge: true`:
352 |
353 | ```javascript
354 | $('#tabs-inside-here').scrollingTabs({
355 | tabs: myTabs,
356 | scrollToTabEdge: true
357 | });
358 | ```
359 |
360 | There's no way to guarantee the left *and* right edges will be full tabs because that's dependent on the the width of the tabs and the window. So this just makes sure the left side will be a full tab.
361 |
362 |
363 | #### Disable Scroll Arrows on Fully Scrolled
364 |
365 | If you want the left scroll arrow to disable when the tabs are scrolled fully left (the way they would be on page load, for example), and the right scroll arrow to disable when the tabs are scrolled fully right, pass in option `disableScrollArrowsOnFullyScrolled: true`:
366 |
367 | ```javascript
368 | $('#tabs-inside-here').scrollingTabs({
369 | tabs: myTabs,
370 | disableScrollArrowsOnFullyScrolled: true
371 | });
372 | ```
373 |
374 | Note that if you have the `reverseScroll` option set to `true`, the opposite arrows will disable.
375 |
376 |
377 | #### Handle Delayed Scrollbar
378 |
379 | If you experience a situation where the right scroll arrow wraps to the next line due to a vertical scrollbar coming into existence on the page *after* the plugin already calculated its width without a scrollbar present, pass in option `handleDelayedScrollbar: true`:
380 |
381 | ```javascript
382 | $('.nav-tabs').scrollingTabs({
383 | handleDelayedScrollbar: true
384 | });
385 | ```
386 |
387 | This would occur if, for example, the bulk of the page's content loaded after a delay, and only then did a vertical scrollbar become necessary.
388 |
389 | It would also occur if a vertical scrollbar only appeared on selection of a particular tab that had more content than the default tab.
390 |
391 | This is not enabled by default because, since a window resize event is not triggered by a vertical scrollbar appearing, it requires adding an iframe to the page that listens for resize events because a scrollbar appearing in the parent window *does* trigger a resize event in the iframe, which then dispatches a resize event to the parent, triggering the plugin to recalculate its width.
392 |
393 |
394 | #### Width Multiplier
395 |
396 | If you want the tabs container to be less than the full width of its parent element, pass in a `widthMultiplier` value that's less than 1. For example, if you want the tabs container to be half the width of its parent, pass in option `widthMultiplier: 0.5`:
397 |
398 | ```javascript
399 | $('#tabs-inside-here').scrollingTabs({
400 | tabs: myTabs,
401 | widthMultiplier: 0.5
402 | });
403 | ```
404 |
405 | #### Tab Click Handler
406 |
407 | You can pass in a callback function that executes any time a tab is clicked using the `tabClickHandler` option.
408 | The callback function is simply passed as the event handler to jQuery's .on(), so the function will receive the jQuery event as an argument, and 'this' inside the function will be the clicked tab's anchor element.
409 |
410 | ```javascript
411 | $('#tabs-inside-here').scrollingTabs({
412 | tabs: myTabs,
413 | tabClickHandler: function (e) {
414 | var clickedTabElement = this;
415 | }
416 | });
417 | ```
418 |
419 | #### Custom Scroll Arrow classes
420 |
421 | You can pass in custom values for the class attributes for the left- and right scroll arrows using options `cssClassLeftArrow` and `cssClassRightArrow`.
422 |
423 | The defaults are `glyphicon glyphicon-chevron-left` and `glyphicon glyphicon-chevron-right`.
424 |
425 | Using different icons might require you to add custom styling to the arrows to position the icons correctly; the arrows can be targeted with these selectors:
426 |
427 | `.scrtabs-tab-scroll-arrow`
428 |
429 | `.scrtabs-tab-scroll-arrow-left`
430 |
431 | `.scrtabs-tab-scroll-arrow-right`
432 |
433 |
434 | ```javascript
435 | $('#tabs-inside-here').scrollingTabs({
436 | tabs: myTabs,
437 | cssClassLeftArrow: 'fa fa-chevron-left',
438 | cssClassRightArrow: 'fa fa-chevron-right'
439 | });
440 | ```
441 |
442 | #### Custom Scroll Arrow content
443 |
444 | You can pass in custom values for the left- and right scroll arrow HTML using options `leftArrowContent` and `rightArrowContent`. This will override any custom `cssClassLeftArrow` and `cssClassRightArrow` settings.
445 |
446 | For example, if you wanted to use svg icons, you could set them like so:
447 |
448 | ```javascript
449 | $('#tabs-inside-here').scrollingTabs({
450 | tabs: myTabs,
451 | leftArrowContent: [
452 | '
'
464 | ].join('')
465 | });
466 | ```
467 |
468 | You would then need to add some CSS to make them work correctly if you don't give them the default `scrtabs-tab-scroll-arrow` classes. This plunk shows it working with svg icons:
469 | http://plnkr.co/edit/2MdZCAnLyeU40shxaol3?p=preview
470 |
471 | When using this option, you can also mark a child element within the arrow content as the click target if you don't want the entire content to be clickable. You do that my adding the CSS class `scrtabs-click-target` to the element that should be clickable, like so:
472 |
473 | ```javascript
474 | $('#tabs-inside-here').scrollingTabs({
475 | tabs: myTabs,
476 | leftArrowContent: [
477 | '
28 | *
29 | *
30 | * JavaScript:
31 | *
32 | * $('.nav-tabs').scrollingTabs();
33 | *
34 | *
35 | * Use Case #2: Data-driven tabs
36 | * -----------------------------
37 | * Demo: http://plnkr.co/edit/MWBjLnTvJeetjU3NEimg?p=preview
38 | *
39 | * Sample HTML:
40 | *
41 | *
42 | *
43 | *
44 | *
45 | * JavaScript:
46 | *
47 | * $('#tabs-inside-here').scrollingTabs({
48 | * tabs: tabs, // required
49 | * propPaneId: 'paneId', // optional
50 | * propTitle: 'title', // optional
51 | * propActive: 'active', // optional
52 | * propDisabled: 'disabled', // optional
53 | * propContent: 'content', // optional
54 | * ignoreTabPanes: false, // optional
55 | * scrollToTabEdge: false, // optional
56 | * disableScrollArrowsOnFullyScrolled: false, // optional
57 | * reverseScroll: false // optional
58 | * });
59 | *
60 | * Settings/Options:
61 | *
62 | * tabs: tabs data array
63 | * prop*: name of your tab object's property name that
64 | * corresponds to that required tab property if
65 | * your property name is different than the
66 | * standard name (paneId, title, etc.)
67 | * tabsLiContent:
68 | * optional string array used to define custom HTML
69 | * for each tab's
element. Each entry is an HTML
70 | * string defining the tab
element for the
71 | * corresponding tab in the tabs array.
72 | * The default for a tab is:
73 | * '
'
74 | * So, for example, if you had 3 tabs and you needed
75 | * a custom 'tooltip' attribute on each one, your
76 | * tabsLiContent array might look like this:
77 | * [
78 | * '',
79 | * '',
80 | * ''
81 | * ]
82 | * This plunk demonstrates its usage (in conjunction
83 | * with tabsPostProcessors):
84 | * http://plnkr.co/edit/ugJLMk7lmDCuZQziQ0k0
85 | * tabsPostProcessors:
86 | * optional array of functions, each one associated
87 | * with an entry in the tabs array. When a tab element
88 | * has been created, its associated post-processor
89 | * function will be called with two arguments: the
90 | * newly created $li and $a jQuery elements for that tab.
91 | * This allows you to, for example, attach a custom
92 | * event listener to each anchor tag.
93 | * This plunk demonstrates its usage (in conjunction
94 | * with tabsLiContent):
95 | * http://plnkr.co/edit/ugJLMk7lmDCuZQziQ0k0
96 | * ignoreTabPanes: relevant for data-driven tabs only--set to true if
97 | * you want the plugin to only touch the tabs
98 | * and to not generate the tab pane elements
99 | * that go in .tab-content. By default, the plugin
100 | * will generate the tab panes based on the content
101 | * property in your tab data, if a content property
102 | * is present.
103 | * scrollToTabEdge: set to true if you want to force full-width tabs
104 | * to display at the left scroll arrow. i.e., if the
105 | * scrolling stops with only half a tab showing,
106 | * it will snap the tab to its edge so the full tab
107 | * shows.
108 | * disableScrollArrowsOnFullyScrolled:
109 | * set to true if you want the left scroll arrow to
110 | * disable when the tabs are scrolled fully left,
111 | * and the right scroll arrow to disable when the tabs
112 | * are scrolled fully right.
113 | * reverseScroll:
114 | * set to true if you want the left scroll arrow to
115 | * slide the tabs left instead of right, and the right
116 | * scroll arrow to slide the tabs right.
117 | * enableSwiping:
118 | * set to true if you want to enable horizontal swiping
119 | * for touch screens.
120 | * widthMultiplier:
121 | * set to a value less than 1 if you want the tabs
122 | * container to be less than the full width of its
123 | * parent element. For example, set it to 0.5 if you
124 | * want the tabs container to be half the width of
125 | * its parent.
126 | * tabClickHandler:
127 | * a callback function to execute any time a tab is clicked.
128 | * The function is simply passed as the event handler
129 | * to jQuery's .on(), so the function will receive
130 | * the jQuery event as an argument, and the 'this'
131 | * inside the function will be the clicked tab's anchor
132 | * element.
133 | * cssClassLeftArrow, cssClassRightArrow:
134 | * custom values for the class attributes for the
135 | * left and right scroll arrows. The defaults are
136 | * 'glyphicon glyphicon-chevron-left' and
137 | * 'glyphicon glyphicon-chevron-right'.
138 | * Using different icons might require you to add
139 | * custom styling to the arrows to position the icons
140 | * correctly; the arrows can be targeted with these
141 | * selectors:
142 | * .scrtabs-tab-scroll-arrow
143 | * .scrtabs-tab-scroll-arrow-left
144 | * .scrtabs-tab-scroll-arrow-right
145 | * leftArrowContent, rightArrowContent:
146 | * custom HTML string for the left and right scroll
147 | * arrows. This will override any custom cssClassLeftArrow
148 | * and cssClassRightArrow settings.
149 | * For example, if you wanted to use svg icons, you
150 | * could set them like so:
151 | *
152 | * leftArrowContent: [
153 | * '
'
165 | * ].join('')
166 | *
167 | * You would then need to add some CSS to make them
168 | * work correctly if you don't give them the
169 | * default scrtabs-tab-scroll-arrow classes.
170 | * This plunk shows it working with svg icons:
171 | * http://plnkr.co/edit/2MdZCAnLyeU40shxaol3?p=preview
172 | *
173 | * When using this option, you can also mark a child
174 | * element within the arrow content as the click target
175 | * if you don't want the entire content to be
176 | * clickable. You do that my adding the CSS class
177 | * 'scrtabs-click-target' to the element that should
178 | * be clickable, like so:
179 | *
180 | * leftArrowContent: [
181 | * '
'
193 | * ].join('')
194 | *
195 | * enableRtlSupport:
196 | * set to true if you want your site to support
197 | * right-to-left languages. If true, the plugin will
198 | * check the page's tag for attribute dir="rtl"
199 | * and will adjust its behavior accordingly.
200 | * handleDelayedScrollbar:
201 | * set to true if you experience a situation where the
202 | * right scroll arrow wraps to the next line due to a
203 | * vertical scrollbar coming into existence on the page
204 | * after the plugin already calculated its width without
205 | * a scrollbar present. This would occur if, for example,
206 | * the bulk of the page's content loaded after a delay,
207 | * and only then did a vertical scrollbar become necessary.
208 | * It would also occur if a vertical scrollbar only appeared
209 | * on selection of a particular tab that had more content
210 | * than the default tab.
211 | * bootstrapVersion:
212 | * set to 4 if you're using Boostrap 4. Default is 3.
213 | * Bootstrap 4 handles some things differently than 3
214 | * (e.g., the 'active' class gets applied to the tab's
215 | * 'li > a' element rather than the 'li' itself).
216 | *
217 | *
218 | * On tabs data change:
219 | *
220 | * $('#tabs-inside-here').scrollingTabs('refresh');
221 | *
222 | * On tabs data change, if you want the active tab to be set based on
223 | * the updated tabs data (i.e., you want to override the current
224 | * active tab setting selected by the user), for example, if you
225 | * added a new tab and you want it to be the active tab:
226 | *
227 | * $('#tabs-inside-here').scrollingTabs('refresh', {
228 | * forceActiveTab: true
229 | * });
230 | *
231 | * Any options that can be passed into the plugin can be set on the
232 | * plugin's 'defaults' object instead so you don't have to pass them in:
233 | *
234 | * $.fn.scrollingTabs.defaults.tabs = tabs;
235 | * $.fn.scrollingTabs.defaults.forceActiveTab = true;
236 | * $.fn.scrollingTabs.defaults.scrollToTabEdge = true;
237 | * $.fn.scrollingTabs.defaults.disableScrollArrowsOnFullyScrolled = true;
238 | * $.fn.scrollingTabs.defaults.reverseScroll = true;
239 | * $.fn.scrollingTabs.defaults.widthMultiplier = 0.5;
240 | * $.fn.scrollingTabs.defaults.tabClickHandler = function () { };
241 | *
242 | *
243 | * Methods
244 | * -----------------------------
245 | * - refresh
246 | * On window resize, the tabs should refresh themselves, but to force a refresh:
247 | *
248 | * $('.nav-tabs').scrollingTabs('refresh');
249 | *
250 | * - scrollToActiveTab
251 | * On window resize, the active tab will automatically be scrolled to
252 | * if it ends up offscreen, but you can also programmatically force a
253 | * scroll to the active tab any time (if, for example, you're
254 | * programmatically setting the active tab) by calling the
255 | * 'scrollToActiveTab' method:
256 | *
257 | * $('.nav-tabs').scrollingTabs('scrollToActiveTab');
258 | *
259 | *
260 | * Events
261 | * -----------------------------
262 | * The plugin triggers event 'ready.scrtabs' when the tabs have
263 | * been wrapped in the scroller and are ready for viewing:
264 | *
265 | * $('.nav-tabs')
266 | * .scrollingTabs()
267 | * .on('ready.scrtabs', function() {
268 | * // tabs ready, do my other stuff...
269 | * });
270 | *
271 | * $('#tabs-inside-here')
272 | * .scrollingTabs({ tabs: tabs })
273 | * .on('ready.scrtabs', function() {
274 | * // tabs ready, do my other stuff...
275 | * });
276 | *
277 | *
278 | * Destroying
279 | * -----------------------------
280 | * To destroy:
281 | *
282 | * $('.nav-tabs').scrollingTabs('destroy');
283 | *
284 | * $('#tabs-inside-here').scrollingTabs('destroy');
285 | *
286 | * If you were wrapping markup, the markup will be restored; if your tabs
287 | * were data-driven, the tabs will be destroyed along with the plugin.
288 | *
289 | */
290 |
--------------------------------------------------------------------------------
/src/scss/jquery.scrolling-tabs.scss:
--------------------------------------------------------------------------------
1 | // Tabs height
2 | $scrtabs-tabs-height: 42px !default;
3 |
4 | // Border color (bootstrap lt gray)
5 | $scrtabs-border-color: 1px solid rgb(221, 221, 221) !default;
6 |
7 | // Foreground color (bootstrap blue)
8 | $scrtabs-foreground-color: rgb(66, 139, 202) !default;
9 |
10 | // Background color on hover (bootstrap gray)
11 | $scrtabs-background-color-hover: rgb(238, 238, 238) !default;
12 |
13 | .scrtabs-tab-container * {
14 | box-sizing: border-box;
15 | }
16 |
17 | .scrtabs-tab-container {
18 | height: $scrtabs-tabs-height;
19 | .tab-content {
20 | clear: left;
21 | }
22 | }
23 |
24 | .scrtabs-tab-container.scrtabs-bootstrap4 .scrtabs-tabs-movable-container > .navbar-nav {
25 | -ms-flex-direction: row;
26 | flex-direction: row;
27 | }
28 |
29 | .scrtabs-tabs-fixed-container {
30 | float: left;
31 | height: $scrtabs-tabs-height;
32 | overflow: hidden;
33 | width: 100%;
34 | }
35 |
36 | .scrtabs-tabs-movable-container {
37 | position: relative;
38 | .tab-content {
39 | display: none;
40 | }
41 | }
42 |
43 | // override user agent padding-start (which translates to padding-right for
44 | // RTL sites) of 40px applied to