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

Limit with filter #97

Closed
jaredprice opened this issue May 2, 2014 · 23 comments
Closed

Limit with filter #97

jaredprice opened this issue May 2, 2014 · 23 comments
Assignees
Labels

Comments

@jaredprice
Copy link

Is it possible to limit the number of images while applying a filter, such that it will look through all the images in the user's feed to satisfy the limit?

    var feed = new Instafeed({
        get: 'user',
        userId: USER_ID,
        clientId: 'CLIENT_ID',
        accessToken: 'ACCESS_TOKEN',
        template: '<a href="{{link}}"><img src="{{image}}" /></a>',
        limit: 12,
        filter: function(image) {
            return image.tags.indexOf('mytag') >= 0;
        }
    });
    feed.run();
@jaredprice
Copy link
Author

The issue I'm running into is that the above method only looks at the 12 most recent images when applying the filter. I'm wanting it to find the 12 most recent images with the specified tag.

@scottzirkel
Copy link

+1 on this. I've tried a few things but can't quite get it to work.

@stevenschobert
Copy link
Owner

@jaredprice Sorry for the confusion there! You are correct, the limit option is applied before the filter, instead of after.

To work around this, you could set the limit option much higher, and then manually keep track of how many images have passed the filter test, and return false once you've gotten all the images you want.

This allows you to have a sort of "artificial" limit that you track outside of the limit option Instafeed.js provides:

var foundImages = 0;
var maxImages = 12;

var feed = new Instafeed({
    // ... other settings
    limit: 60,
    success: function() {
        foundImages = 0;
    },
    filter: function(image) {
        if (image.tags.indexOf('mytag') >= 0 && foundImages < maxImages) {
            foundImages = foundImages + 1;
            return true;
        }
        return false;
    }
});
feed.run();

Hope that helps!

@jaredprice
Copy link
Author

Here is what I'm using. Still not getting it to work.

    var foundImages = 0;
    var maxImages = 6;
    var feed = new Instafeed({
        get: 'user',
        userId: USER_ID,
        clientId: 'CLIENT_ID',
        accessToken: 'ACCESS_TOKEN',
        resolution: 'standard_resolution',
        template: '<a href="{{link}}" id="instagram" class="instafeed"><img src="{{image}}" class="instagram-img" /></a>',
        limit: 600,
        success: function() {
            foundImages = 0;
        },
        filter: function(image) {
            if (image.tags.indexOf('MY_TAG') >= 0 && foundImages < maxImages) {
                foundImages = foundImages + 1;
                return true;
            }
            return false;
        }
    });
    feed.run();

@jaredprice
Copy link
Author

I noticed that you say there is a max limit amount of 60. Is there a way to increase this? The tag that I'm attempting to use first appears 47 images deep in the feed presently. I'm wanting to populate 6 images at all times, but I'm concerned with building it in this way where the further away from the current images with the tag that we get, the possibility for losing them in the capture becomes greater. I hate to have to query 1000 images everytime to check against, but I'm not sure any other way to pull it off. The solution you provided doesn't seem to be working for me even when observing the 60 image max for the limit feature though.

@stevenschobert
Copy link
Owner

@jaredprice I'm afraid there isn't a way around that right now, no. I believe that limit is coming only from their API, which is out of my control (see #23).

You can however, use the .next() method to load more images, and your filter should get evaluated every time, which could be an easy way for you to "load" more than 60 images. They end up being separate network requests, and can only be made 1 at a time, but in theory you could just keep calling .next() until you have the amount of images you wish.

Sorry I don't have a better answer for you!

@jaredprice
Copy link
Author

Would I place this method inside the filter function?

@stevenschobert
Copy link
Owner

@jaredprice No, you can call that from anywhere after you’ve created that feed object:

var feed = new Instafeed({
  // settings …
});

// load the feed the first time
feed.run();

// now anywhere you want you can load more:
feed.next();

Sorry for not clarifying that!

@tamfr
Copy link

tamfr commented Aug 29, 2014

@jaredprice @scottzirkel In case you didn't see, ndwl posted in #23 that setting limit to -1 yields all the images, all of them except the very first one that is. Use that with what was explained above and you'll get all the recent images with the tag you specify. The following example yields the 12 most recent images of a tag for a specific user:

var foundImages = 0;
var maxImages = 12;     
var feed = new Instafeed({
     limit: -1,
     resolution: 'standard_resolution',
     get: 'user',
     userId: 'user-id',
     accessToken: 'token',
     success: function() {
          foundImages = 0;
     },
     filter: function(image) {
          if (image.tags.indexOf('mytag') >= 0 && foundImages < maxImages) {
               foundImages = foundImages + 1;
               return true;
          }
     return false;
     }
});
feed.run();

This was referenced Oct 21, 2014
@shariquequadri
Copy link

The limit=-1 now doesn't work in combination with the filter.

@iosonosempreio
Copy link

The -1 limit isn't working at all for me... I just hope I'm not missing anything. In order to get it working, I must set the limit to 60.
Btw, I'm wondering if it's possible to set a loop that is returning one image at time, checking for the date to be equal (or lower, or greater) than a given date. The given date may be a very old one, so all the pics are retrieved.
The idea is to put the limit value to 1, and then calling the feed a number of times until we have all the pics. Probably it will be kind of a slow thing, but it could represent a sort of workaround.
Don't know if it's possible. Does anybody thought about it?

@rhysburnie
Copy link

This is what I use when I want a max and a min (I also happen to want to grab my images and filter by multiple tags)

var min = 10,
    max = 10,
    lastMatchedImages = 0;

var recent = new Instafeed({

    // whatever

    limit: 60,
    filter: function()
    {
        // I want to have multiple tags or plurals
        // so FYI this is how you do it
        var match = image.tags.join(',').match(/plant[s]{0,1},|building/gi) || [];

        if(match.length > 0 && lastMatchedImages < max) {
            lastMatchedImages++;
            return true;
        }
        return false;
    },
    after: function()
    {
        if(lastMatchedImages < min) {
            if(this.hasNext()) {
                recent.next();
            }
        } else {

            // whatever

        }
    }
};

recent.run();

I have a next button to continue pagination it calls recent.run() but resets lastMatchedImages to 0 first that way I can continue pagination within scope of the tags.

NB: this obviously results in multiple ajax requests so you way want a limit of attempts it makes - I don't care.

@JimmyRittenborg
Copy link

These workarounds doesn't quite cut it for me - the #97 (comment) by @stevenschobert gets close, but it has a huge downside as everything in the difference between the filter and the rest of maxImages gets completely ignored and effectively whipped out of the feed - I think for this to work properly, another array after filterring has to be introduced, which serves as a buffer, and then limit should be set to twice the maximum number of images that should be displayed at once, from this array the entries gets sorted and attached to the dom. And then the load more, would need to work in conjunction with this behaviour, as the buffer array can contain entries past whats available from instagram at that moment.

@tamfr
Copy link

tamfr commented Feb 19, 2015

For those of you that really need the functionality proving difficult with this, that is specifying a tag and pulling from all images without limit, try https://github.com/d4nyll/instafetch. It is a bit clunky, but works and was specifically written for this task. The example site is http://d4nyll.github.io/instafetch/. You can also check out www.osteoengineering.com, which uses both instafeed and instafetch (www.osteoengineering.com/team/briswan for example). Each team member page pulls images from our instagram account with the team member in it based on tags.

@rhysburnie
Copy link

@JimmyRittenborg

Obviously thats the case, as stated that's a custom filter for my own purposes.
You would set up your own filter.

RE: the rest of the results completely ignored - that is the point of a filter

I can get the mechanism described to work in all situations with or without filters, I simply provided an example.

@JimmyRittenborg
Copy link

@rhysburnie the point of a filter is to strip out what's defined to be stripped out by the filter, and certainly nothing more, which is actually the case.

For example: The filter is set to filter out two images, by their ID. 12 should be shown at a time. Limit is set to 24 (buffering for the filter as 12 should be shown, and not only 10). when hitting [Load more] the remaining 10 images is effectively filtered out, although not defined to be filtered out and 24-48 is now being fetched, again with most of half the data being whipped out.

btw. I wasn't referring to your example, but the exemple i was mentioning in my comment.

@rhysburnie
Copy link

@JimmyRittenborg

What Im guessing is that you are concerned that because the filtered results may only contain 2 images that the pagination would somehow be out of sync?
Fair enough assumption but it's not the case, the plugin doesn't track any kind of buffer.

The plugin doesn't manipulate pagination based on filtered results, it only uses the nextUrl property provided in the instagram json.

If you look at the plugin code the filter function has noting to do with pagination, it only filters what will be displayed.

So in the following (the result amount per respnse would be based on settings but lets imagine 12):

1st call

actual results: 12
results for displayed: 3 (9 not matched)

2nd call

  • instagram api completly unaware of any filtering etc. it just receives the url defined in nextUrl property

actual results: next 12
results for displayed: 5 (7 not matched)

Each load more will always get the next correct set from instagram because it's doing it by simply calling the nextUrl property provided by the api and not a buffer.

@JimmyRittenborg
Copy link

@rhysburnie I'm still referring to #97 (comment) which doesen't change the fact that 12 images should be showed, 60 gets pulled in 2 gets filtered out (blocking by ID's) and 46 gets laid to rest in you browser memory for no one to ever see.

Conclusion: When using a filter to EXCLUDE items, that #97 (comment) trick will have a funky behaviour and feel really buggy.

True, nothing gets buffered - and that was actually the reason for why I suggested THAT and pagination on such buffer instead, to be a possible solution to the problem.

@JimmyRittenborg
Copy link

but it could probably just be in my application.. as it clearly says maxImages ;)

@rhysburnie
Copy link

@JimmyRittenborg

Yes if max of 10 and the result set of 20 and your filter matches 15 in that result set then those last five will effectively be hidden from display.

This is a limitation of the plugin itself. The images array only exists within the scope of the recent fetch (see Instafeed.prototype.parse).

@rhysburnie
Copy link

@JimmyRittenborg

But unlike everyone else on here who are offering solutions your simply throwing around the word buffer.

Perhaps the developer intends to fix this in his own time.
Otherwise you could do it.

What you have hit is a technical limitation of the plugin. There are several ways you could go about it but all involve editing the internal code, I would assume the developer wants to keep it clean and simple. The issue rarely happens when it does in my case I would be excluding a small amount of images personally I don't care enough to edit the code and create a pull request.

Im not sure why you would be using a filter to find image by ID anyway when the instagram api allows you to get data for a specific image by ID directly.

@razvan-fuzz
Copy link

@rhysburnie

I think I took your code one step further. Though not very efficient, this gets you all images of a certain tag filtered by a certain user. If there are more items than the limit, then it adds a class to the item and hides it. The next time the load more button is pressed your variable lastMatchedImages is initialised with the number of hidden images, their class is removed and they are not hidden anymore. This way you don't loose items and always get the right number of new images, unless you're on the last page.

    var loadButton = document.getElementById('load-more');
    var min = 20,
        max = 20,
        lastMatchedImages = 0;
    var feed = new Instafeed({
        limit: 60,
        get: 'tagged',
        tagName: 'YOURTAG',
        clientId: 'YOURID',
        template: '<a href="{{link}}" class="{{model.className}}" style="{{model.style}}"><img src="{{image}}" /></a>',
        filter: function(image)
        {
            if(image.user.username == 'USERNAME') {
                if(lastMatchedImages < max){
                    lastMatchedImages++;
                }
                else{
                    image.className = "fidden";
                    image.style = "display: none";
                };
                return true;
            }
            return false;
        },
          after: function() {
            if(this.hasNext()) {
                if(lastMatchedImages < min) {
                    feed.next();
                }
            } else {
              loadButton.setAttribute('disabled', 'disabled');
              $('#load-more').hide();
            }
          },
    });

    // bind the load more button
    loadButton.addEventListener('click', function() {
        numItems = $('.fidden').length;
        $('.fidden').show().removeClass( "fidden" );
        lastMatchedImages = numItems;
        feed.next();
    });

    // run our feed!
    feed.run();

@benjamin-hull
Copy link
Collaborator

Closing as complete.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

10 participants