Jump to content

nbcommunication

Members
  • Content Count

    110
  • Joined

  • Last visited

  • Days Won

    1

nbcommunication last won the day on July 25 2019

nbcommunication had the most liked content!

Community Reputation

153 Excellent

About nbcommunication

  • Rank
    Distinguished Member

Profile Information

  • Gender
    Not Telling
  • Location
    Lerwick, Shetland

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Nice one. Yeah, my implementation using UIkit's Scrollspy component isn't great to be honest, but I didn't want to use a 3rd-party plugin for the example. Your best bet would be to look for a jQuery plugin for handling the scroll-to-bottom thing, I'm sure something will exist! Basically, when the scroll-to-bottom is triggered, you need to call the get() function. This should replace the // Attach Listener part of my example. Cheers, Chris
  2. Hi @jonatan, Try putting the if($config->ajax) code at the top of your template file, before anything else is being output. This will ensure that what is being returned is purely JSON. You can log failed requests like so: $.getJSON(window.location.href, function(data) { // ... }).fail(function(jqXHR, textStatus, errorThrown) { console.log(jqXHR, textStatus, errorThrown); }); I think what you'd probably be getting is a JSON parse error due to the html being output prior to the AJAX response. The reason for the next results to not be explicit in the way you've suggested is that the "next" link provided by the API is tied to the original request, and since pagination is likely to be handled by AJAX requests, it makes sense to just build this in as I've done. Cheers, Chris
  3. Hi @jonatan, I've been able to pick away at this over the weekend... too cold yet to plant tatties! With the discovery of the hidden limit option in the API, I had to rewrite some of the module, but everything should just work the same, if not even better... However, I'm not sure it'll help too much with API rate limiting in your case, as each carousel album is still a separate API call. There is now the option to prevent the "children" (the rest of the album carousel images) from being retrieved: <?php $instagram = $modules->get("InstagramBasicDisplayApi"); $items = $instagram->getMedia(["children" => false]); When working with this over the weekend, I kept an eye on the rate limiting page and it did get nudged frequently, but didn't go beyond 30% used. The account I was using for testing only had a few carousels though. I've also been able to implement "lazy loading". The example I've added to the README is based on the getMedia() example, using UIkit's javascript utilities. I've attached a short clip of how this looks. Here's how it might work using Bootstrap/jQuery: In your template file: <?php $instagram = $modules->get("InstagramBasicDisplayApi"); // The pagination cursor is reset if the request is not AJAX, e.g. when the page is loaded. if($config->ajax) { header("Content-Type: application/json"); echo $instagram->getMedia(); // ["json" => true] is inferred by $config->ajax die(); } echo "<div id='instagram' class='row'></div>"; In your javascript: // Totally untested!!!! var instagram = { $el: {}, // Where the items go $loading: {}, // The loading spinner total: 0, // The total number of items init: function() { this.$el = $("#instagram"); if(!this.$el.length) return; // Add the spinner this.$el.after("<div id='instagram-loading'>...Your choice of spinner!</div>"); this.$loading = $("#instagram-loading"); this.$loading.hide(); // Get the first batch of items this.get(); }, get: function() { var this$1 = this; // Show spinner this$1.$loading.show(); // Request $.getJSON(window.location.href, function(data) { // Hide spinner this$1.$loading.hide(); if(!$.isArray(data) || !data.length) return; // If no items do not render var items = []; data.forEach(function(item, index) { switch(item.type) { case "VIDEO": items.push(this$1.renderItem(item.poster, item.alt, item.src, index)); break; case "CAROUSEL_ALBUM": var out = ""; for(var i = 0; i < item.children.length; i++) { var src = item.children[i].src; out += "<a class='carousel-item' data-fancybox='gallery-ig' data-height='600' data-caption='" + item.alt + "' href='" + src + "'>" + "<div style='background-image: url(" + src + ")' class='pics'></div>" + "</a>"; } items.push( "<div data-interval='3000' class='carousel slide carousel-fade col-4 p-3 pics' data-ride='carousel' id='instagram-item-" + (this$1.total + index) + "'>" + "<div class='carousel-inner'>" + out + "<a class='carousel-control-prev' href='#_{$post->id}' role='button' data-slide='prev'>" + "<span class='carousel-control-icon-bg' aria-hidden='true'></span>" + "<span class='carousel-control-prev-icon' aria-hidden='true'></span>" + "<span class='sr-only'>Previous</span>" + "</a>" + "<a class='carousel-control-next' href='#_{$post->id}' role='button' data-slide='next'>" + "<span class='carousel-control-icon-bg' aria-hidden='true'></span>" + "<span class='carousel-control-next-icon' aria-hidden='true'></span>" + "<span class='sr-only'>Next</span>" + "</a>" + "</div>" + "</div>" ); break; default: // IMAGE items.push(this$1.renderItem(item.src, item.alt, item.src, index)); break; } }); var count = items.length; if(count) { // Append items to the container this$1.$el.append(items.join("")); // Attach listener // No idea if this works!!! $(window).on("resize scroll", function() { var next = $("#instagram-item-" + (this$1.total + count - (count < 5 ? 1 : 6))); if(!next.hasClass("seen") && this$1.inViewport()) { next.addClass("seen"); this$1.get(); } }); // Update total this$1.total = this$1.total + count; } }, function(e) { this$1.$loading.hide(); console.log(e); // ERROR }) }, inViewport: function(el) { // Untested, got the code from // https://medium.com/talk-like/detecting-if-an-element-is-in-the-viewport-jquery-a6a4405a3ea2 var elementTop = el.offset().top; var elementBottom = elementTop + el.outerHeight(); var viewportTop = $(window).scrollTop(); var viewportBottom = viewportTop + $(window).height(); return elementBottom > viewportTop && elementTop < viewportBottom; }, renderItem: function(src, alt, href, index) { return "<div class='col-4 p-3 pics' id='instagram-item-" + (this.total + index) + "'>" + "<a data-fancybox='gallery-ig' data-height='600' data-caption='" + alt + "' href='" + href + "'>" + "<div style='background-image: url(" + src + ")' class='pics'>" + (src !== href ? "<div class='overlay-video-icon'></div>" : "") + "</div>" + "</a>" + "</div>"; } }; $(document).ready(function() { instagram.init(); }); I've just done the jQuery from memory with the addition of an inViewport function I found online. No idea if it works! Let me know how you get on! Cheers, Chris instagram-basic-display-api-lazy-2020-03-29.mp4
  4. Hi @jonatan, I'm making good progress on this but not finished yet. Discovered that there's a hidden "limit" API option which has necessitated a bit of a rewrite. May get to it this weekend (weather is looking good though, so might be out in the garden!), if not on Monday. Cheers, Chris
  5. Hi @jonatan, Aye lazy loading is proving to be a little tricky, mainly because of caching. I need to think through this more and will get back to it tomorrow. Cheers, Chris
  6. Hi @jonatan, I've managed to get access to an account with 20 items for testing. The "counting" in the module is actually correct, I think the issue is maybe that after the limit is reached the API just returns blank records? Anyway, I've added a little bit of code that removes any items without a media_url before they are returned, which should fix your issue. Code not pushed yet, should be later today. Cheers, Chris
  7. Hi @jonatan, Thanks for the debug array. Yep there's definitely an issue with asking for more items than there actually is. Will get that sorted. Each carousel requires a separate API call. That means each request for 80 items (that isn't cached) uses up 50 API calls. The error isn't at that point. Try this: <?php switch($post->type) { case "VIDEO": // ... break; case "CAROUSEL_ALBUM": // If the post does not have children, continue without rendering if(!$post->children) break; // ... break; // ... } Cheers, Chris
  8. Hi @jonatan, No, I think echoing as you are doing would probably be faster if anything. Basically no difference - I just like to use the array so I don't have to wrap with <div></div> in three separate places. I'm going to look into making the pagination more available through the module tomorrow. Might be tricky, and it probably will need to be batches of 24, but I definitely think you've made a good case that it should be available. I think that may have been from the previous API. This one returns the first 24 items, and a link for getting the next 24. You can keep going on until all items have been received or until the API limits have been maxed out. Indeed, this is what would happen if you were to call something like InstagramBasicDisplayApi::getMedia(10000), although I think there would be a timeout before completion. If you request 89 and there are only 80, it should return 80, but I don't think I actually tested that. I don't have access to an account at the moment with a relatively small amount of items, but should do soon, so will test this when I can. I suspect there is an issue and this is why you are getting the undefined offset errors and the blank items. For debugging, I'd add the following to your code: <?php $images = $instagram->getMedia(89); echo count($images) . "<br>" . print_r($images, 1); If you are requesting 80 items, and 10 of those are album carousels, that should be 14 calls to the API (24, 24, 24, 24[8] + a call for each carousel). How many carousels do you have? When I was developing and testing I didn't budge the limit off 0%. Will have another look at this tomorrow. I think it may be useful to have an option to not get the full carousel when using getMedia() as this does seem to be the issue. I'm not following this. I think I know what you mean now I've gone through the following... I'll tweak your code to what I think you are trying to achieve and that'll maybe get us closer: <?php $username = "a_username"; $account = $instagram->getProfile($username); $postsnum = $account["media_count"] ?? 0; // If the API request is unsuccessful, the post count below will not be displayed ?> <div class="col-12 text-center mb-3"> <a href="https://instagram.com/<?= $username ?>/" target="_blank" class="marked"> <h3 class="marked my-5 instalink">@<?= $username ?></h3> </a> <?php if($postsnum): ?><h5 class="marked-dark"><?= $postsnum ?> POSTS / OPSLAG </h5><?php endif; ?> </div> getProfile() is a single call which will be cached for either an hour or however long you have the cache time set to so I wouldn't consider this a resource issue. Given that the cache time will be the same for getMedia(), the count and the number of items you get if you were to get them all should be the same, but the count won't update until the cache has expired. getUserAccount() should have the same value for media_count, but it is only updated when getProfile() is called (and an API request is made) so I don't think it is worth using in this situation. It is a public method but only so it could be used in the config - I can't think of a situation where it should be used over getProfile(). The errors you've pointed out in your last post are related to the total number issue which I'll get fixed as soon as I can. I'll hopefully have some progress on this tomorrow! Thanks again for your feedback! Cheers, Chris
  9. Hi @jonatan, I'll have a think about how best to implement a lazy-load. I'll need to provide a way to return the "next" link to do this. The cache time is set in the module configuration, should be 3600 by default. Quite possible that the single request is maxing out the limit, will look at that later. Cheers, Chris
  10. Hi @jonatan, I'll provide a fuller response later but just a couple of things now: The API doesn't actually allow for querying a specific number of items like the old one did. The module actually uses the built in pagination to retrieve as many items as requested in the call. That's why it is taking a while. You should have a cache time of at least 3600 seconds (an hour) if you are requesting this many items. This will prevent maxing out the limits (which is a lot easier to do when developing anyway!). If I were in your position, I'd be weighing whether so many items need to be displayed. I'd probably just display the first batch (e.g. $images = $instagram->getMedia()) which returns 24 items normally. For the PHP error: <?php foreach($images = $instagram->getMedia(89) as $post) { ... } // I'd change this to: $images = $instagram->getMedia(89); if(count($images)) { foreach($images as $post) { ... } } Cheers, Chris
  11. Hi @gowthamg, The instructions for this module, for setting up the facebook app are here: https://github.com/nbcommunication/InstagramBasicDisplayApi/blob/master/README.md and relate exclusively to this part of the facebook/instagram docs: https://developers.facebook.com/docs/instagram-basic-display-api/overview#user-token-generator. I'd advise reviewing the errors displayed on your screenshot - notes and screencast are missing. If you do have success in getting the app reviewed and approved, please share here, but as I said previously, this isn't in the purview of this module. Cheers, Chris
  12. Hi @gowthamg - I can't help you here I'm afraid. This module and the instructions provided are not geared toward app review. Cheers, Chris
  13. Hi @gowthamg, What do you mean by all users? In the past, getting Instagram data from any user was pretty simple, but it is locked down now. You can only retrieve data from users who have authorised your app. This module is built around the oAuth token generator provided by facebook, which allows you to add a "test" Instagram user, and then generate a token by logging in as that user and authorising the app. This bypasses the need to submit the app for review, which is intended for apps that would be public facing. You can only get data from users that have authorised your app, and in this case of this module, you need to login as the user to authorise it. For a number of clients recently we've arranged a time where they change their password to something temporary and let us know the temp password, we run through the steps in the README and get the app/module set up, and then let the client know so they can change their password back. It has worked well so far. Cheers, Chris
  14. Hi @jonatan, Many thanks for your feedback, and for helping out @gowthamg. You are correct - looks like he's trying to set up the full API which isn't what this module uses. I've updated the README with the module call in each example, and also added an example for getMedia() which demonstrates how to build a multi-media gallery using UIkit. I've attached a video example of the result 🙂 Here's the code I added to the README: // Function for rendering items function renderInstagramItem($src, $alt, $href = null) { if(is_null($href)) $href = $src; return "<a href='$href' data-caption='$alt' " . ($src !== $href ? "data-poster='$src' " : "") . "class='uk-display-block uk-cover-container'>" . "<canvas width='640' height='640'></canvas>" . "<img src='$src' alt='$alt' data-uk-cover>" . "</a>"; } // Get the module $instagram = $modules->get("InstagramBasicDisplayApi"); // Get the 16 most recent items and render them based on type $items = []; foreach($instagram->getMedia(16) as $item) { switch($item->type) { case "VIDEO": $items[] = renderInstagramItem($item->poster, $item->alt, $item->src); break; case "CAROUSEL_ALBUM": // If 4 or greater items, display a grid of the first 4 images // Otherwise display the main image (no break, moves to default) if($item->children->count() >= 4) { $items[] = "<div class='uk-grid-collapse uk-child-width-1-2' data-uk-grid>" . $item->children->find("limit=4")->each(function($item) { return "<div>" . renderInstagramItem($item->src, $item->alt) . "</div>"; }) . "</div>"; break; } default: // IMAGE $items[] = renderInstagramItem($item->src, $item->alt); break; } } // Render the items as a grid echo "<div class='uk-grid-collapse uk-child-width-1-2 uk-child-width-1-4@s' data-uk-grid data-uk-lightbox>"; foreach($items as $item) { echo "<div>$item</div>"; } echo "</div>"; The query about data-width - this is a totally separate thing unfortunately. That's the oEmbed implementation from which you get a HTML embed code which normally includes javascript from the provider, and in the case of Instagram includes code which handles a data-width attribute. There's nothing like that here. This API gives you basic data, and it is up to you to render it. I'd actually recommend looking more into oEmbed if you are looking to embed single posts in articles or similar. The main purpose of this module and the API itself is a standalone "feed" or gallery of user media. Cheers, Chris instagram-basic-display-api-2020-03-21.mp4
  15. Hey, If anyone has installed and implemented this module, please let me know if you've any feedback! I've currently only used it as a replacement for InstagramFeed, and it has worked great 🙂 Cheers, Chris
×
×
  • Create New...