| 1 | /* |
||
| 2 | * @name DoubleScroll |
||
| 3 | * @desc displays scroll bar on top and on the bottom of the div |
||
| 4 | * @requires jQuery |
||
| 5 | * |
||
| 6 | * @author Pawel Suwala - http://suwala.eu/ |
||
| 7 | * @author Antoine Vianey - http://www.astek.fr/ |
||
| 8 | * @version 0.5 (11-11-2015) |
||
| 9 | * |
||
| 10 | * Dual licensed under the MIT and GPL licenses: |
||
| 11 | * http://www.opensource.org/licenses/mit-license.php |
||
| 12 | * http://www.gnu.org/licenses/gpl.html |
||
| 13 | * |
||
| 14 | * Usage: |
||
| 15 | * https://github.com/avianey/jqDoubleScroll |
||
| 16 | */ |
||
| 17 | (function( $ ) { |
||
| 18 | |||
| 19 | jQuery.fn.doubleScroll = function(userOptions) { |
||
| 20 | |||
| 21 | // Default options |
||
| 22 | var options = { |
||
| 23 | contentElement: undefined, // Widest element, if not specified first child element will be used |
||
| 24 | scrollCss: { |
||
| 25 | 'overflow-x': 'auto', |
||
| 26 | 'overflow-y': 'hidden', |
||
| 27 | 'height': '20px' |
||
| 28 | }, |
||
| 29 | contentCss: { |
||
| 30 | 'overflow-x': 'auto', |
||
| 31 | 'overflow-y': 'hidden' |
||
| 32 | }, |
||
| 33 | onlyIfScroll: true, // top scrollbar is not shown if the bottom one is not present |
||
| 34 | resetOnWindowResize: false, // recompute the top ScrollBar requirements when the window is resized |
||
| 35 | timeToWaitForResize: 30 // wait for the last update event (usefull when browser fire resize event constantly during ressing) |
||
| 36 | }; |
||
| 37 | |||
| 38 | $.extend(true, options, userOptions); |
||
| 39 | |||
| 40 | // do not modify |
||
| 41 | // internal stuff |
||
| 42 | $.extend(options, { |
||
| 43 | topScrollBarMarkup: '<div class="doubleScroll-scroll-wrapper"><div class="doubleScroll-scroll"></div></div>', |
||
| 44 | topScrollBarWrapperSelector: '.doubleScroll-scroll-wrapper', |
||
| 45 | topScrollBarInnerSelector: '.doubleScroll-scroll' |
||
| 46 | }); |
||
| 47 | |||
| 48 | var _showScrollBar = function($self, options) { |
||
| 49 | |||
| 50 | if (options.onlyIfScroll && $self.get(0).scrollWidth <= $self.width()) { |
||
| 51 | // content doesn't scroll |
||
| 52 | // remove any existing occurrence... |
||
| 53 | $self.prev(options.topScrollBarWrapperSelector).remove(); |
||
| 54 | return; |
||
| 55 | } |
||
| 56 | |||
| 57 | // add div that will act as an upper scroll only if not already added to the DOM |
||
| 58 | var $topScrollBar = $self.prev(options.topScrollBarWrapperSelector); |
||
| 59 | |||
| 60 | if ($topScrollBar.length == 0) { |
||
|
0 ignored issues
–
show
Best Practice
introduced
by
Loading history...
|
|||
| 61 | |||
| 62 | // creating the scrollbar |
||
| 63 | // added before in the DOM |
||
| 64 | $topScrollBar = $(options.topScrollBarMarkup); |
||
| 65 | $self.before($topScrollBar); |
||
| 66 | |||
| 67 | // apply the css |
||
| 68 | $topScrollBar.css(options.scrollCss); |
||
| 69 | $(options.topScrollBarInnerSelector).css("height", "20px"); |
||
| 70 | $self.css(options.contentCss); |
||
| 71 | |||
| 72 | var scrolling = false; |
||
| 73 | |||
| 74 | // bind upper scroll to bottom scroll |
||
| 75 | $topScrollBar.bind('scroll.doubleScroll', function() { |
||
| 76 | if (scrolling) { |
||
| 77 | scrolling = false; |
||
| 78 | return; |
||
| 79 | } |
||
| 80 | scrolling = true; |
||
| 81 | $self.scrollLeft($topScrollBar.scrollLeft()); |
||
| 82 | }); |
||
| 83 | |||
| 84 | // bind bottom scroll to upper scroll |
||
| 85 | var selfScrollHandler = function() { |
||
| 86 | if (scrolling) { |
||
| 87 | scrolling = false; |
||
| 88 | return; |
||
| 89 | } |
||
| 90 | scrolling = true; |
||
| 91 | $topScrollBar.scrollLeft($self.scrollLeft()); |
||
| 92 | }; |
||
| 93 | $self.bind('scroll.doubleScroll', selfScrollHandler); |
||
| 94 | } |
||
| 95 | |||
| 96 | // find the content element (should be the widest one) |
||
| 97 | var $contentElement; |
||
| 98 | |||
| 99 | if (options.contentElement !== undefined && $self.find(options.contentElement).length !== 0) { |
||
| 100 | $contentElement = $self.find(options.contentElement); |
||
| 101 | } else { |
||
| 102 | $contentElement = $self.find('>:first-child'); |
||
| 103 | } |
||
| 104 | |||
| 105 | // set the width of the wrappers |
||
| 106 | $(options.topScrollBarInnerSelector, $topScrollBar).width($contentElement.outerWidth()); |
||
| 107 | $topScrollBar.width($self.width()); |
||
| 108 | $topScrollBar.scrollLeft($self.scrollLeft()); |
||
| 109 | |||
| 110 | } |
||
| 111 | |||
| 112 | return this.each(function() { |
||
| 113 | |||
| 114 | var $self = $(this); |
||
| 115 | |||
| 116 | _showScrollBar($self, options); |
||
| 117 | |||
| 118 | // bind the resize handler |
||
| 119 | // do it once |
||
| 120 | if (options.resetOnWindowResize) { |
||
| 121 | |||
| 122 | var id; |
||
| 123 | var handler = function(e) { |
||
|
0 ignored issues
–
show
|
|||
| 124 | _showScrollBar($self, options); |
||
| 125 | }; |
||
| 126 | |||
| 127 | $(window).bind('resize.doubleScroll', function() { |
||
| 128 | // adding/removing/replacing the scrollbar might resize the window |
||
| 129 | // so the resizing flag will avoid the infinite loop here... |
||
| 130 | clearTimeout(id); |
||
| 131 | id = setTimeout(handler, options.timeToWaitForResize); |
||
| 132 | }); |
||
| 133 | |||
| 134 | } |
||
| 135 | |||
| 136 | }); |
||
| 137 | |||
| 138 | } |
||
| 139 | |||
| 140 | }( jQuery )); |
||
| 141 |