/*jquery.cascade.js */
/*
 * jQuery UI cascade
 * version: 1.1.1 (6/16/2008)
 * @requires: jQuery v1.2 or later
 * adapted from Yehuda Katz, Rein Henrichs autocomplete plugin
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Copyright 2008 Mike Nichols
 */
;(function($) {
  $.ui = $.ui || {};
  var cascade = $.ui.cascade = $.ui.cascade || {};

  $.fn.cascade = function(parent, opt) {
    if (opt.event) { //namespace our event 
      opt.event = opt.event.replace('.cascade', '') + '.cascade';
    }
    opt = $.extend({}, {
      //static list to use as datasource 
      list: [],
      //delay before firing getList operation
      timeout: 10,
      //function to fetch datasource
      getList: function(select) {
        $(this).trigger("updateList", [opt.list]);
      },
      //applied to each item in datasource      
      template: function(parentVal) {
        return "<option value='" + this + "'>" + this + "</option>";
      },
      //'this' is the js object, or the current list item from 'getList',
      match: function(selectedValue) {
        return true;
      },
      //event to listen on parent which fires the cascade
      event: "change.cascade",
      //delegate for retrieving the parent element's value
      getParentValue: function(parent) {
        return $(parent).val();
      }
    }, opt);

    if ($.ui.cascade.ext) {
      for (var ext in $.ui.cascade.ext) {
        if (opt[ext]) {
          opt = $.extend(opt, $.ui.cascade.ext[ext](opt));
          delete opt[ext];
        }
      }
    }

    var source = $(parent);
    return this.each(function() {
      var self = $(this);

      //bind any events in extensions to each instance
      if ($.ui.cascade.event) {
        for (var e in $.ui.cascade.event) {
          self.bind(e + ".cascade", [source], $.ui.cascade.event[e]);
        }
      }

      source.bind(opt.event, function() {
        self.trigger("loading.cascade", [source[0]]);

        var selectTimeout = $.data(self, "selectTimeout");
        if (selectTimeout) {
          window.clearInterval(selectTimeout);
        }
        $.data(self, "selectTimeout", window.setTimeout(function() {
          self.trigger("cascade");
        }, opt.timeout));

      });

      self.bind("cascade", function() {
        self.one("updateList", function(e, list) {
          var parentValue = opt.getParentValue.call(self, parent);
          var filteredList = $(list).filter(function() {
            return opt.match.call(this, parentValue);
          });

          self.empty(); //clear the source/select
          $(filteredList).each(function() {
            var newOption = opt.template.call(this, parentValue);
            self.append(newOption);
          });
          self.trigger("loaded.cascade", [source[0]]); //be sure to fire even if there is no data

          if (self.is(":input")) {
            self.trigger("change.cascade");
          }
        });

        opt.getList.call(self[0], source); //call with child element as this

      });
    });
  };

})(jQuery);