Skip to content

Commit

Permalink
Initial version (0.1.0).
Browse files Browse the repository at this point in the history
  • Loading branch information
iclanzan committed Jan 31, 2014
1 parent a613f11 commit c75351e
Show file tree
Hide file tree
Showing 16 changed files with 786 additions and 3 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
bower_components
14 changes: 14 additions & 0 deletions .jshintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"curly": true,
"eqeqeq": true,
"immed": true,
"latedef": true,
"newcap": true,
"noarg": true,
"sub": true,
"undef": true,
"unused": true,
"boss": true,
"eqnull": true,
"node": true
}
32 changes: 32 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Contributing #

## Important notes ##
Please don’t edit files in the `dist` subdirectory as they are generated via Gulp. You’ll find source code in the `src` subdirectory!

### Code style ###
Regarding code style like indentation and whitespace, **follow the conventions you see used in the source already.**

### PhantomJS ###
While Gulp can run the included unit tests via [PhantomJS](http://phantomjs.org/), this shouldn’t be considered a substitute for the real thing. Please be sure to test the `test/*.html` unit test file(s) in _actual_ browsers.

## Modifying the code ##
First, ensure that you have the latest [Node.js](http://nodejs.org/) and [npm](http://npmjs.org/) installed.

Test that Gulp and Bower are installed by running `gulp --version` and `bower --version`. If the commands aren’t found, run `npm install -g gulp bower`. For more information about installing the tools, see [gulpjs.com](http://gulpjs.com/) or [bower.io](http://bower.io/) respectively.

1. Fork and clone the repo.
2. Run `npm install` to install all build dependencies.
3. Run `bower install` to install the front-end dependencies.
4. Run `gulp` to build this project.

Assuming that you don’t see any errors, you’re ready to go. Just be sure to run `gulp` after making any changes, to ensure that nothing is broken.

## Submitting pull requests ##

1. Create a new branch, please don’t work in your `master` branch directly.
2. Add failing tests for the change you want to make. Run `gulp` to see the tests fail.
3. Fix stuff.
4. Run `gulp` to see if the tests pass. Repeat steps 2-4 until done.
5. Open `test/*.html` unit test file(s) in actual browser to ensure tests pass everywhere.
6. Update the documentation to reflect any changes.
7. Push to your fork and submit a pull request.
58 changes: 55 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,56 @@
slinky
======
# Slinky.js - Scrolling navigation component for web apps #

Scrolling navigation component for web apps
Create beautiful navigation lists with stacking headers that are visible at all times.

_Slinky is currently implemented as a jQuery plugin but if there is enough demand I might write a standalone version too._

## Getting Started ##

Download the [production version][min] or the [development version][max] and include it after jQuery. Then just call `$('.nav').slinky()` for example to enable Slinky on all elements with a `nav` class.

[min]: https://raw.github.com/iclanzan/slinky/master/dist/jquery.slinky.min.js
[max]: https://raw.github.com/iclanzan/slinky/master/dist/jquery.slinky.js

### Example ###

A minimal HTML structure for Slinky to work with can look something like this:

```html
<div class="nav">
<div class="scroller">
<section>
<header>First Header</header>
<ul>
<li>item</li>
<li>item</li>
</ul>
</section>
<section>
<header>Second Header</header>
<p>Some content</p>
</section>
<!-- more sections here -->
</div>
</div>
```

And the accompanying CSS:

```CSS
.nav {
position: relative;
height: 400px;
overflow: hidden;
}

.scroller {
height: 100%;
overflow: auto;
}
```

Slinky doesn’t make any assumptions about the tags and classes you are using but it does expect to find an element with hidden overflow wrapped around a scrollable element. Inside of it content should be split into sections. The first child of each section is considered to be the header.

## Release History ##

+ **v0.1.0 (2014-01-31)** Initial version
9 changes: 9 additions & 0 deletions bower.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "slinky",
"version": "0.1.0",
"dependencies": {},
"devDependencies": {
"qunit": "~1.13.0",
"jquery": ">=1.7.1"
}
}
128 changes: 128 additions & 0 deletions dist/jquery.slinky.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* Slinky.js v0.1.0
*
* Copyright (c) 2014 Sorin Iclanzan
* Licensed under the MIT license.
*/

(function ($, window, undefined) {
'use strict';

var pluginName = 'slinky';

var slinky = $.fn[pluginName] = function (options) {
options = $.extend({}, slinky.options, options);

return this.each(function () {
var $element = $(this);
// Prevent multiple instantiations on the same element.
if ($element.data(pluginName)) {
return;
}
$element.data(pluginName, true);


var $scroller = $element.children().first();
var $sections, headers, scrollerHeight, timer;

function refresh() {
headers.forEach(function (header) {
var position = '';
var top = header.$parent.position().top;

if (top < header.top) {
position = 'top';
}
else if (top + header.height > scrollerHeight - header.bottom) {
position = 'bottom';
}

if (position) {
// Don’t do anything if the header is already positioned properly.
if (header.position != position) {
header.$parent.css('paddingTop', header.height);
header.$
.css('position', 'absolute')
.css(position, header[position])
.css(position == 'top' ? 'bottom' : 'top', '');
header.position = position;
}
}
else {
header.$parent.css('paddingTop', '');
header.$.css('position', '');
header.position = '';
}
});
}

function init() {
scrollerHeight = $scroller.outerHeight();
headers = [];
$sections = $scroller.children();
$sections.each(function () {
var $section = $(this);
var $header = $section.children().first();
headers.push({
$: $header,
$parent: $section,
height: $header.outerHeight(),
position: '' // can be 'top' or 'bottom'
});
});

// Pre-calculate the offsets that the headers would have
// from the top or bottom of the scroller.
headers.forEach(function (header, i) {
header.top = i > 0 ? (headers[i - 1].top + headers[i - 1].height) : 0;

i = headers.length - i - 1;
headers[i].bottom = i < headers.length - 1 ? (headers[i + 1].bottom + headers[i + 1].height) : 0;
});

refresh();
}

function enablePointerEvents() {
$sections.css('pointer-events', '');
timer = undefined;
}

init();

$scroller

.on('wheel.' + pluginName, function () {
if (timer) {
clearTimeout(timer);
}
else {
$sections.css('pointer-events', 'none');
}
timer = setTimeout(enablePointerEvents, 100);
})

.on('scroll.' + pluginName, refresh);

// On window resize we need to recalculate everything in case relative
// units where used anywhere.
$(window).on('resize.' + pluginName, init);

var MutationObserver = MutationObserver || window.WebKitMutationObserver;
if (MutationObserver) {
var observer = new MutationObserver(init);
observer.observe($scroller[0], {
childList: true, characterData: true, subtree: true
});
}

$element.on('remove.' + pluginName, function () {
$scroller.off('wheel.' + pluginName + ' scroll.' + pluginName);
$(window).off('resize.' + pluginName, init);
if (observer) {
observer.disconnect();
}
});
});
};
}(jQuery, window));
1 change: 1 addition & 0 deletions dist/jquery.slinky.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 42 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use strict';

var gulp = require('gulp');
var clean = require('gulp-clean');
var rename = require('gulp-rename');
var jshint = require('gulp-jshint');
var template = require('gulp-template');
var concat = require('gulp-concat');
var qunit = require('gulp-qunit');
var uglify = require('gulp-uglify');
var notify = require('gulp-notify');

var pkg = require('./package.json');

gulp.task('clean', function () {
return gulp.src('dist/', {read: false})
.pipe(clean());
});

gulp.task('test', function () {
gulp.src('test/slinky.html')
.pipe(qunit());
});

gulp.task('build', ['clean'], function (){
return gulp.src('src/*.js')
.pipe(jshint('src/.jshintrc'))
.pipe(jshint.reporter('default'))
.pipe(template(pkg))
.pipe(concat('jquery.slinky.js'))
.pipe(gulp.dest('dist'))
.pipe(rename('jquery.slinky.min.js'))
.pipe(uglify())
.pipe(gulp.dest('dist'))
.pipe(notify({ message: 'Slinky build was successful!' }));
});

gulp.task('watch', function () {
gulp.watch('src/*.js', ['default']);
});

gulp.task('default', ['build', 'test']);
36 changes: 36 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "slinky",
"version": "0.1.0",
"description": "Scrolling navigation component for web apps.",
"title": "Slinky.js",
"keywords": [
"jquery-plugin"
],
"homepage": "https://github.com/iclanzan/slinky",
"bugs": "https://github.com/iclanzan/slinky/issues",
"author": {
"name": "Sorin Iclanzan",
"email": "[email protected]",
"url": "https://github.com/iclanzan"
},
"repository": {
"type": "git",
"url": "https://github.com/iclanzan/slinky.git"
},
"licenses": [
{
"type": "MIT"
}
],
"devDependencies": {
"gulp": "~3.5.0",
"gulp-uglify": "~0.2.0",
"gulp-notify": "~0.4.0",
"gulp-clean": "~0.2.4",
"gulp-qunit": "git+ssh://[email protected]/jonkemp/gulp-qunit.git",
"gulp-jshint": "~1.3.4",
"gulp-rename": "~0.2.2",
"gulp-concat": "~2.1.7",
"gulp-template": "~0.1.1"
}
}
32 changes: 32 additions & 0 deletions slinky.jquery.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "slinky",
"title": "Slinky.js",
"description": "Scrolling navigation component for web apps.",
"version": "0.1.0",
"homepage": "https://github.com/iclanzan/slinky",
"author": {
"name": "Sorin Iclanzan",
"url": "https://github.com/iclanzan"
},
"repository": {
"type": "git",
"url": "https://github.com/iclanzan/slinky.git"
},
"bugs": "https://github.com/iclanzan/slinky/issues",
"licenses": [
{
"type": "MIT",
"url": "http://opensource.org/licenses/MIT"
}
],
"dependencies": {
"jquery": ">=1.7.1"
},
"keywords": [
"jquery-plugin",
"navigation",
"menu",
"accordion",
"ui"
]
}
14 changes: 14 additions & 0 deletions src/.jshintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"curly": true,
"immed": true,
"latedef": true,
"newcap": true,
"noarg": true,
"sub": true,
"undef": true,
"unused": true,
"boss": true,
"eqnull": true,
"browser": true,
"predef": ["jQuery"]
}
Loading

0 comments on commit c75351e

Please sign in to comment.