Skip to content

Commit

Permalink
Align with Ember's HistoryLocation router
Browse files Browse the repository at this point in the history
  • Loading branch information
bcardarella authored and briangonzalez committed Jan 25, 2017
1 parent 3d0cd5b commit 605d9ea
Show file tree
Hide file tree
Showing 6 changed files with 6,106 additions and 51 deletions.
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
# Ember-router-scroll
# ember-router-scroll

[![Build Status](https://travis-ci.org/dollarshaveclub/ember-router-scroll.svg?branch=master)](https://travis-ci.org/dollarshaveclub/ember-router-scroll)

> Scroll to page top on transition, like a non-SPA website. An alternative scroll behavior for Ember applications.
## Installation

```
ember install ember-router-scroll
```

Scroll to page top on transition, like a non-SPA website. An alternative scroll behavior for Ember applications.
## Demo
See [demo](https://dollarshaveclub.github.io/router-scroll-demo/) made by [@Chuabacca](https://github.com/Chuabacca/)

Expand Down
20 changes: 10 additions & 10 deletions addon/locations/router-scroll.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import Ember from 'ember';

const uuid = () => 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : r & 3 | 8;
return v.toString(16);
});

const {
get,
HistoryLocation,
} = Ember;

export default HistoryLocation.extend({
init(...args) {
this._super(...args);
this.stateCounter = 0;
},
pushState(path) {
const id = `${this.stateCounter++}`;
const state = { path, id };
const state = { path, uuid: uuid() };
get(this, 'history').pushState(state, null, path);
this._previousURL = this.getURL(); // eslint-disable-line no-underscore-dangle
this.previousURL = this.getURL();
},
replaceState(path) {
const id = `${this.stateCounter++}`;
const state = { path, id };
const state = { path, uuid: uuid() };
get(this, 'history').replaceState(state, null, path);
this._previousURL = this.getURL(); // eslint-disable-line no-underscore-dangle
this.previousURL = this.getURL();
},
});
6 changes: 3 additions & 3 deletions addon/services/router-scroll.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ export default Service.extend({

position: computed(function position() {
const scrollMap = get(this, 'scrollMap');
const stateId = get(window, 'history.state.id');
const stateUuid = get(window, 'history.state.uuid');

set(this, 'key', stateId);
const key = get(this, 'key') || '-1';
set(this, 'key', stateUuid);
const key = getWithDefault(this, 'key', '-1');

return getWithDefault(scrollMap, key, { x: 0, y: 0 });
}).volatile(),
Expand Down
17 changes: 8 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ember-router-scroll",
"version": "0.0.7",
"version": "0.1.0",
"description": "Scroll to top with preserved browser history scroll position",
"directories": {
"doc": "doc",
Expand All @@ -9,7 +9,6 @@
"scripts": {
"build": "ember build",
"eslint": "eslint app/**/*.js addon/**/*.js tests/**/*.js --quiet --ignore-path .eslintignore",
"prepublish": "npm test",
"start": "ember server",
"test": "ember try:each"
},
Expand Down Expand Up @@ -51,32 +50,31 @@
},
{
"name": "Brian Gonzalez",
"url": "https://twitter.com/brianmgonzalez"
"url": "https://github.com/briangonzalez"
}
],
"license": "MIT",
"devDependencies": {
"broccoli-asset-rev": "^2.4.2",
"ember-ajax": "^2.0.1",
"ember-cli": "2.6.2",
"ember-cli": "2.11.0",
"ember-cli-app-version": "^1.0.0",
"ember-cli-dependency-checker": "^1.2.0",
"ember-cli-htmlbars": "^1.0.3",
"ember-cli-htmlbars-inline-precompile": "^0.3.1",
"ember-cli-inject-live-reload": "^1.4.0",
"ember-cli-jshint": "^1.0.0",
"ember-cli-qunit": "^1.4.0",
"ember-cli-release": "^0.2.9",
"ember-cli-release": "^1.0.0-beta.2",
"ember-cli-sri": "^2.1.0",
"ember-cli-uglify": "^1.2.0",
"ember-data": "^2.6.0",
"ember-disable-prototype-extensions": "^1.1.0",
"ember-export-application-global": "^1.0.5",
"ember-getowner-polyfill": "1.0.1",
"ember-load-initializers": "^0.5.1",
"ember-resolver": "^2.0.3",
"ember-welcome-page": "^1.0.1",
"eslint": "^2.4.0",
"ember-welcome-page": "^2.0.3",
"eslint": "^3.14.0",
"eslint-config-airbnb": "^6.1.0",
"eslint-plugin-dollarshaveclub": "^1.0.0",
"loader.js": "^4.0.1",
Expand All @@ -89,10 +87,11 @@
"browser scroll"
],
"dependencies": {
"ember-getowner-polyfill": "1.0.1",
"ember-cli-babel": "^5.1.6"
},
"ember-addon": {
"configPath": "tests/dummy/config",
"demoURL": "https://dollarshaveclub.github.io/router-scroll-demo/"
"demoURL": "https://dollarshaveclub.github.io/router-scroll-demo/"
}
}
53 changes: 26 additions & 27 deletions tests/unit/services/router-scroll-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,61 +3,60 @@ import { moduleFor, test } from 'ember-qunit';

const {
get,
set
set,
} = Ember;

moduleFor('service:router-scroll', {
// Specify the other units that are required for this test.
// needs: ['service:foo']
});
moduleFor('service:router-scroll');

// Replace this with your real tests.
test('it inits `scrollMap` and `key`', function(assert) {
let service = this.subject();
test('it inits `scrollMap` and `key`', function init(assert) {
const service = this.subject();
assert.deepEqual(get(service, 'scrollMap'), {});
assert.deepEqual(get(service, 'key'), null);
});

test('updating will set `scrollMap` to the current scroll position', function(assert) {
let service = this.subject();
test('updating will set `scrollMap` to the current scroll position', function scrollMap(assert) {
const service = this.subject();

let expected = { x: window.scrollX, y: window.scrollY };
const expected = { x: window.scrollX, y: window.scrollY };
set(service, 'key', '123');
service.update();
assert.deepEqual(get(service, 'scrollMap'), { '123': expected });
assert.deepEqual(get(service, 'scrollMap'), { 123: expected });
});

test('updating will not set `scrollMap` to the current scroll position if `key` is not yet set', function(assert) {
let service = this.subject();
test('updating will not set `scrollMap` to the current scroll position if `key` is not yet set',
function scrollMapCurrentPos(assert) {
const service = this.subject();

service.update();
assert.deepEqual(get(service, 'scrollMap'), { });
});

test('computing the position for an existing state id return the coords', function(assert) {
let service = this.subject();
let state = window.history.state;
window.history.replaceState({id: '123'}, null);
test('computing the position for an existing state uuid return the coords',
function existingUUID(assert) {
const service = this.subject();
window.history.replaceState({ uuid: '123' }, null);

let expected = { x: 1, y: 1 };
const expected = { x: 1, y: 1 };
set(service, 'scrollMap.123', expected);
assert.deepEqual(get(service, 'position'), expected);
window.history.replaceState(state, null);
});

test('computing the position for a state without a cached scroll position returns default', function(assert) {
let service = this.subject();
let state = window.history.state;
window.history.replaceState({id: '123'}, null);
test('computing the position for a state without a cached scroll position returns default',
function cachedScroll(assert) {
const service = this.subject();
const state = window.history.state;
window.history.replaceState({ uuid: '123' }, null);

let expected = { x: 0, y: 0 };
const expected = { x: 0, y: 0 };
assert.deepEqual(get(service, 'position'), expected);
window.history.replaceState(state, null);
});

test('computing the position for a non-existing state returns default', function(assert) {
let service = this.subject();
test('computing the position for a non-existant state returns default',
function nonExistantState(assert) {
const service = this.subject();

let expected = { x: 0, y: 0 };
const expected = { x: 0, y: 0 };
assert.deepEqual(get(service, 'position'), expected);
});
Loading

0 comments on commit 605d9ea

Please sign in to comment.