Skip to content

Commit

Permalink
Initial public commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ejb committed Apr 19, 2016
0 parents commit 8045a25
Show file tree
Hide file tree
Showing 9 changed files with 1,020 additions and 0 deletions.
13 changes: 13 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Copyright (c) 2016 Dow Jones & Company

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
115 changes: 115 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# scrollWatcher 📜👀

A small JavaScript library for scroll-based data-driven graphics (without any nasty [scrolljacking](http://blog.arronhunt.com/post/66973746030/stop-scrolljacking)). scrollWatcher sticks an element at a fixed position onscreen, and then provides the distance scrolled through its (much taller) parent as a percentage.

- [Demo here](http://wsj.github.io/scroll-watcher/)

As seen on WSJ.com in [How Fed Rates Move Markets](http://graphics.wsj.com/reacting-to-fed-rates/) and [What ECB Stimulus Has Done](http://graphics.wsj.com/what-ecb-qe-stimulus-has-done/).

## Is scrollWatcher the right library for you?

- Want something to always stick on the page? Use [CSS `position: fixed;`](https://css-tricks.com/almanac/properties/p/position/#article-header-id-2).
- Want something to stick when you scroll past it? Use [jQuery fixto plugin](https://github.com/bbarakaci/fixto) or [jQuery Sticky](https://github.com/garand/sticky).
- Want a sticky header that hides on scroll? Use [headroom.js](http://wicky.nillia.ms/headroom.js/).
- Want to trigger events on scroll? Use [Waypoints](http://imakewebthings.com/waypoints/).
- **If you want to use scroll as a way of interacting with a data-driven graphic without scrolljacking, use scrollWatcher.**

## Quickstart

1. Include [jQuery](http://jquery.com) and the sticky-positioning [fixto plugin](https://github.com/bbarakaci/fixto) on the page.

2. In your HTML, you'll need a tall outer element, with one much shorter element inside of it.

```html
<div class="outer" style="height: 2000px;"></div>
<div class="inner"></div>
</div>
```

3. In your JavaScript, you'll need to call `scrollWatcher` with a configuration object using `parent` and `onUpdate` arguments. The function passed into `onUpdate` will run every 20 miliseconds.

```js
scrollWatcher({
parent: '.outer',
onUpdate: function( scrollPercent, parentElement ){
$('.inner').text('Scrolled '+scrollPercent+'% through the parent.');
}
});
```

## Examples

Check out the source code to see how these are used.

- [Basic demo](http://wsj.github.io/scroll-watcher/)
- [Using a D3 scale](http://wsj.github.io/scroll-watcher/examples/d3-scale.html)
- [Using a D3 time scale](http://wsj.github.io/scroll-watcher/examples/d3-scale-time.html)
- [Checking if the user has got there yet](http://wsj.github.io/scroll-watcher/examples/active.html)

## Other features

### Starting and stopping

If you create a new instance of scrollWatcher:

```js
var myWatcher = scrollWatcher({
onUpdate: function( scrollPercent, parentElement ){
console.log('Scrolled '+scrollPercent+'% through the parent.');
},
parent: '.outer'
});
```

... you can then start, pause and stop at any time.

```js
// stop checking but keep stuck
myWatcher.pause();

// stop checking and unstick
myWatcher.stop();

// start checking and restick
myWatcher.start();
```

### Check if active

There are two read-only properties:

- `active` is true when the scrollWatcher instance is currently onscreen (and running).

```js
var isActive = myWatcher.active;
```

- `hasBeenActive` is true when the scrollWatcher instance has been onscreen (and run) at least once.

```js
var isOrWasActive = myWatcher.hasBeenActive;
```

You may want to use these to (for example) hide a "keep scrolling!" message.

### Check for device support

Use `scrollWatcher.supported()` to check whether or not scrollWatcher will work in the current browser.

## Browser support

scrollWatcher works on all modern browsers, including IE 9 and up. However, **it does not work on iOS 7 and lower** due to the way Safari handles CSS `position: fixed;`.

## Testing

To run tests, open [`tests.html`](http://github.com/wsj/scroll-watcher/tests.html) in your browser and wait a couple of seconds.

## Version history

**v1.0.0** (April 19, 2016)

- Initial public release

## License

[ISC](/LICENSE)
117 changes: 117 additions & 0 deletions examples/active.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<style>
.outer, .outer2 {
height: 2000px;
position: relative;
border: 1px solid skyblue;
}
.inner {
font-size: 100px;
width: 100%;
border: 1px solid pink;
}
.meter {
height: 20px;
width: 0;
background: blue;
margin: 20px 0;
}
.stuck{
position:fixed;
top:0;
}

.scroll-status {
position: fixed;
top: 30%;
right: 0;
background: #eee;
border: 1px solid black;
padding: 10px;
font-size: 30px;
}

.status2 {
top: 40%;
background-color: #D9B4B5;
font-size: 20px;
}

.status3 {
top: 45%;
background-color: #D9B4B5;
font-size: 20px;
}

.scroll-status.true {
background-color: #CCE4D5;
}


.spacer {
height: 800px;
background: #f9f9f9;
}

</style>

<p>This is a demo page for <a href="http://github.com/wsj/scroll-watcher/">scrollWatcher</a>.</p>

<p>This shows how to use the active and hasBeenActive features of scrollWatcher.

<div class="spacer"></div>

<div class="outer">
<div class="inner">
<div class="text"></div>
<div class="meter"></div>
</div>
</div>

<div class="scroll-status status1">
Loading...
</div>
<div class="scroll-status status2">
Loading...
</div>
<div class="scroll-status status3">
Loading...
</div>

<script src="https://code.jquery.com/jquery-latest.min.js"></script>
<script src="https://rawgit.com/bbarakaci/fixto/master/dist/fixto.min.js"></script>
<script src="../scroll-watcher.js"></script>

<script type="text/javascript">

var onUpdate = function( scroll, $parent ){
$parent.find('.text').text( scroll.toFixed(2) );
$parent.find('.meter').width( scroll + '%' );

// user-friendly message
if ( myWatcher.hasBeenActive ) {
$('.status1').text('Cool, you know what to do now.')
} else {
$('.status1').text('Hey user, try scrolling.')
}

// debug to show how the variables work
if ( myWatcher.hasBeenActive ) {
$('.status2').addClass('true').text('hasBeenActive is true')
} else {
$('.status2').removeClass('true').text('hasBeenActive is false')
}
if ( myWatcher.active ) {
$('.status3').addClass('true').text('active is true')
} else {
$('.status3').removeClass('true').text('active is false')
}
}

var myWatcher = scrollWatcher({
onUpdate: onUpdate,
parent: '.outer'
});

</script>
75 changes: 75 additions & 0 deletions examples/d3-scale-time.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<style>
.outer, .outer2 {
height: 2000px;
position: relative;
border: 1px solid skyblue;
}
.inner {
font-size: 100px;
width: 100%;
border: 1px solid pink;
}
.meter {
height: 20px;
width: 0;
background: blue;
margin: 20px 0;
}
.stuck{
position:fixed;
top:0;
}


</style>

<p>This is a demo page for <a href="http://github.com/wsj/scroll-watcher/">scrollWatcher</a>.</p>
<p>In this example, we are using D3 to convert between the percentage-scrolled and a time scale.</p>
<p>So instead of going from 0 to 100, it goes from Jan. 1 to Dec. 31.</p>


<div class="outer">
<div class="inner">
<div class="text"></div>
<div class="meter"></div>
</div>
</div>

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.11/d3.min.js"></script>
<script src="https://code.jquery.com/jquery-latest.min.js"></script>
<script src="https://rawgit.com/bbarakaci/fixto/master/dist/fixto.min.js"></script>
<script src="../scroll-watcher.js"></script>

<script type="text/javascript">

// create a normal D3 time parser
var dateFormat = d3.time.format("%Y-%m-%d");

// create date objects for our start and end
var dateRange = [
dateFormat.parse('2015-01-01'),
dateFormat.parse('2015-12-31')
];

// create D3 time scale using dateRange
var scale = d3.time.scale()
.domain([0,100])
.range(dateRange);

var onUpdate = function( scroll, $parent ){
// map the percentage scrolled to our time scale
var scaled = scale(scroll);
// format it as a human-readable date
var formatted = dateFormat(new Date(scaled));
$parent.find('.text').text( formatted );
$parent.find('.meter').width( scroll + '%' );
}

scrollWatcher({
onUpdate: onUpdate,
parent: '.outer'
});

</script>
64 changes: 64 additions & 0 deletions examples/d3-scale.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<style>
.outer, .outer2 {
height: 2000px;
position: relative;
border: 1px solid skyblue;
}
.inner {
font-size: 100px;
width: 100%;
border: 1px solid pink;
}
.meter {
height: 20px;
width: 0;
background: blue;
margin: 20px 0;
}
.stuck{
position:fixed;
top:0;
}


</style>

<p>This is a demo page for <a href="http://github.com/wsj/scroll-watcher/">scrollWatcher</a>.</p>
<p>In this example, we are using D3 to convert between the percentage-scrolled and another (arbitrary) scale.</p>
<p>So instead of going from 0 to 100, it goes from -860 to 4200.</p>


<div class="outer">
<div class="inner">
<div class="text"></div>
<div class="meter"></div>
</div>
</div>

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.11/d3.min.js"></script>
<script src="https://code.jquery.com/jquery-latest.min.js"></script>
<script src="https://rawgit.com/bbarakaci/fixto/master/dist/fixto.min.js"></script>
<script src="../scroll-watcher.js"></script>

<script type="text/javascript">

// create D3 scale, using rangeRound to ensure rounded numbers are produced
var scale = d3.scale.linear()
.domain([0,100])
.rangeRound([-860,4200]);

var onUpdate = function( scroll, $parent ){
// map the percentage scrolled to our crazy scale
var scaled = scale(scroll);
$parent.find('.text').text( scaled );
$parent.find('.meter').width( scroll + '%' );
}

scrollWatcher({
onUpdate: onUpdate,
parent: '.outer'
});

</script>
Loading

0 comments on commit 8045a25

Please sign in to comment.