|
1 | 1 | /** |
2 | 2 | * jquery-bootstrap-scrolling-tabs |
3 | | - * @version v1.2.2 |
| 3 | + * @version v2.0.0 |
4 | 4 | * @link https://github.com/mikejacobson/jquery-bootstrap-scrolling-tabs |
5 | 5 | * @author Mike Jacobson <michaeljjacobson1@gmail.com> |
6 | 6 | * @license MIT License, http://www.opensource.org/licenses/MIT |
7 | 7 | */ |
8 | | - |
9 | 8 | /** |
10 | 9 | * jQuery plugin version of Angular directive angular-bootstrap-scrolling-tabs: |
11 | 10 | * https://github.com/mikejacobson/angular-bootstrap-scrolling-tabs |
|
95 | 94 | * scroll arrow to slide the tabs right. |
96 | 95 | * enableSwiping: |
97 | 96 | * set to true if you want to enable horizontal swiping |
98 | | - * for touch screens. This simply enables horizontal |
99 | | - * scrolling--and therefore the horizontal scrollbar--for |
100 | | - * the tabs. For WebKit-based browsers, the scrollbar |
101 | | - * will then be hidden via CSS (because the plugin will |
102 | | - * add CSS class scrtabs-allow-scrollbar to the parent |
103 | | - * element) but for browsers that don't support |
104 | | - * ::-webkit-scrollbar, the scrollbar will be visible. |
| 97 | + * for touch screens. |
105 | 98 | * widthMultiplier: |
106 | 99 | * set to a value less than 1 if you want the tabs |
107 | 100 | * container to be less than the full width of its |
|
232 | 225 | ;(function ($, window) { |
233 | 226 | 'use strict'; |
234 | 227 |
|
| 228 | + /* exported CONSTANTS */ |
235 | 229 | var CONSTANTS = { |
236 | 230 | CONTINUOUS_SCROLLING_TIMEOUT_INTERVAL: 50, // timeout interval for repeatedly moving the tabs container |
237 | 231 | // by one increment while the mouse is held down--decrease to |
|
243 | 237 | DATA_KEY_IS_MOUSEDOWN: 'scrtabsismousedown', |
244 | 238 |
|
245 | 239 | CSS_CLASSES: { |
246 | | - ALLOW_SCROLLBAR: 'scrtabs-allow-scrollbar', |
247 | 240 | SCROLL_ARROW_DISABLE: 'scrtabs-disable' |
248 | 241 | }, |
249 | 242 |
|
|
257 | 250 | DROPDOWN_MENU_HIDE: 'hide.bs.dropdown.scrtabs', |
258 | 251 | DROPDOWN_MENU_SHOW: 'show.bs.dropdown.scrtabs', |
259 | 252 | FORCE_REFRESH: 'forcerefresh.scrtabs', |
260 | | - MOUSEDOWN: 'mousedown.scrtabs touchstart.scrtabs', |
261 | | - MOUSEUP: 'mouseup.scrtabs touchend.scrtabs', |
262 | | - WINDOW_RESIZE: 'resize.scrtabs', |
263 | | - TABS_READY: 'ready.scrtabs' |
| 253 | + MOUSEDOWN: 'mousedown.scrtabs', |
| 254 | + MOUSEUP: 'mouseup.scrtabs', |
| 255 | + TABS_READY: 'ready.scrtabs', |
| 256 | + TOUCH_END: 'touchend.scrtabs', |
| 257 | + TOUCH_MOVE: 'touchmove.scrtabs', |
| 258 | + TOUCH_START: 'touchstart.scrtabs', |
| 259 | + WINDOW_RESIZE: 'resize.scrtabs' |
264 | 260 | } |
265 | 261 | }; |
266 | 262 |
|
|
306 | 302 | var ehd = this; |
307 | 303 |
|
308 | 304 | ehd.setElementReferences(); |
309 | | - ehd.setEventListeners(); |
| 305 | + ehd.setEventListeners(options); |
| 306 | + }; |
| 307 | + |
| 308 | + p.listenForTouchEvents = function () { |
| 309 | + var ehd = this, |
| 310 | + stc = ehd.stc, |
| 311 | + smv = stc.scrollMovement, |
| 312 | + ev = CONSTANTS.EVENTS; |
| 313 | + |
| 314 | + var touching = false; |
| 315 | + var touchStartX; |
| 316 | + var startingContainerLeftPos; |
| 317 | + var newLeftPos; |
| 318 | + |
| 319 | + stc.$movableContainer |
| 320 | + .on(ev.TOUCH_START, function (e) { |
| 321 | + touching = true; |
| 322 | + startingContainerLeftPos = stc.movableContainerLeftPos; |
| 323 | + touchStartX = e.originalEvent.changedTouches[0].pageX; |
| 324 | + }) |
| 325 | + .on(ev.TOUCH_END, function () { |
| 326 | + touching = false; |
| 327 | + }) |
| 328 | + .on(ev.TOUCH_MOVE, function (e) { |
| 329 | + if (!touching) { |
| 330 | + return; |
| 331 | + } |
| 332 | + |
| 333 | + var touchPageX = e.originalEvent.changedTouches[0].pageX; |
| 334 | + var diff = touchPageX - touchStartX; |
| 335 | + var minPos; |
| 336 | + |
| 337 | + newLeftPos = startingContainerLeftPos + diff; |
| 338 | + if (newLeftPos > 0) { |
| 339 | + newLeftPos = 0; |
| 340 | + } else { |
| 341 | + minPos = smv.getMinPos(); |
| 342 | + if (newLeftPos < minPos) { |
| 343 | + newLeftPos = minPos; |
| 344 | + } |
| 345 | + } |
| 346 | + stc.movableContainerLeftPos = newLeftPos; |
| 347 | + stc.$movableContainer.css('left', smv.getMovableContainerCssLeftVal()); |
| 348 | + smv.refreshScrollArrowsDisabledState(); |
| 349 | + }); |
310 | 350 | }; |
311 | 351 |
|
312 | 352 | p.refreshAllElementSizes = function () { |
|
400 | 440 | ehd.setMovableContainerWidth(); |
401 | 441 | }; |
402 | 442 |
|
403 | | - p.setEventListeners = function () { |
| 443 | + p.setEventListeners = function (settings) { |
404 | 444 | var ehd = this, |
405 | 445 | stc = ehd.stc, |
406 | 446 | evh = stc.eventHandlers, |
407 | 447 | ev = CONSTANTS.EVENTS; |
408 | 448 |
|
| 449 | + if (settings.enableSwiping) { |
| 450 | + ehd.listenForTouchEvents(); |
| 451 | + } |
| 452 | + |
409 | 453 | stc.$slideLeftArrow |
410 | 454 | .off('.scrtabs') |
411 | 455 | .on(ev.MOUSEDOWN, function (e) { evh.handleMousedownOnSlideMovContainerLeftArrow.call(evh, e); }) |
|
526 | 570 |
|
527 | 571 | // prototype methods |
528 | 572 | (function (p){ |
529 | | - p.handleClickOnSlideMovContainerLeftArrow = function (e) { |
| 573 | + p.handleClickOnSlideMovContainerLeftArrow = function () { |
530 | 574 | var evh = this, |
531 | 575 | stc = evh.stc; |
532 | 576 |
|
533 | 577 | stc.scrollMovement.incrementMovableContainerLeft(); |
534 | 578 | }; |
535 | 579 |
|
536 | | - p.handleClickOnSlideMovContainerRightArrow = function (e) { |
| 580 | + p.handleClickOnSlideMovContainerRightArrow = function () { |
537 | 581 | var evh = this, |
538 | 582 | stc = evh.stc; |
539 | 583 |
|
540 | 584 | stc.scrollMovement.incrementMovableContainerRight(); |
541 | 585 | }; |
542 | 586 |
|
543 | | - p.handleMousedownOnSlideMovContainerLeftArrow = function (e) { |
| 587 | + p.handleMousedownOnSlideMovContainerLeftArrow = function () { |
544 | 588 | var evh = this, |
545 | 589 | stc = evh.stc; |
546 | 590 |
|
547 | 591 | stc.$slideLeftArrow.data(CONSTANTS.DATA_KEY_IS_MOUSEDOWN, true); |
548 | 592 | stc.scrollMovement.continueSlideMovableContainerLeft(); |
549 | 593 | }; |
550 | 594 |
|
551 | | - p.handleMousedownOnSlideMovContainerRightArrow = function (e) { |
| 595 | + p.handleMousedownOnSlideMovContainerRightArrow = function () { |
552 | 596 | var evh = this, |
553 | 597 | stc = evh.stc; |
554 | 598 |
|
555 | 599 | stc.$slideRightArrow.data(CONSTANTS.DATA_KEY_IS_MOUSEDOWN, true); |
556 | 600 | stc.scrollMovement.continueSlideMovableContainerRight(); |
557 | 601 | }; |
558 | 602 |
|
559 | | - p.handleMouseupOnSlideMovContainerLeftArrow = function (e) { |
| 603 | + p.handleMouseupOnSlideMovContainerLeftArrow = function () { |
560 | 604 | var evh = this, |
561 | 605 | stc = evh.stc; |
562 | 606 |
|
563 | 607 | stc.$slideLeftArrow.data(CONSTANTS.DATA_KEY_IS_MOUSEDOWN, false); |
564 | 608 | }; |
565 | 609 |
|
566 | | - p.handleMouseupOnSlideMovContainerRightArrow = function (e) { |
| 610 | + p.handleMouseupOnSlideMovContainerRightArrow = function () { |
567 | 611 | var evh = this, |
568 | 612 | stc = evh.stc; |
569 | 613 |
|
570 | 614 | stc.$slideRightArrow.data(CONSTANTS.DATA_KEY_IS_MOUSEDOWN, false); |
571 | 615 | }; |
572 | 616 |
|
573 | | - p.handleWindowResize = function (e) { |
| 617 | + p.handleWindowResize = function () { |
574 | 618 | var evh = this, |
575 | 619 | stc = evh.stc, |
576 | 620 | newWinWidth = stc.$win.width(); |
|
765 | 809 | smv.enableSlideRightArrow(); |
766 | 810 | }; |
767 | 811 |
|
768 | | - p.scrollToActiveTab = function (options) { |
| 812 | + p.scrollToActiveTab = function () { |
769 | 813 | var smv = this, |
770 | 814 | stc = smv.stc, |
771 | 815 | RIGHT_OFFSET_BUFFER = 20, |
|
801 | 845 | smv.slideMovableContainerToLeftPos(); |
802 | 846 | return true; |
803 | 847 | } else { |
804 | | - leftScrollArrowWidth = stc.$slideLeftArrow.outerWidth(); |
| 848 | + leftScrollArrowWidth = stc.$slideLeftArrow.outerWidth(); |
805 | 849 | if (activeTabLeftPos < leftScrollArrowWidth) { // active tab off left side |
806 | 850 | stc.movableContainerLeftPos += leftScrollArrowWidth - activeTabLeftPos; |
807 | 851 | smv.slideMovableContainerToLeftPos(); |
|
820 | 864 |
|
821 | 865 | // make sure LeftPos is set so that a tab edge will be against the |
822 | 866 | // left scroll arrow so we won't have a partial, cut-off tab |
823 | | - stc.$tabsLiCollection.each(function (index) { |
| 867 | + stc.$tabsLiCollection.each(function () { |
824 | 868 | var tabWidth = $(this).width(); |
825 | 869 |
|
826 | 870 | totalTabWidth += tabWidth; |
|
952 | 996 | }(ScrollingTabsControl.prototype)); |
953 | 997 |
|
954 | 998 |
|
| 999 | + /* exported buildNavTabsAndTabContentForTargetElementInstance */ |
955 | 1000 | var tabElements = (function () { |
956 | 1001 |
|
957 | 1002 | return { |
|
1128 | 1173 | return; |
1129 | 1174 | } |
1130 | 1175 |
|
1131 | | - tabs.forEach(function(tab, index) { |
| 1176 | + tabs.forEach(function(tab) { |
1132 | 1177 | tabElements |
1133 | 1178 | .getNewElTabLi(tab, propNames, true) // true -> forceActiveTab |
1134 | 1179 | .appendTo($navTabs); |
|
1209 | 1254 | return $scroller; |
1210 | 1255 | } |
1211 | 1256 |
|
| 1257 | + /* exported listenForDropdownMenuTabs, |
| 1258 | + refreshTargetElementInstance, |
| 1259 | + scrollToActiveTab */ |
1212 | 1260 | function checkForTabAdded(refreshData) { |
1213 | 1261 | var updatedTabsArray = refreshData.updatedTabsArray, |
1214 | 1262 | propNames = refreshData.propNames, |
|
1359 | 1407 | } |
1360 | 1408 |
|
1361 | 1409 | // the tab order changed... |
1362 | | - updatedTabsArray.forEach(function (t, i) { |
| 1410 | + updatedTabsArray.forEach(function (t) { |
1363 | 1411 | var paneId = t[propNames.paneId]; |
1364 | 1412 |
|
1365 | 1413 | newTabsCollection.push( |
|
1471 | 1519 | 'left': ddMenuTargetLeft |
1472 | 1520 | }); |
1473 | 1521 |
|
1474 | | - function handleClickOnDropdownMenuItem(e) { |
| 1522 | + function handleClickOnDropdownMenuItem() { |
1475 | 1523 | var $selectedMenuItemAnc = $(this), |
1476 | 1524 | $selectedMenuItemLi = $selectedMenuItemAnc.parent('li'), |
1477 | 1525 | $selectedMenuItemDropdownMenu = $selectedMenuItemLi.parent('.dropdown-menu'), |
|
1590 | 1638 | $targetEls.trigger(CONSTANTS.EVENTS.TABS_READY); |
1591 | 1639 | }; |
1592 | 1640 |
|
1593 | | - if (settings.enableSwiping) { |
1594 | | - $targetEl.parent().addClass(CONSTANTS.CSS_CLASSES.ALLOW_SCROLLBAR); |
1595 | | - $targetEl.data('scrtabs').enableSwipingElement = 'parent'; |
1596 | | - } |
1597 | | - |
1598 | 1641 | wrapNavTabsInstanceInScroller($targetEl, settings, readyCallback); |
1599 | 1642 | }); |
1600 | 1643 |
|
|
1607 | 1650 | $targetEls.trigger(CONSTANTS.EVENTS.TABS_READY); |
1608 | 1651 | }; |
1609 | 1652 |
|
1610 | | - var $newTargetEl = buildNavTabsAndTabContentForTargetElementInstance($targetEl, settings, readyCallback); |
1611 | | - |
1612 | | - if (settings.enableSwiping) { |
1613 | | - $newTargetEl.addClass(CONSTANTS.CSS_CLASSES.ALLOW_SCROLLBAR); |
1614 | | - $newTargetEl.data('scrtabs').enableSwipingElement = 'self'; |
1615 | | - } |
| 1653 | + buildNavTabsAndTabContentForTargetElementInstance($targetEl, settings, readyCallback); |
1616 | 1654 | }); |
1617 | 1655 | }, |
1618 | 1656 |
|
|
0 commit comments