Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ES6-ification #21

Merged
merged 3 commits into from
May 21, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ indent_style = space
indent_size = 2

[*.hbs]
insert_final_newline = false
indent_style = space
indent_size = 2

Expand Down
2 changes: 2 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
bower_components/
tests/
tmp/
dist/

.bowerrc
.editorconfig
Expand Down
18 changes: 17 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
---
language: node_js
node_js:
- "0.12"

sudo: false

cache:
directories:
- node_modules

env:
- EMBER_TRY_SCENARIO=default
- EMBER_TRY_SCENARIO=ember-1.10
- EMBER_TRY_SCENARIO=ember-1.11
- EMBER_TRY_SCENARIO=ember-release
- EMBER_TRY_SCENARIO=ember-beta
- EMBER_TRY_SCENARIO=ember-canary

matrix:
fast_finish: true
allow_failures:
- env: EMBER_TRY_SCENARIO=ember-canary

before_install:
- export PATH=/usr/local/phantomjs-2.0.0/bin:$PATH
- "npm config set spin false"
- "npm install -g npm@^2"

Expand All @@ -17,4 +33,4 @@ install:
- bower install

script:
- npm test
- ember try $EMBER_TRY_SCENARIO test
63 changes: 56 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,67 @@ Now, whenever the `infinity-loader` is in view, it will send an action to the ro

When the new records are loaded, they will automatically be pushed into the Model array.

#### JSON Response
## Advanced Usage

### JSON Request/Response Customization

By default, ember-infinity will send pagination parameters as part of a GET request as follows

````
/items?per_page=5&page=1
````

The response provided by your server should include the number of total pages.
and will expect to recieve metadata in the response payload via a `total_pages` param in a `meta` object

```json
{ "meta": { "total_pages": 4 } }
```js
{
items: [
{id: 1, name: 'Test'},
{id: 2, name: 'Test 2'}
],
meta: {
total_pages: 3
}
}
```

If your query returns 20 objects, and you're showing 6 per page, then the
number of total pages would be 4.
If you wish to customize some aspects of the JSON contract for pagination, you may do so via your routes. For example:

## Advanced Usage
```js
import Ember from 'ember';
import InfinityRoute from "ember-infinity/mixins/route";

export default Ember.Route.extend(InfinityRoute, {

perPageParam: "per", // instead of "per_page"
pageParam: "pg", // instead of "page"
totalPagesParam: "meta.total", // instead of "meta.total_pages"

model() {
/* Load pages of the Product Model, starting from page 1, in groups of 12. */
return this.infinityModel("product", { perPage: 12, startingPage: 1 });
}
});
```

This will result in request query params being sent out as follows

````
/items?per=5&pg=1
````

and ember-infinity will be set up to parse the total number of pages from a JSON response like this:

```js
{
items: [
...
],
meta: {
total: 3
}
}
```

### infinityModel

Expand Down
31 changes: 17 additions & 14 deletions addon/components/infinity-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,43 +14,44 @@ export default Ember.Component.extend({
developmentMode: false,
scrollable: null,

didInsertElement: function() {
didInsertElement() {
this._super(...arguments);
this._setupScrollable();
this.set('guid', Ember.guidFor(this));
this._bindScroll();
this._checkIfInView();
},

willDestroyElement: function() {
willDestroyElement() {
this._super(...arguments);
this._unbindScroll();
},

_bindScroll: function() {
var _this = this;
this.get("scrollable").on("scroll."+this.get('guid'), function() {
Ember.run.debounce(_this, _this._checkIfInView, _this.get('scrollDebounce'));
_bindScroll() {
this.get("scrollable").on(`scroll.${this.get('guid')}`, () => {
Ember.run.debounce(this, this._checkIfInView, this.get('scrollDebounce'));
});
},

_unbindScroll: function() {
this.get("scrollable").off("scroll."+this.get('guid'));
_unbindScroll() {
this.get("scrollable").off(`scroll.${this.get('guid')}`);
},

_checkIfInView: function() {
_checkIfInView() {
var selfOffset = this.$().offset().top;
var scrollable = this.get("scrollable");
var scrollableBottom = scrollable.height() + scrollable.scrollTop();

var inView = selfOffset < scrollableBottom ? true : false;
var inView = selfOffset < scrollableBottom;

if (inView && !this.get('developmentMode')) {
this.sendAction('loadMoreAction');
}
},

_setupScrollable: function() {
_setupScrollable() {
var scrollable = this.get('scrollable');
if (Ember.$.type(scrollable) === 'string') {
if (Ember.typeOf(scrollable) === 'string') {
var items = Ember.$(scrollable);
if (items.length === 1) {
this.set('scrollable', items.eq(0));
Expand All @@ -64,7 +65,9 @@ export default Ember.Component.extend({
}
},

loadedStatusDidChange: Ember.observer('infinityModel.reachedInfinity', 'destroyOnInfinity', function() {
if (this.get('infinityModel.reachedInfinity') && this.get('destroyOnInfinity')) { this.destroy(); }
loadedStatusDidChange: Ember.observer('infinityModel.reachedInfinity', 'destroyOnInfinity', function () {
if (this.get('infinityModel.reachedInfinity') && this.get('destroyOnInfinity')) {
this.destroy();
}
})
});
87 changes: 62 additions & 25 deletions addon/mixins/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,30 @@ export default Ember.Mixin.create({
*/
_modelPath: 'controller.model',

/**
* Name of the "per page" param in the
* resource request payload
* @type {String}
* @default "per_page"
*/
perPageParam: 'per_page',

/**
* Name of the "page" param in the
* resource request payload
* @type {String}
* @default "page"
*/
pageParam: 'page',

/**
* Path of the "total pages" param in
* the HTTP response
* @type {String}
* @default "meta.total_pages"
*/
totalPagesParam: 'meta.total_pages',

/**
@private
@property _canLoadMore
Expand All @@ -77,7 +101,7 @@ export default Ember.Mixin.create({
_canLoadMore: Ember.computed('_totalPages', '_currentPage', function() {
var totalPages = this.get('_totalPages');
var currentPage = this.get('_currentPage');
return totalPages && currentPage ? currentPage < totalPages : false;
return (totalPages && currentPage) ? (currentPage < totalPages) : false;
}),

/**
Expand All @@ -89,10 +113,9 @@ export default Ember.Mixin.create({
@param {Object} options Optional, the perPage and startingPage to load from.
@return {Ember.RSVP.Promise}
*/
infinityModel: function(modelName, options) {
var _this = this;
infinityModel(modelName, options) {

if (this.store === undefined){
if (Ember.isEmpty(this.store) || Ember.isEmpty(this.store.find)){
throw new Ember.Error("Ember Data store is not available to infinityModel");
} else if (modelName === undefined) {
throw new Ember.Error("You must pass a Model Name to infinityModel");
Expand All @@ -113,18 +136,26 @@ export default Ember.Mixin.create({
this.set('_modelPath', modelPath);
this.set('_extraParams', options);

var params = Ember.merge({ page: startingPage, per_page: perPage }, options);
var requestPayloadBase = {};
requestPayloadBase[this.get('perPageParam')] = perPage;
requestPayloadBase[this.get('pageParam')] = startingPage;

var params = Ember.merge(requestPayloadBase, options);
var promise = this.store.find(modelName, params);

promise.then(
function(infinityModel) {
var totalPages = infinityModel.get('meta.total_pages');
_this.set('_currentPage', startingPage);
_this.set('_totalPages', totalPages);
infinityModel.set('reachedInfinity', !_this.get('_canLoadMore'));
Ember.run.scheduleOnce('afterRender', _this, 'infinityModelUpdated', { lastPageLoaded: startingPage, totalPages: totalPages, newObjects: infinityModel });
infinityModel => {
var totalPages = infinityModel.get(this.get('totalPagesParam'));
this.set('_currentPage', startingPage);
this.set('_totalPages', totalPages);
infinityModel.set('reachedInfinity', !this.get('_canLoadMore'));
Ember.run.scheduleOnce('afterRender', this, 'infinityModelUpdated', {
lastPageLoaded: startingPage,
totalPages: totalPages,
newObjects: infinityModel
});
},
function() {
() => {
throw new Ember.Error("Could not fetch Infinity Model. Please check your serverside configuration.");
}
);
Expand All @@ -138,8 +169,7 @@ export default Ember.Mixin.create({
@method infinityLoad
@return {Boolean}
*/
_infinityLoad: function() {
var _this = this;
_infinityLoad() {
var nextPage = this.get('_currentPage') + 1;
var perPage = this.get('_perPage');
var totalPages = this.get('_totalPages');
Expand All @@ -151,33 +181,40 @@ export default Ember.Mixin.create({

var params = Ember.merge({ page: nextPage, per_page: perPage }, this.get('_extraParams'));
var promise = this.store.find(modelName, params);

promise.then(
function(infinityModel) {
infinityModel => {
model.pushObjects(infinityModel.get('content'));
_this.set('_loadingMore', false);
_this.set('_currentPage', nextPage);
Ember.run.scheduleOnce('afterRender', _this, 'infinityModelUpdated', { lastPageLoaded: nextPage, totalPages: totalPages, newObjects: infinityModel });
if (!_this.get('_canLoadMore')) {
_this.set(_this.get('_modelPath') + '.reachedInfinity', true);
Ember.run.scheduleOnce('afterRender', _this, 'infinityModelLoaded', { totalPages: totalPages });
this.set('_loadingMore', false);
this.set('_currentPage', nextPage);
Ember.run.scheduleOnce('afterRender', this, 'infinityModelUpdated', {
lastPageLoaded: nextPage,
totalPages: totalPages,
newObjects: infinityModel
});
if (!this.get('_canLoadMore')) {
this.set(this.get('_modelPath') + '.reachedInfinity', true);
Ember.run.scheduleOnce('afterRender', this, 'infinityModelLoaded', {
totalPages: totalPages
});
}
},
function() {
_this.set('_loadingMore', false);
() => {
this.set('_loadingMore', false);
throw new Ember.Error("You must pass a Model Name to infinityModel");
}
);
} else {
if (!this.get('_canLoadMore')) {
this.set(this.get('_modelPath') + '.reachedInfinity', true);
Ember.run.scheduleOnce('afterRender', _this, 'infinityModelLoaded', { totalPages: totalPages });
Ember.run.scheduleOnce('afterRender', this, 'infinityModelLoaded', { totalPages: totalPages });
}
}
return false;
},

actions: {
infinityLoad: function() {
infinityLoad() {
this._infinityLoad();
}
}
Expand Down
16 changes: 8 additions & 8 deletions bower.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
{
"name": "ember-infinity",
"dependencies": {
"jquery": "^1.11.1",
"ember": "1.10.0",
"ember-data": "1.0.0-beta.15",
"ember-resolver": "~0.1.12",
"loader.js": "ember-cli/loader.js#3.2.0",
"ember-cli-shims": "ember-cli/ember-cli-shims#0.0.3",
"ember-cli-test-loader": "ember-cli-test-loader#0.1.3",
"ember-load-initializers": "ember-cli/ember-load-initializers#0.0.2",
"ember-qunit": "0.2.8",
"ember-data": "1.0.0-beta.17",
"ember-load-initializers": "ember-cli/ember-load-initializers#0.1.4",
"ember-qunit": "0.3.3",
"ember-qunit-notifications": "0.0.7",
"qunit": "~1.17.1",
"pretender": "0.1.0"
"ember-resolver": "~0.1.15",
"jquery": "^1.11.1",
"loader.js": "ember-cli/loader.js#3.2.0",
"pretender": "0.6.0",
"qunit": "~1.17.1"
}
}
Loading