Skip to content

Commit

Permalink
Add pagination support
Browse files Browse the repository at this point in the history
  • Loading branch information
stevenschobert committed Nov 2, 2020
1 parent 23a126c commit 7cca0b2
Showing 1 changed file with 148 additions and 27 deletions.
175 changes: 148 additions & 27 deletions src/instafeed.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ function Instafeed(options) {
accessTokenTimeout: 10000,
after: null,
apiTimeout: 10000,
apiLimit: 25,
before: null,
debug: false,
error: null,
Expand All @@ -32,7 +33,11 @@ function Instafeed(options) {

// state holder
var state = {
running: false
running: false,
node: null,
token: null,
paging: null,
pool: []
};

// copy options over defaults
Expand All @@ -49,6 +54,7 @@ function Instafeed(options) {
assert(typeof opts.accessToken === 'string' || typeof opts.accessToken === 'function', 'accessToken must be a string or function, got ' + opts.accessToken + ' ('+ typeof opts.accessToken +')');
assert(typeof opts.accessTokenTimeout === 'number', 'accessTokenTimeout must be a number, got '+ opts.accessTokenTimeout + ' ('+ typeof opts.accessTokenTimeout +')');
assert(typeof opts.apiTimeout === 'number', 'apiTimeout must be a number, got '+ opts.apiTimeout + ' ('+ typeof opts.apiTimeout +')');
assert(typeof opts.apiLimit === 'number', 'apiLimit must be a number, got ' + opts.apiLimit + ' ('+ typeof opts.apiLimit +')');
assert(typeof opts.debug === 'boolean', 'debug must be true or false, got ' + opts.debug + ' ('+ typeof opts.debug +')');
assert(typeof opts.mock === 'boolean', 'mock must be true or false, got ' + opts.mock + ' ('+ typeof opts.mock +')');
assert(typeof opts.templateBoundaries === 'object' && opts.templateBoundaries.length === 2 && typeof opts.templateBoundaries[0] === 'string' && typeof opts.templateBoundaries[1] === 'string', 'templateBoundaries must be an array of 2 strings, got ' + opts.templateBoundaries + ' ('+ typeof opts.templateBoundaries +')');
Expand All @@ -70,10 +76,6 @@ function Instafeed(options) {

Instafeed.prototype.run = function run() {
var scope = this;
var node = null;
var url = null;
var items = null;
var html = null;

this._debug('run', 'options', this._options);
this._debug('run', 'state', this._state);
Expand All @@ -90,15 +92,15 @@ Instafeed.prototype.run = function run() {
// get dom node
this._debug('run', 'getting dom node');
if (typeof this._options.target === 'string') {
node = document.getElementById(this._options.target);
this._state.node = document.getElementById(this._options.target);
} else {
node = this._options.target;
this._state.node = this._options.target;
}
if (!node) {
if (!this._state.node) {
this._fail(new Error('no element found with ID ' + this._options.target));
return false;
}
this._debug('run', 'got dom node', node);
this._debug('run', 'got dom node', this._state.node);

// get access token
this._debug('run', 'getting access token');
Expand All @@ -109,45 +111,146 @@ Instafeed.prototype.run = function run() {
return;
}

url = 'https://graph.instagram.com/me/media?fields=caption,id,media_type,media_url,permalink,thumbnail_url,timestamp,username&access_token='+ token;
scope._debug('onTokenReceived', 'request url', url);
scope._debug('onTokenReceived', 'got token', token);
scope._state.token = token;

scope._showNext(function onNextShown(err) {
if (err) {
scope._debug('onNextShown', 'error', err);
scope._fail(err);
return;
}

scope._finish();
});
});

return true;
};

Instafeed.prototype.hasNext = function hasNext() {
var paging = this._state.paging;
var pool = this._state.pool;

this._debug('hasNext', 'paging', paging);
this._debug('hasNext', 'pool', pool.length, pool);

return (pool.length > 0 || (paging && typeof paging.next === 'string'));
};

Instafeed.prototype.next = function next() {
var scope = this;

if (!scope.hasNext()) {
scope._debug('next', 'hasNext is false, skipping');
return false;
}

// prevent re-entry
if (scope._state.running) {
scope._debug('next', 'already running, skipping');
return false;
}

// set as running
scope._start();

// show next set
scope._showNext(function onNextShown(err) {
if (err) {
scope._debug('onNextShown', 'error', err);
scope._fail(err);
return;
}

scope._finish();
});
};

Instafeed.prototype._showNext = function showNext(callback) {
var scope = this;
var url = null;
var poolItems = null;
var hasLimit = (typeof this._options.limit === 'number');

scope._debug('showNext', 'pool', scope._state.pool.length, scope._state.pool);

if (scope._state.pool.length > 0) {
if (hasLimit) {
poolItems = scope._state.pool.splice(0, scope._options.limit);
} else {
poolItems = scope._state.pool.splice(0);
}

scope._debug('showNext', 'items from pool', poolItems.length, poolItems);
scope._debug('showNext', 'updated pool', scope._state.pool.length, scope._state.pool);

if (scope._options.mock) {
scope._debug('showNext', 'mock enabled, skipping render');
} else {
try {
scope._renderData(poolItems);
} catch (renderErr) {
callback(renderErr);
return;
}
}

callback(null);
} else {
if (scope._state.paging && typeof scope._state.paging.next === 'string') {
url = scope._state.paging.next;
} else {
url = 'https://graph.instagram.com/me/media?fields=caption,id,media_type,media_url,permalink,thumbnail_url,timestamp,username&limit='+ scope._options.apiLimit +'&access_token='+ scope._state.token;
}

scope._debug('showNext', 'making request', url);

// make network request
scope._makeApiRequest(url, function onResponseReceived(err, data) {
var processed = null;

if (err) {
scope._debug('onResponseReceived', 'error', err);
scope._fail(new Error('api request error: ' + err.message));
callback(new Error('api request error: ' + err.message));
return;
}

scope._debug('onResponseReceived', 'data', data);
scope._success(data);

scope._debug('onResponseReceived', 'setting paging', data.paging);
scope._state.paging = data.paging;

try {
items = scope._processData(data);
scope._debug('onResponseReceived', 'processed data', items);
processed = scope._processData(data);
scope._debug('onResponseReceived', 'processed data', processed);

if (processed.unused && processed.unused.length > 0) {
scope._debug('onResponseReceived', 'saving unused to pool', processed.unused.length, processed.unused);
for (var i = 0; i < processed.unused.length; i++) {
scope._state.pool.push(processed.unused[i]);
}
}
} catch (processErr) {
scope._fail(processErr);
callback(processErr);
return;
}

if (scope._options.mock) {
scope._debug('onResponseReceived', 'mock enabled, skipping render');
scope._debug('onResponseReceived', 'mock enabled, skipping append');
} else {
try {
html = scope._renderData(items);
scope._debug('onResponseReceived', 'html content', html);
scope._renderData(processed.items);
} catch (renderErr) {
scope._fail(renderErr);
callback(renderErr);
return;
}
node.innerHTML = html;
}

scope._finish();
callback(null);
});
});

return true;
}
};

Instafeed.prototype._processData = function processData(data) {
Expand All @@ -160,6 +263,7 @@ Instafeed.prototype._processData = function processData(data) {
var dataItem = null;
var transformedItem = null;
var filterResult = null;
var unusedItems = null;

this._debug('processData', 'hasFilter', hasFilter, 'hasTransform', hasTransform, 'hasSort', hasSort, 'hasLimit', hasLimit);

Expand Down Expand Up @@ -214,12 +318,18 @@ Instafeed.prototype._processData = function processData(data) {
if (hasLimit) {
limitDelta = transformedFiltered.length - this._options.limit;
this._debug('processData', 'checking limit', transformedFiltered.length, this._options.limit, limitDelta);

if (limitDelta > 0) {
unusedItems = transformedFiltered.slice(transformedFiltered.length - limitDelta);
this._debug('processData', 'unusedItems', unusedItems.length, unusedItems);
transformedFiltered.splice(transformedFiltered.length - limitDelta, limitDelta);
}
}

return transformedFiltered;
return {
items: transformedFiltered,
unused: unusedItems
};
};

Instafeed.prototype._extractTags = function extractTags(str) {
Expand Down Expand Up @@ -276,12 +386,13 @@ Instafeed.prototype._renderData = function renderData(items) {
var hasRender = (typeof this._options.render === 'function');
var item = null;
var itemHtml = null;
var container = null;
var html = '';

this._debug('renderData', 'hasTemplate', hasTemplate, 'hasRender', hasRender);

if (typeof items !== 'object' || items.length <= 0) {
return null;
return;
}

for (var i = 0; i < items.length; i++) {
Expand All @@ -306,7 +417,17 @@ Instafeed.prototype._renderData = function renderData(items) {
}
}

return html;
this._debug('renderData', 'html content', html);

container = document.createElement('div');
container.innerHTML = html;

this._debug('renderData', 'container', container, container.childNodes.length, container.childNodes);

while (container.childNodes.length > 0) {
this._debug('renderData', 'appending child', container.childNodes[0]);
this._state.node.appendChild(container.childNodes[0]);
}
};

Instafeed.prototype._basicRender = function basicRender(data) {
Expand Down

0 comments on commit 7cca0b2

Please sign in to comment.