// Allow CSS to prevent the initial flash of content before the DOM is ready.
$('html').addClass('js');

// Plug-in function to apply appropriate classes to clickable <div> or <span> elements.
$.fn.makeClickable = function(callback1, callback2) {
  $(this)
    .addClass('clickable')
    .hover(function() {
      $(this).addClass('hover');
    }, function() {
      $(this).removeClass('hover');
    });
  if (callback2 == null) {
    return $(this).click(callback1);
  }
  else {
    return $(this).toggle(callback1, callback2);
  }
};

// The following code executes once, after the DOM is fully loaded.
$(document).ready(function() {
  $('body').addClass('product-finder');

  $('<div class="ad"></div>').appendTo('#product-results').load('ads/index.htm');

  $('.product-search-criterion').hide();

  $('.product-search-criterion h4').each(function() {
    var $criterionName = $(this);
    var $criterion = $criterionName.parent();
    
    $criterionName
      .insertBefore('#product-search-criteria-names *:last')
      .makeClickable(function() {
        resetSearch();
        $(this).siblings().removeClass('selected').end().addClass('selected');
        $('.product-search-criterion').hide();
        $criterion.slideDown();
      });
  });
  
  // Plug-in to create a "hierarchy name" from one of the displayed trees.
  // This is the counterpart to the "printCategoryTree()" function in the Perl
  // code that generates the page.
  $.fn.hierarchyName = function() {
    return $(this)
      .add($(this).parents('li')).find('> span')
      .map(function(){
        return $(this).text();
      })
      .get()
      .reverse()
      .join(' - ');
  };
  
  // Clear all the search results when the user does something like switch their
  // search type.
  function resetSearch() {
    resetFilter();
    $('.product-search-criterion li').removeClass('selected');
    $('.product-result').removeClass('found');
    $('.product-result-category').hide();
    // $('#product-results > .ad').show();
  }
  
  // Show the categories that have visible products. This includes preparing
  // the filter selections for the revealed categories.
  function revealCategories(filterType) {
    $('.product-result-category').hide();
    $('.product-result-category:has(.product-result:visible)')
      .show()
      .each(function() {
        var $category = $(this);
        $category.find('.product-filter').empty();
        
        // The filter box is only applicable if at least two products are in
        // the category.
        if ($category.find('.product-result:visible').length > 1) {
          var filterLabel = filterType == 'product-search-applications' ? 'Application' : 'Product Type';
          var $filterHeader = $('<h4>Filter by ' + filterLabel + '</h4>').makeClickable(function() {
            var $filter = $('#' + filterType).clone().removeAttr('id').insertAfter(this);
            $filter.find('*').removeClass().show();
            $filter.find('li').hide();
          
            var found = {};
            $category.find('.product-result.found ul.' + filterType + ' li').each(function() {
              var text = $(this).text();
              if (found[text]) return;
              found[text] = true;

              var $item = $filter;
              $.each(text.split(' - '), function(index, value) {
                $item = $item.find('> ul > li').filter(function() {
                  return $(this).find('> span').text() == value;
                }).show();
              });
            });
          
            // Handle clicks on the leaf nodes within the filter dropdown. A
            // click here adds the "filtered" class to appropriate products,
            // hiding them from view.
            $filter.find('li:visible:not(:has(li))').makeClickable(function() {
              var $filterItem = $(this);
              var $results = $category.find('.product-result');
              var value = $filterItem.hierarchyName();

              // Highlight the selected item.
              $filter.find('li').removeClass('selected');
              $filterItem.addClass('selected');

              // Show the correct products.
              $results
                .addClass('filtered')
                .filter(function() {
                  var found = false;
                  $(this).find('ul.' + filterType + ' li').each(function() {
                    found = found || $(this).text() == value;
                  });
                  return found;
                })
                .removeClass('filtered');
            });

            $(this).addClass('selected');
            $filter.slideDown();
          }, function() {
            $(this).removeClass('selected').next().remove();
            resetFilter();
          });
          $category.find('.product-filter').append($filterHeader);
        }
        
        $category.find('a.ajax').each(function() {
          $(this).parent().load($(this).attr('href'));
        });
      });
    
    $('.product-result-category h3').removeClass('expanded');
    $('.product-result-category-contents').hide();
    if ($('.product-result-category:visible').length == 1) {
      $('.product-result-category:visible h3').addClass('expanded');
      $('.product-result-category:visible .product-result-category-contents').show();
    }
  }
  
  // Reset the filter, showing all products for the category. Called when the
  // user does something like collapsing the filter box.
  function resetFilter() {
    $('.product-search-filter li').removeClass('selected');
    $('.product-result').removeClass('filtered');
  }

  // Handle clicks on the leaf-level product criteria. Clicks here need to
  // reveal the appropriate categories in the results column.
  $('.product-search-criterion li:not(:has(li))').makeClickable(function() {
    resetSearch();

    var $searchItem = $(this);
    
    // Highlight the selected item.
    $searchItem.addClass('selected');
    $('.product-search-criterion > ul > li > ul:not(:has(.selected))').slideUp();
    
    var key = $searchItem.parents('.product-search-criterion').attr('id');
    var value = $searchItem.hierarchyName();
    
    $('#product-results > .ad').hide();

    // A small timeout here allows the waiting indicator to show in IE before
    // the browser starts thinking about what to do.
    $('#product-finder-wait').show();
    setTimeout(function() {
      // Show the correct products.
      $('.product-result').filter(function() {
        var found = false;
        $(this).find('ul.' + key + ' li').each(function() {
          found = found || $(this).text() == value;
        });
        return found;
      }).addClass('found');
    
      // Show categories with visible products.
      revealCategories(key == 'product-search-applications' ? 'product-search-types' : 'product-search-applications');

      $('#product-finder-wait').hide();
    }, 100);
    return false;
  });
  
  // Non-leaf-level product criteria just slide their descendants up and down,
  // accordion-style.
  $('.product-search-criterion > ul > li:not(.clickable)').each(function() {
    $(this).children('ul').hide();
    $(this).makeClickable(function() {
      var $searchItem = $(this);
      resetSearch();

      $searchItem.addClass('selected');
      $searchItem.siblings().children('ul:visible').slideUp();
      $searchItem.children('ul').slideDown();
      return false;
    });
  });

  // Clicks on the result category headers collapse and expand the category
  // contents.
  $('.product-result-category h3').makeClickable(function() {
    if ($(this).hasClass('expanded')) {
      $(this).removeClass('expanded');
      $(this).next('.product-result-category-contents').slideToggle();
    }
    else {
      $(this).addClass('expanded');
      $(this).next('.product-result-category-contents').slideDown();
    }
  });
});

$(document).ready(function(){
$('#product-search-criteria-names h4:first').addClass("finder-left-corner");
$('#product-search-criteria-names h4:last').addClass("finder-right-corner");
});