Skip to content

Commit 2700535

Browse files
authored
Merge pull request #32 from mikejacobson/fix-swipe
Fix swipe
2 parents aa1e2eb + 00f8193 commit 2700535

21 files changed

+173
-131
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
.jshintrc
12
.project
23
.sass-cache
34
*.rb

README.md

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ Usage
4040
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)
4141

4242

43+
Breaking Change for v2.0.0: Only affects swiping for touch screens
44+
--
45+
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.
46+
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`.
47+
4348
Breaking Change for v1.0.0
4449
--
4550
* The plugin files, `jquery.scrolling-tabs.js` and `jquery.scrolling-tabs.css`, have been moved from the project root into `<root>/dist/`.
@@ -432,42 +437,13 @@ http://plnkr.co/edit/2MdZCAnLyeU40shxaol3?p=preview
432437

433438
#### <a id="allowScrollbar"></a>Enable Horizontal Swiping for Touch Screens
434439

435-
To enable horizontal swiping for touch screens, you need to enable horizontal scrolling&mdash;and therefore the horizontal scrollbar&mdash;for the tabs. For WebKit-based browsers, the scrollbar can then be hidden via CSS, but for browsers that don't support `::-webkit-scrollbar` (see [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-scrollbar) for details), the scrollbar will be visible (which is what this plugin was originally built to prevent).
436-
437-
So if you only need to support WebKit-based browsers, there are two ways to enable swiping: you can add a CSS class to an ancestor element of the tabs, or you can pass in a config option on init.
438-
439-
##### Enable via CSS Class
440-
Adding CSS class `scrtabs-allow-scrollbar` to an ancestor element of the tabs element will enable touch swiping. As long as the tabs fixed container (`.scrtabs-tabs-fixed-container`) is a descendent of the element with that class, it will work.
441-
442-
For example:
443-
```html
444-
<body class="scrtabs-allow-scrollbar">
445-
<!-- Nav tabs -->
446-
<ul class="nav nav-tabs" role="tablist">
447-
<li role="presentation" class="active"><a href="#tab1" role="tab" data-toggle="tab">Tab Number 1</a></li>
448-
<li role="presentation"><a href="#tab2" role="tab" data-toggle="tab">Tab Number 2</a></li>
449-
<li role="presentation"><a href="#tab3" role="tab" data-toggle="tab">Tab Number 3</a></li>
450-
</ul>
451-
452-
<!-- Tab panes -->
453-
<div class="tab-content">
454-
<div role="tabpanel" class="tab-pane active" id="tab1">Tab 1 content...</div>
455-
<div role="tabpanel" class="tab-pane" id="tab2">Tab 2 content...</div>
456-
<div role="tabpanel" class="tab-pane" id="tab3">Tab 3 content...</div>
457-
</div>
458-
</body>
459-
```
460-
461-
##### Enable via Config Option
462-
Alternatively, you can pass in option `enableSwiping: true` when initializing the plugin:
440+
To enable horizontal swiping for touch screens, pass in option `enableSwiping: true` when initializing the plugin:
463441
```javascript
464442
$('.nav-tabs').scrollingTabs({
465443
enableSwiping: true
466444
});
467445
```
468-
This will simply add the `scrtabs-allow-scrollbar` CSS class to the tabs' parent element for you.
469-
470-
446+
This will enable swiping for any browser that supports [touch events](https://developer.mozilla.org/en-US/docs/Web/API/Touch_events).
471447

472448

473449
#### Setting Defaults

bower.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "jquery-bootstrap-scrolling-tabs",
3-
"version": "1.2.2",
3+
"version": "2.0.0",
44
"main": [
55
"./dist/jquery.scrolling-tabs.js",
66
"./dist/jquery.scrolling-tabs.css"

dist/jquery.scrolling-tabs.css

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* jquery-bootstrap-scrolling-tabs
3-
* @version v1.2.2
3+
* @version v2.0.0
44
* @link https://github.com/mikejacobson/jquery-bootstrap-scrolling-tabs
55
* @author Mike Jacobson <[email protected]>
66
* @license MIT License, http://www.opensource.org/licenses/MIT
@@ -19,11 +19,6 @@
1919
overflow: hidden;
2020
width: 100%; }
2121

22-
.scrtabs-allow-scrollbar .scrtabs-tabs-fixed-container {
23-
overflow-x: auto; }
24-
.scrtabs-allow-scrollbar .scrtabs-tabs-fixed-container::-webkit-scrollbar {
25-
display: none; }
26-
2722
.scrtabs-tabs-movable-container {
2823
position: relative; }
2924
.scrtabs-tabs-movable-container .tab-content {

dist/jquery.scrolling-tabs.js

Lines changed: 78 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
/**
22
* jquery-bootstrap-scrolling-tabs
3-
* @version v1.2.2
3+
* @version v2.0.0
44
* @link https://github.com/mikejacobson/jquery-bootstrap-scrolling-tabs
55
* @author Mike Jacobson <[email protected]>
66
* @license MIT License, http://www.opensource.org/licenses/MIT
77
*/
8-
98
/**
109
* jQuery plugin version of Angular directive angular-bootstrap-scrolling-tabs:
1110
* https://github.com/mikejacobson/angular-bootstrap-scrolling-tabs
@@ -95,13 +94,7 @@
9594
* scroll arrow to slide the tabs right.
9695
* enableSwiping:
9796
* 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.
10598
* widthMultiplier:
10699
* set to a value less than 1 if you want the tabs
107100
* container to be less than the full width of its
@@ -232,6 +225,7 @@
232225
;(function ($, window) {
233226
'use strict';
234227

228+
/* exported CONSTANTS */
235229
var CONSTANTS = {
236230
CONTINUOUS_SCROLLING_TIMEOUT_INTERVAL: 50, // timeout interval for repeatedly moving the tabs container
237231
// by one increment while the mouse is held down--decrease to
@@ -243,7 +237,6 @@
243237
DATA_KEY_IS_MOUSEDOWN: 'scrtabsismousedown',
244238

245239
CSS_CLASSES: {
246-
ALLOW_SCROLLBAR: 'scrtabs-allow-scrollbar',
247240
SCROLL_ARROW_DISABLE: 'scrtabs-disable'
248241
},
249242

@@ -257,10 +250,13 @@
257250
DROPDOWN_MENU_HIDE: 'hide.bs.dropdown.scrtabs',
258251
DROPDOWN_MENU_SHOW: 'show.bs.dropdown.scrtabs',
259252
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'
264260
}
265261
};
266262

@@ -306,7 +302,51 @@
306302
var ehd = this;
307303

308304
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+
});
310350
};
311351

312352
p.refreshAllElementSizes = function () {
@@ -400,12 +440,16 @@
400440
ehd.setMovableContainerWidth();
401441
};
402442

403-
p.setEventListeners = function () {
443+
p.setEventListeners = function (settings) {
404444
var ehd = this,
405445
stc = ehd.stc,
406446
evh = stc.eventHandlers,
407447
ev = CONSTANTS.EVENTS;
408448

449+
if (settings.enableSwiping) {
450+
ehd.listenForTouchEvents();
451+
}
452+
409453
stc.$slideLeftArrow
410454
.off('.scrtabs')
411455
.on(ev.MOUSEDOWN, function (e) { evh.handleMousedownOnSlideMovContainerLeftArrow.call(evh, e); })
@@ -526,51 +570,51 @@
526570

527571
// prototype methods
528572
(function (p){
529-
p.handleClickOnSlideMovContainerLeftArrow = function (e) {
573+
p.handleClickOnSlideMovContainerLeftArrow = function () {
530574
var evh = this,
531575
stc = evh.stc;
532576

533577
stc.scrollMovement.incrementMovableContainerLeft();
534578
};
535579

536-
p.handleClickOnSlideMovContainerRightArrow = function (e) {
580+
p.handleClickOnSlideMovContainerRightArrow = function () {
537581
var evh = this,
538582
stc = evh.stc;
539583

540584
stc.scrollMovement.incrementMovableContainerRight();
541585
};
542586

543-
p.handleMousedownOnSlideMovContainerLeftArrow = function (e) {
587+
p.handleMousedownOnSlideMovContainerLeftArrow = function () {
544588
var evh = this,
545589
stc = evh.stc;
546590

547591
stc.$slideLeftArrow.data(CONSTANTS.DATA_KEY_IS_MOUSEDOWN, true);
548592
stc.scrollMovement.continueSlideMovableContainerLeft();
549593
};
550594

551-
p.handleMousedownOnSlideMovContainerRightArrow = function (e) {
595+
p.handleMousedownOnSlideMovContainerRightArrow = function () {
552596
var evh = this,
553597
stc = evh.stc;
554598

555599
stc.$slideRightArrow.data(CONSTANTS.DATA_KEY_IS_MOUSEDOWN, true);
556600
stc.scrollMovement.continueSlideMovableContainerRight();
557601
};
558602

559-
p.handleMouseupOnSlideMovContainerLeftArrow = function (e) {
603+
p.handleMouseupOnSlideMovContainerLeftArrow = function () {
560604
var evh = this,
561605
stc = evh.stc;
562606

563607
stc.$slideLeftArrow.data(CONSTANTS.DATA_KEY_IS_MOUSEDOWN, false);
564608
};
565609

566-
p.handleMouseupOnSlideMovContainerRightArrow = function (e) {
610+
p.handleMouseupOnSlideMovContainerRightArrow = function () {
567611
var evh = this,
568612
stc = evh.stc;
569613

570614
stc.$slideRightArrow.data(CONSTANTS.DATA_KEY_IS_MOUSEDOWN, false);
571615
};
572616

573-
p.handleWindowResize = function (e) {
617+
p.handleWindowResize = function () {
574618
var evh = this,
575619
stc = evh.stc,
576620
newWinWidth = stc.$win.width();
@@ -765,7 +809,7 @@
765809
smv.enableSlideRightArrow();
766810
};
767811

768-
p.scrollToActiveTab = function (options) {
812+
p.scrollToActiveTab = function () {
769813
var smv = this,
770814
stc = smv.stc,
771815
RIGHT_OFFSET_BUFFER = 20,
@@ -801,7 +845,7 @@
801845
smv.slideMovableContainerToLeftPos();
802846
return true;
803847
} else {
804-
leftScrollArrowWidth = stc.$slideLeftArrow.outerWidth();
848+
leftScrollArrowWidth = stc.$slideLeftArrow.outerWidth();
805849
if (activeTabLeftPos < leftScrollArrowWidth) { // active tab off left side
806850
stc.movableContainerLeftPos += leftScrollArrowWidth - activeTabLeftPos;
807851
smv.slideMovableContainerToLeftPos();
@@ -820,7 +864,7 @@
820864

821865
// make sure LeftPos is set so that a tab edge will be against the
822866
// left scroll arrow so we won't have a partial, cut-off tab
823-
stc.$tabsLiCollection.each(function (index) {
867+
stc.$tabsLiCollection.each(function () {
824868
var tabWidth = $(this).width();
825869

826870
totalTabWidth += tabWidth;
@@ -952,6 +996,7 @@
952996
}(ScrollingTabsControl.prototype));
953997

954998

999+
/* exported buildNavTabsAndTabContentForTargetElementInstance */
9551000
var tabElements = (function () {
9561001

9571002
return {
@@ -1128,7 +1173,7 @@
11281173
return;
11291174
}
11301175

1131-
tabs.forEach(function(tab, index) {
1176+
tabs.forEach(function(tab) {
11321177
tabElements
11331178
.getNewElTabLi(tab, propNames, true) // true -> forceActiveTab
11341179
.appendTo($navTabs);
@@ -1209,6 +1254,9 @@
12091254
return $scroller;
12101255
}
12111256

1257+
/* exported listenForDropdownMenuTabs,
1258+
refreshTargetElementInstance,
1259+
scrollToActiveTab */
12121260
function checkForTabAdded(refreshData) {
12131261
var updatedTabsArray = refreshData.updatedTabsArray,
12141262
propNames = refreshData.propNames,
@@ -1359,7 +1407,7 @@
13591407
}
13601408

13611409
// the tab order changed...
1362-
updatedTabsArray.forEach(function (t, i) {
1410+
updatedTabsArray.forEach(function (t) {
13631411
var paneId = t[propNames.paneId];
13641412

13651413
newTabsCollection.push(
@@ -1471,7 +1519,7 @@
14711519
'left': ddMenuTargetLeft
14721520
});
14731521

1474-
function handleClickOnDropdownMenuItem(e) {
1522+
function handleClickOnDropdownMenuItem() {
14751523
var $selectedMenuItemAnc = $(this),
14761524
$selectedMenuItemLi = $selectedMenuItemAnc.parent('li'),
14771525
$selectedMenuItemDropdownMenu = $selectedMenuItemLi.parent('.dropdown-menu'),
@@ -1590,11 +1638,6 @@
15901638
$targetEls.trigger(CONSTANTS.EVENTS.TABS_READY);
15911639
};
15921640

1593-
if (settings.enableSwiping) {
1594-
$targetEl.parent().addClass(CONSTANTS.CSS_CLASSES.ALLOW_SCROLLBAR);
1595-
$targetEl.data('scrtabs').enableSwipingElement = 'parent';
1596-
}
1597-
15981641
wrapNavTabsInstanceInScroller($targetEl, settings, readyCallback);
15991642
});
16001643

@@ -1607,12 +1650,7 @@
16071650
$targetEls.trigger(CONSTANTS.EVENTS.TABS_READY);
16081651
};
16091652

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);
16161654
});
16171655
},
16181656

dist/jquery.scrolling-tabs.min.css

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)