SitePoint Sponsor

User Tag List

Results 1 to 14 of 14
  1. #1
    SitePoint Member
    Join Date
    Feb 2013
    Posts
    13
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Ajax request inside click function?

    Can you run an ajax request inside of a click function? I have been working with an api and I need to do a second request to get the comments for an image/video that was clicked. I am really new with ajax request and api's. And I have been working on a small script piecing things together.

    First off I know I am not accessing the url correctly for the second ajax request. I dont know how to re-use the code for that inside of this click event (if thats even where it goes). Second I dont know the proper way to access the array of comments. You can see in my butchered up code below I am lost for this part of the functionality.

    My console error message is this - "GET http://localhost/ig/insta.apiUrl 404 (Not Found) "

    I know I have things wrong please bare with me.

    Code:
    (function () {
        "use strict";
        var insta = window.insta = window.insta || {}; // insta Object
    
        insta = {
    
            apiUrl: 'https://api.instagram.com/v1/users/self/feed?access_token=[token here]&callback=?',
    
            init: function () {
                $.ajax({
                    type: 'GET',
                    url: insta.apiUrl,
                    dataType: 'json',
                    success: insta.success
                });
            },
    
            renderGrams: function (grams) {
                $.each(grams, function(index, gram) {
                    var gramHtml = '<div class="col-md-3"><p><img class="img-circle" style="margin-right: 5px" width="60" src="' + gram.user.profile_picture + '">' + gram.user.username + '</p><a href="#myModal" data-toggle="modal" data-username="' + gram.user.username +'" data-img-url="' + gram.images.standard_resolution.url + '" data-tags="' + gram.tags + '">';
                    if (gram.type === 'image') { gramHtml = gramHtml + '<img class="img-thumbnail" src="' + gram.images.low_resolution.url + '"/>'; }
                    if (gram.type === 'video') { gramHtml = gramHtml + '<video class="img-thumbnail" src="' + gram.videos.low_resolution.url + '"/>'; }
                    gramHtml = gramHtml + '</a></div>';
                    $('.results').append(gramHtml);
                });
            },
    
            setupClickEvent: function () {
                $('a').click(function(){
                    var largeImage = $(this).data('imgUrl');
                    var username = $(this).data('username');
                    var tags = $(this).data('tags');
    
                    $('.modal-title').html(username);
                    $('.modal-body').html('<div class="col-md-6"><img class="img-responsive" src="' + largeImage + '"><div class="tagwrap">' + tags + '</div></div>');
    
                    $.getJSON('insta.apiUrl', function(index, gram) {
                    $('.comments-container').html('<p>' + comments.data.text + '</p>');
                    });
    
                });
            },
    
            success: function (responseData) {
                if (responseData.meta.code === 200) {
                    insta.renderGrams(responseData.data);
                    insta.setupClickEvent();
                } else {
                    $('.results').html('<h1>An Error Occured</h1><p>' + responseData.meta.error_message + '</p>');
                }
            }
        };
    
        // This actually fires fires everything off
        // Follow from here
        insta.init(); 
    }());
    Here is some of the json for the comments -

    Code:
    "comments": {
            "count": 6,
            "data": [
              {
                "created_time": "1391457298",
                "text": "First like xd",
                "from": {
                  "username": "lars010999",
                  "profile_picture": "http:\/\/images.ak.instagram.com\/profiles\/profile_248947423_75sq_1379584795.jpg",
                  "id": "248947423",
                  "full_name": "Lars Lopulalan"
                },
                "id": "647913236748481826"
              },
              {
                "created_time": "1391457540",
                "text": "@blamay48 @bhamilton543 is a for sure character!!\ud83d\ude02 #tourguide",
                "from": {
                  "username": "mepmx",
                  "profile_picture": "http:\/\/images.ak.instagram.com\/profiles\/profile_340656728_75sq_1382493493.jpg",
                  "id": "340656728",
                  "full_name": "MEPMX\ud83d\udcf7@mepmx"
                },
                "id": "647915264509916589"
              },

  2. #2
    Programming Since 1978 silver trophybronze trophy felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, NSW, Australia
    Posts
    16,810
    Mentioned
    25 Post(s)
    Tagged
    1 Thread(s)
    With the line:

    Code:
    $.getJSON('insta.apiUrl', function(index, gram) {
    try removing the quotes arount insta.apiUrl
    Stephen J Chapman

    javascriptexample.net, Book Reviews, follow me on Twitter
    HTML Help, CSS Help, JavaScript Help, PHP/mySQL Help, blog
    <input name="html5" type="text" required pattern="^$">

  3. #3
    SitePoint Member
    Join Date
    Feb 2013
    Posts
    13
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by felgall View Post
    With the line:

    Code:
    $.getJSON('insta.apiUrl', function(index, gram) {
    try removing the quotes arount insta.apiUrl
    Thank you. That worked I believe but now I have an error - Uncaught ReferenceError: comments is not defined

    So I need to define it in with a var I assume? Why is it that I cant seem to build things yet with my brain based off of the books/tutorials I have done haha, this is killing me!

    My placement may be a bit off as well, but I'm really stumped on putting another ajax request together for this. All the ajax examples, and reading the docs don't even help me "get it" when trying to piece this together.

  4. #4
    Community Advisor bronze trophy
    fretburner's Avatar
    Join Date
    Apr 2013
    Location
    Brazil
    Posts
    1,397
    Mentioned
    45 Post(s)
    Tagged
    12 Thread(s)
    Hi clayton47,

    Quote Originally Posted by clayton47 View Post
    I have an error - Uncaught ReferenceError: comments is not defined
    It looks like this section of code is the problem:
    Code JavaScript:
    $.getJSON(insta.apiUrl, function(index, gram) {
        $('.comments-container').html('<p>' + comments.data.text + '</p>');
    });

    the success callback should have a single argument called comments:
    Code JavaScript:
    $.getJSON(insta.apiUrl, function(comments) {
        $('.comments-container').html('<p>' + comments.data.text + '</p>');
    });

  5. #5
    SitePoint Member
    Join Date
    Feb 2013
    Posts
    13
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by fretburner View Post
    Hi clayton47,



    It looks like this section of code is the problem:
    Code JavaScript:
    $.getJSON(insta.apiUrl, function(index, gram) {
        $('.comments-container').html('<p>' + comments.data.text + '</p>');
    });

    the success callback should have a single argument called comments:
    Code JavaScript:
    $.getJSON(insta.apiUrl, function(comments) {
        $('.comments-container').html('<p>' + comments.data.text + '</p>');
    });
    Ah ha! That returned some legitimate data - But I am trying to access it incorrectly it looks like. I'm not sure how to write the function to get the comments text array. And each image I click on after closing the modal that pops up my image with data its showing in the console that its just adding the next set of comments ontop of the next. How do I reset that ajax call for each click so it only displays data related to that item clicked?

    Looks like this is getting closer. Thanks for the help!

    Here is the console log I did on the (comments) function.

    Code:
    Object {pagination: Object, meta: Object, data: Array[19]}
    data: Array[19]
    0: Object
    1: Object
    2: Object
    3: Object
    4: Object
    5: Object
    6: Object
    7: Object
    8: Object
    9: Object
    10: Object
    11: Object
    12: Object
    13: Object
    14: Object
    15: Object
    16: Object
    17: Object
    18: Object
    attribution: null
    caption: Object
    comments: Object
    count: 11
    data: Array[8]
    0: Object
    created_time: "1391489255"
    from: Object
    id: "648181310245154586"
    text: "@jay_lyne I'm bringing ear plugs this year so my ears don't bleed from all of you screaming. Lol jk"
    __proto__: Object
    1: Object
    2: Object
    3: Object
    4: Object
    5: Object
    6: Object
    7: Object
    length: 8
    __proto__: Array[0]
    __proto__: Object
    created_time: "1391487831"
    filter: "Normal"
    id: "648169368524795843_181493434"
    images: Object
    likes: Object
    link: "http://instagram.com/p/j-wptFNa_D/"
    location: null
    tags: Array[1]
    type: "image"
    user: Object
    user_has_liked: false
    users_in_photo: Array[0]
    __proto__: Object
    length: 19
    __proto__: Array[0]
    meta: Object
    pagination: Object
    __proto__: Object

  6. #6
    Community Advisor bronze trophy
    fretburner's Avatar
    Join Date
    Apr 2013
    Location
    Brazil
    Posts
    1,397
    Mentioned
    45 Post(s)
    Tagged
    12 Thread(s)
    OK, so I've read over your code and had a look at the Instagram API docs to see what actually gets returned in the JSON response. I've made some changes to your code which should hopefully get it working the way you want (although I haven't been able to test it as I don't have an Instagram account or API key).

    First of all, add a grams object to your insta object, which we'll use to cache the data returned from the API:

    Code JavaScript:
    insta = {
     
        grams: {},
     
        // ...

    Next, within the renderGrams function, add this line of code to add each item to our cache object, using the ID as a key:

    Code JavaScript:
    $.each(grams, function(index, gram) {
        insta.grams[gram.id] = gram; // Add item to cache
        // ...

    and, change the modal link HTML so that it has a data attribute only for the item ID:

    Code JavaScript:
    <a href="#myModal" data-toggle="modal" data-media-id="' + gram.id +'">

    Next, within the setupClickEvent function, we need to grab the ID from the clicked link, and use that to pull the rest of the data from the cache:

    Code JavaScript:
    $('a').click(function(){
        var mediaId = $(this).data('mediaId'),
            gram = insta.grams[mediaId],
            largeImage = gram.images.standard_resolution.url,
            username = gram.user.username,
            tags = gram.tags,
            comments = '';

    then, at the bottom of the function, instead of making an extra AJAX call to get the comments, we'll pull the comments from the cache and loop over them, appending them to a string which we then inject into the page:

    Code JavaScript:
    $.each(gram.comments.data, function(index, comment){
        comments += '<p>' + comments.text + '</p>';
    });
     
    $('.comments-container').html(comments);
    I've created a gist of the whole thing, so you can see the changes in context: https://gist.github.com/anonymous/8810353

  7. #7
    SitePoint Member
    Join Date
    Feb 2013
    Posts
    13
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, I was aware of trying to store them in a data attribute. But is it bad to try to store all the comments for all the grams loaded on a page into that? Forgive my ignorance, but I thought it would be better to retrieve them upon click because of that. By default 18 instagram items are loaded on the page. Couldn't it add up to a lot of comments being stored in the cache? Maybe I need to look up the cache usage in the docs for json data like this (if I am understanding this correctly).

    How would we test speed of this type of web app to know what might be more efficient in code? I have never even performed tests on any code so thats a whole other world I assume.

    I really appreciate all the help everyone has contributed to this. My brain is trying to soak up everything!

    I tried the code from your gist, and something isnt working. No error messages in the console or anything. I noticed on line 44 in the gist -

    Code:
    comments += '<p>' + comments.text + '</p>';
    should there be an = after the + ? I removed it and code still didnt work.

  8. #8
    Community Advisor bronze trophy
    fretburner's Avatar
    Join Date
    Apr 2013
    Location
    Brazil
    Posts
    1,397
    Mentioned
    45 Post(s)
    Tagged
    12 Thread(s)
    Quote Originally Posted by clayton47 View Post
    Ok, I was aware of trying to store them in a data attribute. But is it bad to try to store all the comments for all the grams loaded on a page into that? Forgive my ignorance, but I thought it would be better to retrieve them upon click because of that. By default 18 instagram items are loaded on the page. Couldn't it add up to a lot of comments being stored in the cache?
    I wouldn't have thought it'd be a problem, but perhaps someone else could comment on that?

    Quote Originally Posted by clayton47 View Post
    How would we test speed of this type of web app to know what might be more efficient in code? I have never even performed tests on any code so thats a whole other world I assume.
    It's not so much to do with speed (although it does help) as cutting down the number of calls to the API - lots of APIs use rate limiting so it's good to economize on requests, especially if you're anticipating a lot of users.

    Quote Originally Posted by clayton47 View Post
    I tried the code from your gist, and something isnt working. No error messages in the console or anything. I noticed on line 44 in the gist -

    Code:
    comments += '<p>' + comments.text + '</p>';
    should there be an = after the + ? I removed it and code still didnt work.
    Ah, sorry, that's a typo. It should be:

    Code JavaScript:
    $.each(gram.comments.data, function(index, comment){
        comments += '<p>' + comment.text + '</p>';
    });

  9. #9
    SitePoint Member
    Join Date
    Feb 2013
    Posts
    13
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ah, sorry, that's a typo. It should be:

    Code JavaScript:
    $.each(gram.comments.data, function(index, comment){
        comments += '<p>' + comment.text + '</p>';
    });
    [/QUOTE]


    Thats the same as it was, is that correct syntax? I am still pretty new so some stuff I may not recognize being a noob.

    I am still not able to get it to work. I will pm you a client id.

  10. #10
    Community Advisor bronze trophy
    fretburner's Avatar
    Join Date
    Apr 2013
    Location
    Brazil
    Posts
    1,397
    Mentioned
    45 Post(s)
    Tagged
    12 Thread(s)
    Quote Originally Posted by clayton47 View Post
    Thats the same as it was, is that correct syntax?
    Sorry, I should have pointed out the difference.. I was referring to comments (plural) within the loop rather than comment .

    Quote Originally Posted by clayton47 View Post
    I am still not able to get it to work. I will pm you a client id.
    Thanks, I'll take a look.

  11. #11
    Community Advisor bronze trophy
    fretburner's Avatar
    Join Date
    Apr 2013
    Location
    Brazil
    Posts
    1,397
    Mentioned
    45 Post(s)
    Tagged
    12 Thread(s)
    Hey man,

    So, here's the updated gist: https://gist.github.com/anonymous/8813601

    I'd made another typo while working with the code (I changed insta.apiUrl to something else, and forgot to change it back), but there was also another problem with the comments container being overwritten every time a modal is created in the click handler.

    The code seems to work fine for me now.

  12. #12
    SitePoint Member
    Join Date
    Feb 2013
    Posts
    13
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Sweet, thanks it works!

    I implemented a bootstrap grid class and its styled a bit. One thing I noticed with my code is the items that are videos are not playing. It just displays the poster image for them like the rest of the images... Do we need to add to the click event for this to happen? The renderGrams function above that has -

    Code:
    if (gram.type === 'video') { gramHtml = gramHtml + '<video class="img-thumbnail" src="' + gram.videos.low_resolution.url + '"/>'; }
    On the code you have changed can you explain what you have done so I can understand better. Being that I am so new to jQuery, and especially ajax stuff its hard for me to just start building things I want. I want to know whats making things work.

  13. #13
    Community Advisor bronze trophy
    fretburner's Avatar
    Join Date
    Apr 2013
    Location
    Brazil
    Posts
    1,397
    Mentioned
    45 Post(s)
    Tagged
    12 Thread(s)
    Hi,

    Sorry for the delayed reply.

    Quote Originally Posted by clayton47 View Post
    Sweet, thanks it works!

    I implemented a bootstrap grid class and its styled a bit. One thing I noticed with my code is the items that are videos are not playing. It just displays the poster image for them like the rest of the images... Do we need to add to the click event for this to happen? The renderGrams function above that has -

    Code:
    if (gram.type === 'video') { gramHtml = gramHtml + '<video class="img-thumbnail" src="' + gram.videos.low_resolution.url + '"/>'; }
    I'm not that familiar with using video in the browser, but I think you can add the 'controls' attribute to the video tag to allow users to start/stop the video. So the above line would change to:

    Code:
    if (gram.type === 'video') { gramHtml = gramHtml + '<video class="img-thumbnail" src="' + gram.videos.low_resolution.url + '" controls />'; }
    Quote Originally Posted by clayton47 View Post
    On the code you have changed can you explain what you have done so I can understand better. Being that I am so new to jQuery, and especially ajax stuff its hard for me to just start building things I want. I want to know whats making things work.
    I didn't change much.. just the last line of the setupClickEvent function. Originally, the code was setting the contents of div.comments-container:

    Code JavaScript:
    $('.comments-container').html(comments);

    but the problem is you already overwrote the comment container markup a few lines previously, with this line:

    Code JavaScript:
    $('.modal-body').html('<div class="col-md-6"><img class="img-responsive" src="' + largeImage + '"><div class="tagwrap">' + tags + '</div></div>');

    So, I changed the last line of the function to wrap the comments in a new container div and append that to the modal body element:

    Code JavaScript:
    $('.modal-body').append('<div class="comments-container">'+comments+'</div>');

  14. #14
    SitePoint Member
    Join Date
    Feb 2013
    Posts
    13
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks again so much for the help. (I didnt get this message in my email that you replied until now. All my emails for replies to this thread were daaaaaaays behind). I am starting to get more familiar with this stuff. All the documentation, and tuts out there never cover unique things like this. They are always the ABC's of working with a language and their different functions etc... I have been building this lil simple app out and its fun and over educational at times doing what seems to me more advance stuff than what a noob like myself is capable of at the time. A little bit of help here helps jump start things and explains them really well. We have all been there before. We have something in our mind we want to do, but just cant seem to wrap our minds around the correct code!

    Thanks again for showing me a way to do what I was trying to get accomplished!


Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •