├── .gitignore
├── .jshintrc
├── Gruntfile.js
├── README.md
├── bower.json
├── example.html
├── jquery.scrolltab.js
├── package.json
└── scrolltab.jquery.json
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | build
3 |
4 | .sizecache.json
5 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "boss": true,
3 | "browser": true,
4 | "curly": true,
5 | "eqeqeq": true,
6 | "eqnull": true,
7 | "expr": true,
8 | "evil": true,
9 | "newcap": true,
10 | "noarg": true,
11 | "undef": true,
12 | "globals": {
13 | "jQuery": true,
14 | "define": true
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | /*jshint node: true */
2 |
3 | 'use strict';
4 |
5 | module.exports = function (grunt) {
6 |
7 | grunt.initConfig({
8 | pkg: grunt.file.readJSON('package.json'),
9 | jshint: {
10 | files: [
11 | 'Gruntfile.js',
12 | 'jquery.scrolltab.js'
13 | ],
14 | options: {
15 | jshintrc: '.jshintrc'
16 | }
17 | },
18 | uglify: {
19 | options: {
20 | banner: '/*! <%= pkg.name %> v<%= pkg.version %> | <%= pkg.license %> | http://chris-saylor.com/Scrolltab */\n',
21 | compress: true
22 | },
23 | build: {
24 | files: {
25 | 'build/jquery.scrolltab-<%= pkg.version %>.min.js': 'jquery.scrolltab.js'
26 | }
27 | }
28 | },
29 | watch: {
30 | files: [
31 | 'jquery.scrolltab.js'
32 | ],
33 | tasks: 'default'
34 | },
35 | compare_size: {
36 | files: [
37 | 'build/jquery.scrolltab-<%= pkg.version %>.min.js',
38 | 'jquery.scrolltab.js'
39 | ],
40 | options: {
41 | compress: {
42 | gz: function (fileContents) {
43 | return require('gzip-js').zip(fileContents, {}).length;
44 | }
45 | }
46 | }
47 | }
48 | });
49 |
50 | grunt.loadNpmTasks('grunt-contrib-jshint');
51 | grunt.loadNpmTasks('grunt-contrib-uglify');
52 | grunt.loadNpmTasks('grunt-contrib-watch');
53 | grunt.loadNpmTasks('grunt-compare-size');
54 |
55 | grunt.registerTask('default', ['jshint', 'uglify', 'compare_size']);
56 | grunt.registerTask('ci', ['jshint']);
57 | };
58 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Scrolltab is a jQuery plugin that adds tabs visually associated to their position relative to the scroll bar.
2 |
3 | This enables a developer to attach floating tabs to the scrollbar of the brwoser that will scroll the user to the position indicated by the tab. This tab is expandable with content within.
4 |
5 | ## Demo
6 |
7 | http://chris-saylor.com/Scrolltab/example.html
8 |
9 | ## Install
10 |
11 | There are two ways of installing:
12 |
13 | 1. Bower - ```bower install jquery-scrolltab```
14 |
15 | 2. Download - You can install traditionally by downloading the [minified version](https://github.com/cjsaylor/Scrolltab/releases/latest).
16 |
17 | ## Options
18 |
19 | * `title`: HTML to display within the pin
20 | * `classname`: The classname for the pin to use
21 | * `mouseenter`: function to execute when the mouseenter event fires on this pin
22 | * `mouseleave`: function to execute when the mouseleave event fires on this pin
23 | * `click`: function to execute when the click event fire on this pin
24 |
25 | ## Setting Options via `data` attributes
26 |
27 | You can set the title and classname of the pin via data attributes on the object.
28 |
29 | ```html
30 |
31 | ```
32 |
33 | ## Behaviors
34 |
35 | The behavior of how the pin displays and hides is customizable by overriding the behavior functions.
36 |
37 | #### Initial Display
38 |
39 | When a new pin is created by the `.scrolltab()` call.
40 |
41 | * Default behavior: `fadeIn('slow')`
42 |
43 | ```
44 | $.fn.scrolltab.pinInitialDisplay
45 | ```
46 |
47 | #### Display On Update
48 |
49 | If the element the scrollpin was tracking becomes visible again, this will redisplay the pin.
50 |
51 | * Default behavior: `fadeIn('slow')`
52 |
53 | ```
54 | $.fn.scrolltab.pinDisplay
55 | ```
56 |
57 | #### Pin Hide
58 |
59 | If the element the scrollpin was tracking is hidden from the dom, this will hide the pin.
60 |
61 | * Default behavior: `fadeOut('fast')`
62 |
63 | ```
64 | $.fn.scrolltab.pinHide
65 | ```
66 |
67 | ## Examples
68 |
69 | ```javascript
70 | // Enables a pin with the default classname
71 | $('').scrolltab();
72 | ```
73 |
74 | ```javascript
75 | // Changes the classname of the created (or existing) pin
76 | $('').scrolltab({ classname: 'test' });
77 | ```
78 |
79 | ```javascript
80 | // Modifies the behavior of the click event on the pin
81 | $('').scrolltab();
96 | ```
97 |
98 | ```javascript
99 | // Modify the default attributes of all pins created now on
100 | // In this example, I want all pins to have a click event function
101 | // callback attached.
102 | $.fn.scrolltab.default = $.extend($.fn.scrolltab.default, {
103 | click: function (e) {
104 | e.preventDefault();
105 | alert('Pin clicked!');
106 | }
107 | });
108 | $('').scrolltab();
109 | ```
110 |
111 | ## Build
112 |
113 | Scrolltab uses [Grunt CLI](http://gruntjs.com/) via [NodeJS](http://nodejs.org/) for linting and building the minified production file.
114 |
115 | #### Setup
116 |
117 | Install grunt cli globally:
118 |
119 | ```bash
120 | $ npm install -g grunt-cli
121 | ```
122 |
123 | Install dev dependencies:
124 |
125 | ```bash
126 | $ npm install -d
127 | ```
128 |
129 | Execute lint and build:
130 |
131 | ```bash
132 | $ grunt
133 | ```
134 |
135 | ## License
136 |
137 | This software is protected under the MIT license.
138 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jquery-scrolltab",
3 | "version": "1.0.5",
4 | "homepage": "http://chris-saylor.com/Scrolltab/",
5 | "authors": [
6 | "Chris Saylor "
7 | ],
8 | "description": "jQuery plugin to add tabs visually associated to their position relative to the scroll bar.",
9 | "main": "jquery.scrolltab.js",
10 | "keywords": [
11 | "scroll",
12 | "scrollspy",
13 | "animation"
14 | ],
15 | "license": "MIT",
16 | "dependencies": {
17 | "jquery": ">= 1.7.1"
18 | },
19 | "ignore": [
20 | "**/.*",
21 | "node_modules",
22 | "bower_components",
23 | "test",
24 | "tests"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Scrolltab Demo
7 |
58 |
59 |
60 |
111 |
112 |
113 |
114 |
117 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
--------------------------------------------------------------------------------
/jquery.scrolltab.js:
--------------------------------------------------------------------------------
1 | /**
2 | * jQuery Scrolltab Plugin v1.0.5
3 | * https://github.com/cjsaylor/scrolltab
4 | *
5 | * Options
6 | * title: HTML to display within the pin.
7 | * classname: Choose the classname you want the pin to use.
8 | *
9 | * Supported events:
10 | * click, mouseenter, mouseleave
11 | *
12 | * This is a simple plugin that enables a developer to attach floating
13 | * tabs to the scrollbar of the browser that will scroll the user to
14 | * the position indicated by the tab. This tab is expandable with content
15 | * within.
16 | *
17 | * The pins react to changes in the pinned object, dom structure/size,
18 | * and the size of the window.
19 | *
20 | * ---------------------------------------------------------------------
21 | * Copyright (c) 2010 - 2014 Chris Saylor
22 | * Permission is hereby granted, free of charge, to any person obtaining a copy
23 | * of this software and associated documentation files (the "Software"), to deal
24 | * in the Software without restriction, including without limitation the rights
25 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
26 | * copies of the Software, and to permit persons to whom the Software is
27 | * furnished to do so, subject to the following conditions:
28 | *
29 | * The above copyright notice and this permission notice shall be included in
30 | * all copies or substantial portions of the Software.
31 | *
32 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
38 | * THE SOFTWARE.
39 | */
40 |
41 | (function (factory) {
42 | if (typeof define === 'function' && define.amd) {
43 | define(['jquery'], factory);
44 | } else {
45 | factory(jQuery);
46 | }
47 | }(function($) {
48 | $.fn.scrolltab = function(options) {
49 |
50 | var settings = $.extend({}, $.fn.scrolltab.defaults, options);
51 |
52 | var data = {
53 | body: 0,
54 | pinId: 1
55 | };
56 |
57 | return this.each(function() {
58 | var obj = $(this);
59 |
60 | // Detect if this object has already had a pin created
61 | if(!obj.data('scrolltab_enabled')) {
62 | initializePin.call(obj);
63 | } else {
64 | // The pin already exists, so lets select the existing pin.
65 | updateExistingPin.call(obj);
66 | }
67 | });
68 |
69 | /**
70 | * Create a pin associated with the subject object.
71 | *
72 | * @return void
73 | */
74 | function initializePin() {
75 | this.data('scrolltab_enabled', true);
76 | data.body = $('body').height();
77 |
78 | var id = 'scrolltab_' + data.pinId++;
79 |
80 | // Create the pin and position
81 | var pin = $('')
82 | .attr('id', id)
83 | .attr('class', this.data('st-classname') || settings.classname)
84 | .html(this.data('st-title') || settings.title)
85 | .css('position', 'fixed')
86 | .css('right', 0)
87 | .bind('mouseenter.scrolltab', settings.mouseenter)
88 | .bind('mouseleave.scrolltab', settings.mouseleave)
89 | .bind('click.scrolltab', settings.click);
90 |
91 | this.data('scrolltab_id', id);
92 |
93 | // Append to dom so we can calculate object height.
94 | $('body').append(pin);
95 |
96 | // Calculate scroll bar position for this element
97 | var pos = calc.call(this, pin);
98 |
99 | // Attach click action (scroll)
100 | pin.css('top', pos)
101 | .hide()
102 | .bind('click.scrolltab', function(e) {
103 | e.preventDefault();
104 | $('html,body').animate({scrollTop: this.offset().top+"px"}, 1000);
105 | }.bind(this))
106 | .css('cursor', 'pointer');
107 |
108 | $.fn.scrolltab.pinInitialDisplay.call(this, pin);
109 |
110 | // Update pin status (if applicable) every second.
111 | setInterval(function() {
112 | update.call(this, pin);
113 | }.bind(this), 1000);
114 | }
115 |
116 | /**
117 | * Update a pin via the pin's subject.
118 | *
119 | * @param object obj
120 | * @return void
121 | */
122 | function updateExistingPin() {
123 | var pin = $('#' + this.data('scrolltab_id'));
124 |
125 | // Only remap what has been set in the options.
126 | if(options.mouseenter) {
127 | pin.unbind('mouseenter.scrolltab').on('mouseenter.scrolltab', options.mouseenter);
128 | }
129 | if(options.mouseleave) {
130 | pin.unbind('mouseleave.scrolltab').on('mouseleave.scrolltab', options.mouseleave);
131 | }
132 | if(options.click) {
133 | pin.unbind('click.scrolltab').on('click.scrolltab', options.click);
134 | }
135 | if(options.classname) {
136 | pin.attr('class', options.classname);
137 | }
138 | if(options.title) {
139 | pin.html(options.title);
140 | }
141 | }
142 |
143 |
144 | /**
145 | * Updates the positions of each scroll pin. If the object of the scroll
146 | * pin is no longer within the visible dom, the corresponding pin is removed.
147 | *
148 | * If the window size is greater than that of the body, hide all pins.
149 | *
150 | * @param jQuery pin - Pin object
151 | * @return void
152 | */
153 | function update(pin) {
154 | if(this.parents().length === 0) {
155 | setTimeout(function() { pin.remove(); }, 1000);
156 | } else if(this.css('display') === 'none') {
157 | $.fn.scrolltab.pinHide.call(this, pin);
158 | } else {
159 | setTimeout(function() {
160 | pin.animate({top: calc.call(this, pin)});
161 | }.bind(this), 1000);
162 | }
163 |
164 | if(!isPinable()) {
165 | $.fn.scrolltab.pinHide.call(this, pin);
166 | } else if(isPinable() && this.css('display') !== 'none') {
167 | $.fn.scrolltab.pinDisplay.call(this, pin);
168 | }
169 | }
170 |
171 | /**
172 | * Calculates the vertical position of the main object to pin for scrolling.
173 | *
174 | * @param jQuery pin - Pin object
175 | * @return float Vertical position result
176 | */
177 | function calc(pin) {
178 | return parseInt(
179 | this.offset().top / $('body').height() * $(window).height() + (pin.height() / 2),
180 | 10
181 | );
182 | }
183 |
184 | /**
185 | * Returns true if the any of the pins should be showing
186 | *
187 | * @return boolean
188 | */
189 | function isPinable() {
190 | return $('body').height() > $(window).height();
191 | }
192 |
193 | };
194 |
195 | /**
196 | * Exposed default options.
197 | *
198 | * @type Object
199 | */
200 | $.fn.scrolltab.defaults = {
201 | title: '',
202 | classname: 'scrolltab-item',
203 | mouseenter: function(){},
204 | mouseleave: function(){},
205 | click: function(){}
206 | };
207 |
208 | /**
209 | * Behavior when a pin needs to be displayed.
210 | *
211 | * This is both the initial display and pin display on update.
212 | *
213 | * @param Object pin jQuery object pin
214 | * @return void
215 | */
216 | $.fn.scrolltab.pinInitialDisplay = $.fn.scrolltab.pinDisplay = function (pin) {
217 | pin.fadeIn('slow');
218 | };
219 |
220 | /**
221 | * Behavior when a pin needs to be hidden.
222 | *
223 | * @param object pin jQuery object pin
224 | * @return void
225 | */
226 | $.fn.scrolltab.pinHide = function (pin) {
227 | pin.fadeOut('fast');
228 | };
229 | }));
230 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jquery.scrolltab",
3 | "version": "1.0.5",
4 | "description": "jQuery plugin to add tabs visually associated to their position relative to the scroll bar.",
5 | "main": "Gruntfile.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "git://github.com/cjsaylor/scrolltab.git"
9 | },
10 | "author": "Chris Saylor",
11 | "license": "MIT",
12 | "readmeFilename": "README.md",
13 | "devDependencies": {
14 | "grunt": "~0.4.0",
15 | "grunt-contrib-jshint": "~0.4.0",
16 | "grunt-contrib-uglify": "~0.2.0",
17 | "grunt-contrib-watch": "~0.3.0",
18 | "grunt-compare-size": "~0.4.0",
19 | "gzip-js": "~0.3.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/scrolltab.jquery.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "scrolltab",
3 | "title": "Scrolltab",
4 | "description": "A jQuery plugin that adds tabs for elements visually associated to their position relative to the scroll bar",
5 | "keywords": [
6 | "scroll",
7 | "scrollspy",
8 | "animation"
9 | ],
10 | "version": "1.0.5",
11 | "author": {
12 | "name": "Chris Saylor",
13 | "url": "http://chris-saylor.com"
14 | },
15 | "licenses": [
16 | {
17 | "type": "MIT",
18 | "url": "https://github.com/cjsaylor/scrolltab/blob/master/README.md"
19 | }
20 | ],
21 | "homepage": "http://chris-saylor.com/Scrolltab/",
22 | "demo": "http://chris-saylor.com/Scrolltab/example.html",
23 | "dependencies": {
24 | "jquery": ">=1.7"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------