2
\$\begingroup\$

I am designing a website for a company that manages buildings/real estate. I did not have much use for a CSS library like Bootstrap or Foundation, except on one page of the website. This page contains a list of selected buildings. When a user clicks on the name of a building, the building's information appears and images of the building appear in a Bootstrap image carousel. I used AJAX to GET the images of a property and then prototyped an object for each property on the list-- easy way to replace the text on-screen.

Below is the JavaScript & jQuery code that makes this happen:

//for bootstrap carousel

$('.carousel').carousel();

//stores the building currently displayed, for swap function below.
var currentBuilding;

//constructor for Building

function Building(title, background, story, images, stats){
    this.title = title;
    this.background = background;
    this.story = story;
    //images references directory where this building's images are located:
    this.images = images; 
    this.stats = stats;
}


//example object

var azusa = new Building(
    "Azusa, CA",
    "The company purchased a building in 2006 with a 20-year loan at 2% interest.",
    "The lot used to be the site of a mini-mall with tenants such as McDonalds and Costco",
    "azusa-california",
    "10,000 sqft");


//bind to onclick for list items. Given a Building (e.g. azusa above),
//place the most recently clicked Building's information on the page.

function swap(building){
    event.preventDefault();
    if(currentBuilding != building) {
        currentBuilding = building;
        $("h3:first").fadeOut(400,function(){
            $("h3:first").html(building.title);
            $("h3:first").fadeIn(400,function(){});
        });
        $("#background p:first").fadeOut(400,function(){
            $("#background p:first").html(building.background);
            $("#background p:first").fadeIn(400,function(){});
        });
        $('#carousel-container').fadeOut(400,function(){
            grabImages(building.images); //see function below
            $('#carousel-container').fadeIn(400,function(){});
        });
        $("#story p:first").fadeOut(400,function(){
            $("#story p:first").html(building.story);
            $("#story p:first").fadeIn(400,function(){});
        });
        $("#stats p:first").fadeOut(400,function(){
            $("#stats p:first").html(building.stats);
            $("#stats p:first").fadeIn(400,function(){});
        });
    }
}
function grabImages(folder){
    var dir = "img/selected-buildings-slides/"+folder;
    var fileextension = ".jpg";
    $.ajax({
        //This will retrieve the contents of the folder if the folder is configured as 'browsable'
        url: dir,
        type: "GET",

        success: function (data) {
            var nth = 0;
            var active=" active";
            $('.carousel-inner').html("");
            //Lsit all png file names in the page
            $(data).find("a:contains(" + fileextension + ")").each(function () {
                if(nth>0){
                    $('.carousel-indicators').append("<li data-target='#property-carousel' data-slide-to='"+nth+"'></li>")
                    active=""
                }
                else{
                    $('.carousel-indicators').html("<li class='active' data-target='#property-carousel' data-slide-to='0'></li>");

                }
                var filename = this.href.replace(window.location.host, "").replace("http://", "");

                $('.carousel-inner').append("<div class='item"+active+"'> <img src ='"+dir+filename+"' alt='property photo'></div>");
                nth++;
            });
        }
    });
}

Now, I am sure you are looking at that grabImages() function and cringing. I know it looks messy, but it works. Really I am looking to see if there is a way to sidestep AJAX without having to reference the explicit path to each individual image, because the image files have arbitrary names.

Also, if there is a way to wait for the images to fully load in grabImages() before displaying them, that would be cool too.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I can't see what's kicking this all off. What is calling swap? \$\endgroup\$
    – Jivings
    Apr 16, 2014 at 17:55
  • \$\begingroup\$ i did the binding in the HTML, sorry! just an <a href="#" onclick="swap(azusa)"> tag \$\endgroup\$ Apr 16, 2014 at 18:55

1 Answer 1

1
\$\begingroup\$

Let's start by removing that inline JS call. Let's use the href to indicate the building. We'll remove the hash later. We also add a class to find these links to attach event handlers:

<a href="#azusa" class="swap-trigger">Azusa</a>

As for the script:

;(function ($) {

  // Cache the fetched elements. Unless they are dynamic, they're better off fetched
  // once and reused rather than fetching them from the DOM every function call.
  var header = $("h3:first");
  var background = $("#background p:first");
  var carouselContainer = $('#carousel-container');
  var story = $("#story p:first");
  var stats = $("#stats p:first");
  var carousel = $('.carousel').carousel();
  var carouselInner = $('.carousel-inner');
  var carouselIndicators = $('.carousel-indicators');
  var fileextension = ".jpg";

  // We store building data here in a hash. The key will match the href that we placed
  // in the links.
  var buildings = {
    'azusa': {
      title: 'Azusa, CA',
      background: 'The company purchased a building in 2006 with a 20-year loan at 2% interest.',
      story: 'The lot used to be the site of a mini-mall with tenants such as McDonalds and Costco',
      images: 'azusa-california',
      stats: '10,000 sqft'
    },
    ...
  };

  // Now we attach a click handler to the links
  $('.swap-trigger').on('click', function (event) {
    event.preventDefault();
    var building = $(this).attr('href').slice(1); //chop of the hash
    swap(building);
  });

  // Your swap function
  function swap(building) {

    // We can store state data into the element itself using .data()
    // That way, we avoid creating a variable for it. The data is saved in the
    // respective element.
    var currentBuilding = carousel.data('currentBuilding');
    if (currentBuilding === building) return;
    carousel.data('currentBuilding', currentBuilding);

    // Using the cached elements
    header.fadeOut(400, function () {
      header.html(building.title).fadeIn(400)
    });
    background.fadeOut(400, function () {
      background.html(building.background).fadeIn(400)
    });
    carouselContainer.fadeOut(400, function () {
      grabImages(building.images);
      carouselContainer.fadeIn(400)
    });
    story.fadeOut(400, function () {
      story.html(building.story).fadeIn(400)
    });
    stats.fadeOut(400, function () {
      stats.html(building.stats).fadeIn(400)
    })
  }

  function grabImages(folder) {
    var dir = "img/selected-buildings-slides/" + folder;

    // Shorthand AJAX GET
    $.get(dir, function (data) {

      var active = " active";
      carouselInner.html('');
      $(data).find("a:contains(" + fileextension + ")").each(function (index,element) {

        //nth was of no use since .each() provides an index on every iteration.
        if (index === 0) {
          carouselIndicators.html("<li class='active' data-target='#property-carousel' data-slide-to='0'></li>");
        } else {
          carouselIndicators.append("<li data-target='#property-carousel' data-slide-to='" + index + "'></li>");
          active = "";
        }
        var filename = this.href.replace(window.location.host, "").replace("http://", "");
        carouselInner.append("<div class='item" + active + "'> <img src ='" + dir + filename + "' alt='property photo'></div>");
      });

    // jQuery sometimes fails to parse correctly, so we make sure
    }, 'html');
  }


}(jQuery));

Can't verify if this actually works, but the mentioned changes should help the code. Also, I can see that the code you have only works for a single link-carousel combination. If there were more than one, then I can sense that it will break. Consider scenarios where there's more than one set.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.