Options

Need some help getting started

wellmanwellman Registered Users Posts: 961 Major grins
I'm trying to write a little JS code that will ultimately place gallery-level Previous and Next buttons on my pages. In other words, if I'm viewing gallery Y within a particular category, I want links to galleries X and Z on the page, thus allowing users to reach those galleries w/o first having to return to the category page.

I've looked through the API help, and it seems like I could use the smugmug.albums.get method toward this goal. I just can't figure out how to call the method through JavaScript. I've looked through BigWebGuy's slideshow code and devbobo's bulk thumbnailer code, but neither seem to use the API, at least not to my novice eyes.

So, to wrap up, how do I make an API call through JS? Thanks!

Comments

  • Options
    devbobodevbobo Registered Users, Retired Mod Posts: 4,339 SmugMug Employee
    edited February 27, 2006
    Hi Greg,

    Unfortunately, the api is a lot of work, and I am not sure if it's the right way to go.

    You could achieve the same thing using an array of album numbers, obviously this approach isn't automatic and would require you to add a new gallery number to the array each time one was created.

    Otherwise, you could try the API, but you will first need to apply for an API key.

    Either way you decide to go, I can help you out with some code.

    Cheers,

    David
    David Parry
    SmugMug API Developer
    My Photos
  • Options
    bwgbwg Registered Users, Retired Mod Posts: 2,119 SmugMug Employee
    edited February 27, 2006
    devbobo wrote:
    Hi Greg,

    Unfortunately, the api is a lot of work, and I am not sure if it's the right way to go.

    You could achieve the same thing using an array of album numbers, obviously this approach isn't automatic and would require you to add a new gallery number to the array each time one was created.

    Otherwise, you could try the API, but you will first need to apply for an API key.

    Either way you decide to go, I can help you out with some code.

    Cheers,

    David

    15524779-Ti.gif

    the api is a big investment to get yourself into...

    the way that dev and i have been getting information back into our hacks is just by calling regular smugmug pages via XMLHttpRequest and then parsing out all the bits we need.

    I looked for a page that would have a list of galleries, but unfortunately the only thing i found requires that you're logged in. sorry ne_nau.gif
    Pedal faster
  • Options
    wellmanwellman Registered Users Posts: 961 Major grins
    edited February 28, 2006
    OK... I'll keep away from the API. Here's my next question. I'm trying to grab the contents of another page and stuff them into a string for parsing. (There may be a better way to do this, so feel free to correct anything.)

    I have this in my Javascript section:
    function getAlbumsInCategory()
    {
    var webServer = RegExp.$1;
    ajax_query(procAlbumsInCategory, webServer+'/Family', null, true);
    }
    function procAlbumsInCategory(response)
    {
    var str = new String(response);
    var objElement = document.getElementById("gwGalleryNav")
    objElement.innerHTML = str; 
    }
    

    And I have this in my footer:
    // Test GalleryNavigator
    var objElement = document.getElementById("gwGalleryNav")
    if (objElement != null)
    {
      getAlbumsInCategory();
    }
    

    I have a test gallery here, where I have a blank div ID'd gwGalleryNav. When I bring up the test gallery, I can see that something is going on by watching status messages fly by in the status bar, but I don't get the contents of the called page shown to me.

    What am I borking? Thanks!
  • Options
    bwgbwg Registered Users, Retired Mod Posts: 2,119 SmugMug Employee
    edited February 28, 2006
    wellman wrote:
    OK... I'll keep away from the API. Here's my next question. I'm trying to grab the contents of another page and stuff them into a string for parsing. (There may be a better way to do this, so feel free to correct anything.)

    I have this in my Javascript section:<snip>

    I have a test gallery here, where I have a blank div ID'd gwGalleryNav. When I bring up the test gallery, I can see that something is going on by watching status messages fly by in the status bar, but I don't get the contents of the called page shown to me.

    What am I borking? Thanks!
    dang, you made me look STOOOPID! of course, just call the category name! clap clap.

    anyways, try a firefox extension called FireBug. it lets you see the XMLHttpResponse calls and responses. Saves you from having to try and put it in an element on your page. I can see your response just fine.
    Pedal faster
  • Options
    wellmanwellman Registered Users Posts: 961 Major grins
    edited February 28, 2006
    bigwebguy wrote:
    anyways, try a firefox extension called FireBug. it lets you see the XMLHttpResponse calls and responses. Saves you from having to try and put it in an element on your page. I can see your response just fine.

    Sweet! Thanks for the extension. I don't have FF at work, so it will be a while before I'm able to do much. Hopefully more to come...
  • Options
    wellmanwellman Registered Users Posts: 961 Major grins
    edited February 28, 2006
    OK. I have the FireBug extension, and I see that I'm getting a response, which looks like the HTML of the category page. This is what I was hoping for. What I'm having trouble with now is parsing the text.

    BWG, in your slideshow code, your slideshowHandler function looks like it's doing some parsing of a response and chunking the data into arrays. This is pretty much what I'd like to do, only I can't figure out the meaning of the re, re2, and re3 variables. (Maybe some character-escaping madness?) Is there a tutorial somewhere that would help me out with this task?

    TIA...
  • Options
    bwgbwg Registered Users, Retired Mod Posts: 2,119 SmugMug Employee
    edited February 28, 2006
    wellman wrote:
    OK. I have the FireBug extension, and I see that I'm getting a response, which looks like the HTML of the category page. This is what I was hoping for. What I'm having trouble with now is parsing the text.

    BWG, in your slideshow code, your slideshowHandler function looks like it's doing some parsing of a response and chunking the data into arrays. This is pretty much what I'd like to do, only I can't figure out the meaning of the re, re2, and re3 variables. (Maybe some character-escaping madness?) Is there a tutorial somewhere that would help me out with this task?

    TIA...
    those are regular expressions....and i have a love/hate relationship with them. Devbobo's the regex man. he's the one who wrote the expressions in slideshow. and as much as i dislike writing them, they are the best way to parse that response.

    there are a ton of regex tutorials out on the web
    Pedal faster
  • Options
    wellmanwellman Registered Users Posts: 961 Major grins
    edited February 28, 2006
    bigwebguy wrote:
    those are regular expressions....and i have a love/hate relationship with them. Devbobo's the regex man. he's the one who wrote the expressions in slideshow. and as much as i dislike writing them, they are the best way to parse that response.

    there are a ton of regex tutorials out on the web

    Thanks. I've heard that term before; looks like I get to do some learning. :):
  • Options
    devbobodevbobo Registered Users, Retired Mod Posts: 4,339 SmugMug Employee
    edited February 28, 2006
    wellman wrote:
    OK. I have the FireBug extension, and I see that I'm getting a response, which looks like the HTML of the category page. This is what I was hoping for. What I'm having trouble with now is parsing the text.

    BWG, in your slideshow code, your slideshowHandler function looks like it's doing some parsing of a response and chunking the data into arrays. This is pretty much what I'd like to do, only I can't figure out the meaning of the re, re2, and re3 variables. (Maybe some character-escaping madness?) Is there a tutorial somewhere that would help me out with this task?

    TIA...

    Greg,

    if your having trouble, post some examples of what you are tryiny to parse and I will write some regexps for you.

    Cheers,

    David
    David Parry
    SmugMug API Developer
    My Photos
  • Options
    wellmanwellman Registered Users Posts: 961 Major grins
    edited March 1, 2006
    OK... I'm getting somewhere. I can see with FireBug that I'm receiving the HTML of the category page I'm calling as the response from the ajax_query function. Now I need to do something with this HTML - parse it.

    It looks like my best bet will be to use the albumTitle_XXXXXXX id attribute as a means of collecting gallery numbers. On category pages, the sample photo and the title are in separate link tags, meaning I'd get dupicates if I searched for href=/gallery/XXXXXXX strings. Also, I'm thinking using the albumTitle_XXXXXXX id will eliminate false hits from other links in people's headers, etc.

    So, I need a regular expression to search for this. I think this is an easy one. I then need to match regexp to the response and eliminate the extraeneous portion of the matched string to get just the number. Does the code below look OK?
    [SIZE=2]var re = /albumTitle_(\d+)/;
    var strMatch = response.match(re);
    strMatch = strMatch.substr(11);[/SIZE]
    

    So finally, here's my real question. After I find the first match, how do I march through the rest of the response to find them all and build an array?

    Thanks!
  • Options
    wellmanwellman Registered Users Posts: 961 Major grins
    edited March 1, 2006
    Well, I think I have a procedure in my head for obtaining an array of the gallery numbers. Here goes...
    1. Define the regexp such as above (which will match albumTitle_XXXXXXX)
    2. Use the split() method on the response along with the regexp as my "delimiter". This will give me an array of the extra stuff between the matches.
    3. Loop through the elements of the array, using each along with a replace() call, operating on the original response string. Use some common delmiter for the replacement, like a comma. This gives me a comma-delimited string of albumTitle_XXXXXXX's.
    4. Use the split() method again, this time with a comma, to get an array.
    5. substr() away the albumTitle_ portion of each element.
    What would be truly sweet is if there were a "NOT" operator for regexps. That way I could apply the NOT to the albumTitle_XXXXXXX expression, call the split() method on the response, and end up with the final array after only one function call. The "delimiter" for the split() would in effect be "anything other than albumTitle_XXXXXXX." Is there such a thing as an anti-regexp? :D
  • Options
    devbobodevbobo Registered Users, Retired Mod Posts: 4,339 SmugMug Employee
    edited March 1, 2006
    [SIZE=2]var re = /albumTitle_(\d+)/;
    var strMatch = response.match(re);
    strMatch = strMatch.substr(11);[/SIZE]
    

    Greg,

    In this scenario, RegExp.$1 will return the album number.

    David
    David Parry
    SmugMug API Developer
    My Photos
  • Options
    devbobodevbobo Registered Users, Retired Mod Posts: 4,339 SmugMug Employee
    edited March 1, 2006
    wellman wrote:
    Well, I think I have a procedure in my head for obtaining an array of the gallery numbers. Here goes...
    1. Define the regexp such as above (which will match albumTitle_XXXXXXX)
    2. Use the split() method on the response along with the regexp as my "delimiter". This will give me an array of the extra stuff between the matches.
    3. Loop through the elements of the array, using each along with a replace() call, operating on the original response string. Use some common delmiter for the replacement, like a comma. This gives me a comma-delimited string of albumTitle_XXXXXXX's.
    4. Use the split() method again, this time with a comma, to get an array.
    5. substr() away the albumTitle_ portion of each element.
    What would be truly sweet is if there were a "NOT" operator for regexps. That way I could apply the NOT to the albumTitle_XXXXXXX expression, call the split() method on the response, and end up with the final array after only one function call. The "delimiter" for the split() would in effect be "anything other than albumTitle_XXXXXXX." Is there such a thing as an anti-regexp? :D

    Try something like this...
    var src = "this is a test albumTitle_123455 blah blah albumTitle_987654";
    
    re = /albumTitle_(\d+)/g;
    
    while (re.exec(src) != null)
      alert(RegExp.$1);
    
    

    The RegExp.$1 variable contains the album number, so do whatever you want with it.

    Hope this is the kinda thing ur after.

    Cheers,

    David
    David Parry
    SmugMug API Developer
    My Photos
  • Options
    wellmanwellman Registered Users Posts: 961 Major grins
    edited March 1, 2006
    devbobo wrote:
    Try something like this...
    var src = "this is a test albumTitle_123455 blah blah albumTitle_987654";
     
    re = /albumTitle_(\d+)/g;
     
    while (re.exec(src) != null)
      alert(RegExp.$1);
     
    

    The RegExp.$1 variable contains the album number, so do whatever you want with it.

    Hope this is the kinda thing ur after.

    Cheers,

    David

    Ah, so that's what the RegExp.$1 is... Thanks very much. I have a busy few days coming up, so it will likely be a while before I get to work on an implementation. Hopefully I'll get something concrete done over the weekend.
  • Options
    wellmanwellman Registered Users Posts: 961 Major grins
    edited March 6, 2006
    Well, I've hit a wall. Using devbobo's suggestions, I have the following little script being called on this page.
    function getAlbumsInCategory()
    {
      ajax_query(procAlbumsInCategory, 'http://wellman.smugmug.com/Family', null, true);
    }
    function procAlbumsInCategory(response)
    {
      re = /albumTitle_(\d+)/g;
      while (re.exec(URLDecode(response)) != null)
        alert(RegExp.$1);
    }
    

    I thought that would give me a series of gallery numbers popping up in little windows, just to verify that the response was getting loaded. The regexp-parsing sample code devbobo gave me worked just fine when I subbed in my own "fake" source, but when I try to pass the response variable, no worky-worky. :cry What am I doing wrong? Sorry for the silly question...
  • Options
    bwgbwg Registered Users, Retired Mod Posts: 2,119 SmugMug Employee
    edited March 6, 2006
    wellman wrote:
    Well, I've hit a wall. Using devbobo's suggestions, I have the following little script being called on this page.
    function getAlbumsInCategory()
    {
      ajax_query(procAlbumsInCategory, 'http://wellman.smugmug.com/Family', null, true);
    }
    function procAlbumsInCategory(response)
    {
      re = /albumTitle_(\d+)/g;
      while (re.exec(URLDecode(response)) != null)
        alert(RegExp.$1);
    }
    
    I thought that would give me a series of gallery numbers popping up in little windows, just to verify that the response was getting loaded. The regexp-parsing sample code devbobo gave me worked just fine when I subbed in my own "fake" source, but when I try to pass the response variable, no worky-worky. :cry What am I doing wrong? Sorry for the silly question...

    greg, try taking the slideshow code out and see what happens.

    what you're describing is kinda what is happening on safari with the slideshow...the response from the httprequest is blank...maybe there's a common thread in here somewhere.
    Pedal faster
  • Options
    devbobodevbobo Registered Users, Retired Mod Posts: 4,339 SmugMug Employee
    edited March 6, 2006
    Greg,

    this code works for me...

    footer code....
    if (isClass('category'))
    {
      re1 = /category_(\S+)/;
      re1.exec(document.body.className);
    
      getAlbumsInCategory(RegExp.$1);
    }
    

    javascript code...
    function isClass(sClass)
    {
      sClassName = document.body.className;
    
      re = new RegExp(sClass + "( |$)") 
    
      if (!sClassName)
        return false;
      return re.test(sClassName);
    }
    
    function getAlbumsInCategory(sCategory)
    {
      var re = /category_(\S+)/;
      re.exec(document.body.className);
      ajax_query(procAlbumsInCategory, webServer+"/"+sCategory, null, true);
    }
    
    function procAlbumsInCategory(response)
    {
      var re = /id="albumTitle_(\d+)/g;
      response = URLDecode(response);
      while (re.exec(response) != null)
        alert(RegExp.$1);
    }
    
    this code doesn't cater for subcategories, but it should be pretty simple to do that.

    Cheers,

    David
    David Parry
    SmugMug API Developer
    My Photos
  • Options
    wellmanwellman Registered Users Posts: 961 Major grins
    edited March 7, 2006
    bigwebguy wrote:
    greg, try taking the slideshow code out and see what happens.

    BWG:
    When I remove the slideshow code, devbobo's code works. When I put the SS code back in, it borks. I can't see much about the JS since I'm on IE at work, but I can tell you that it gives me this error:

    s.length is null or not an object

    Hope this helps somewhat.

    Devbobo, thanks! I think I'm getting lots of "false positives" for the first few matches due to the customization not being "internalized" by smugmug yet. I have the code commented out on my site for the time being - until I get time to do something with the results. Thanks again!
  • Options
    devbobodevbobo Registered Users, Retired Mod Posts: 4,339 SmugMug Employee
    edited March 7, 2006
    wellman wrote:
    BWG:
    When I remove the slideshow code, devbobo's code works. When I put the SS code back in, it borks. I can't see much about the JS since I'm on IE at work, but I can tell you that it gives me this error:

    s.length is null or not an object

    Hope this helps somewhat.

    Devbobo, thanks! I think I'm getting lots of "false positives" for the first few matches due to the customization not being "internalized" by smugmug yet. I have the code commented out on my site for the time being - until I get time to do something with the results. Thanks again!
    Greg,

    Make sure that the function isClass isn't defined twice, as it was used with the slideshow code...i think.

    Cheers,

    David
    David Parry
    SmugMug API Developer
    My Photos
  • Options
    wellmanwellman Registered Users Posts: 961 Major grins
    edited March 7, 2006
    Well, I have a crude impementation of GalleryNavigator up and running. :): Thanks to all the awesome comments from devbobo and bigwebguy. Comments, corrections, etc appreciated - I'm sure there's lots of room for improvement, especially in user-friendliness and code stability.

    The code basically adds links to the trailing end of the breadcrumb. The links are to the galleries (within the same category) adjacent to the one currently being viewed. If the first or last gallery is being viewed, only one link is shown. Demo here.

    Known issues:
    1. It's slow to load for categories with large numbers of galleries due to all the background parsing. I'm guessing one solution to this might be to save the array of gallery IDs in a cookie after the first parsing, but I don't know how to do that. :cry
    2. Funky category names might bork the code. I'm handling spaces (ie My Buddies) and ampersands (ie Me & My Buddies), but other patterns might break the string transformation.

    So here goes...

    javascript:
    function isBodyClass(sClass)
    {
    sClassName = document.body.className;
    re = new RegExp(sClass + "( |$)")
    if (!sClassName) return false;
    return re.test(sClassName);
    }
    function getAlbumsInCategory(sCategory)
    {
    ajax_query(procAlbumsInCategory, webServer+"/"+sCategory, null, true);
    }
    function procAlbumsInCategory(response)
    {
    // Set up variables
    arrGalleryID = new Array();
    var re = /id="albumTitle_(\d+)/g;
    // Find all matches
    i=0;
    while (re.exec(response) != null)
    {
    arrGalleryID = RegExp.$1;
    i++;
    }
    N=i;
    // Get current gallery ID
    var re2 = /gallery_(\d+)/;
    re2.exec(document.body.className);
    var sCurGalleryID = RegExp.$1
    // Find adjacent gallery IDs

    for (i=0; i<N; p i++) <> if (arrGalleryID == sCurGalleryID)
    break;
    // Define texts
    var sGnLeadingText = ' (';
    var sGnSpacerText = ' | ';
    var sGnTrailingText = ')';
    var sGnPrevText = '«Older';
    var sGnNextText = 'Newer»';
    // Construct links

    if (i+1<N) p <> sGnPrevText = ''+sGnPrevText+'';
    else
    sGnPrevText = '';
    if (i-1>=0)
    sGnNextText = ''+sGnNextText+'';
    else
    sGnNextText = '';
    if (sGnPrevText == '' || sGnNextText == '')
    sGnSpacerText = '';
    // Alter breadcrumb text
    var objGnEdit = document.getElementById("albumTitle");
    var sGnTemp = objGnEdit.innerHTML;
    sGnTemp = sGnTemp+''+sGnLeadingText+sGnPrevText+sGnSpacerText+sGnNextText+sGnTrailingText+'';
    objGnEdit.innerHTML = sGnTemp;
    }

    Footer (in script tags):
    // GalleryNavigator
    if (isBodyClass('galleryPage'))
    {
    re1 = /category_(\S+)/;
    re1.exec(document.body.className);

    sCategory = new String(RegExp.$1);
    sCategory = sCategory.replace(/__/, " & ");
    sCategory = sCategory.replace(/_/, ' ');
    getAlbumsInCategory(sCategory);
    }


    CSS:
    #galleryNavigator {
    font-weight:normal;
    color: #000;
    }

    I'd love to hear improvement ideas. This is pretty much what I'd envisioned for my own needs, but it could use a lot of "generification."
  • Options
    wellmanwellman Registered Users Posts: 961 Major grins
    edited March 7, 2006
    BWG:

    I was able to get whatever conflict there was between the SlideShow code and the GalleryNavigator code worked out by placing the loadSlideshow() funcrtion in an "if" in my footer like below:
    if (isBodyClass('homepage'))
    loadSlideshow();
    

    The isBodyClass() function is adapted from devbobo's isClass() function (actually not a bit different):
    function isBodyClass(sClass) 
    {
      sClassName = document.body.className;
      re = new RegExp(sClass + "( |$)") 
      if (!sClassName) return false;
      return re.test(sClassName);
    }
    

    Maybe simultaneous ajax calls were being made by your code and mine and the responses got crossed? The slideshow didn't need to load anywhere for me but the homepage, so this fix works fine. Don't know what would happen if you wanted to have a slideshow and these gallery links in the same gallery, though...
  • Options
    bwgbwg Registered Users, Retired Mod Posts: 2,119 SmugMug Employee
    edited March 7, 2006
    wellman wrote:
    BWG:

    I was able to get whatever conflict there was between the SlideShow code and the GalleryNavigator code worked out by placing the loadSlideshow() funcrtion in an "if" in my footer like below:
    if (isBodyClass('homepage'))
    loadSlideshow();
    
    The isBodyClass() function is adapted from devbobo's isClass() function (actually not a bit different):
    function isBodyClass(sClass) 
    {
      sClassName = document.body.className;
      re = new RegExp(sClass + "( |$)") 
      if (!sClassName) return false;
      return re.test(sClassName);
    }
    
    Maybe simultaneous ajax calls were being made by your code and mine and the responses got crossed? The slideshow didn't need to load anywhere for me but the homepage, so this fix works fine. Don't know what would happen if you wanted to have a slideshow and these gallery links in the same gallery, though...
    greg, i think you may have just solved our safari bug too.....clap.gif (i knew if i procrastinated long enough someone would. heh)

    it's odd though. the slideshow should exit if the specified slideshowContainerId isn't found. hmm....

    looks great by the way, very cool idea.thumb.gif
    Pedal faster
  • Options
    devbobodevbobo Registered Users, Retired Mod Posts: 4,339 SmugMug Employee
    edited March 7, 2006
    wellman wrote:
    BWG:

    I was able to get whatever conflict there was between the SlideShow code and the GalleryNavigator code worked out by placing the loadSlideshow() funcrtion in an "if" in my footer like below:
    interesting headscratch.gif

    when I first wrote that code for you, I did it like this....
    if (isClass('category'))
    {
      getAlbumsInCategory();
    }
    
    function getAlbumsInCategory()
    {
      var re = /category_(\S+)/;
      re.exec(document.body.className);
      ajax_query(procAlbumsInCategory, webServer+"/"+RegExp.$1, null, true);
    }
    
    function procAlbumsInCategory(response)
    {
      var re = /id="albumTitle_(\d+)/g;
      response = URLDecode(response);
      while (re.exec(response) != null)
        alert(RegExp.$1);
    }
    
    in FF, it would only return the first RegExp.$1 in procAlbumsInCategory(), while it worked fine in IE. I tried numerous methods, and found that passing the variable into getAlbumsInCategory() was the only way it would work properly.

    This may or may not be related, but I thought it would be worth mentioning. ne_nau.gif

    The hack looks great Greg, you have done an awesome job, my only comment....i don't like the way it makes the breadcrumb wrap onto another line, personally, I would like to see it under the breadcrumb.

    Cheers,

    David
    David Parry
    SmugMug API Developer
    My Photos
Sign In or Register to comment.