﻿/*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 || {}; $.ui.cascade = $.ui.cascade || {};

    $.fn.cascade = function (parent, opt) {
        if (opt.event) {
            //namespace our event 
            opt.event = opt.event.replace('.cascade', '') + '.cascade';
        }

        opt = $.extend({}, {
            list: [], //static list to use as datasource 
            timeout: 10, //delay before firing getList operation
            getList: function (select) { $(this).trigger("updateList", [opt.list]); }, //function to fetch datasource
            template: function (str) { return "<option value='" + str + "'>" + str + "</option>"; }, //applied to each item in datasource      
            match: function (selectedValue) { return true; }, //'this' is the js object, or the current list item from 'getList',
            event: "change.cascade", //event to listen on parent which fires the cascade
            getParentValue: function (parent) { return $(parent).val(); } //delegate for retrieving the parent element's value
        }, 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];
                }
            }
        }

        return this.each(function () {
            var source = $(parent);
            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) {
                    list = $(list)
              .filter(function () { return opt.match.call(this, opt.getParentValue(parent)); })
              .map(function () {
                  var node = $(opt.template(this))[0];
                  return node;
              });

                    self.empty(); //clear the source/select

                    if (list.length) {
                        self.html(list);
                    }

                    self.trigger("loaded.cascade", [source[0]]); //be sure to fire even if there is no data

                    if (self.is(":input")) { //opinionated , but  enables cascading from this element as  well
                        self.trigger("change.cascade");
                    }
                });

                opt.getList.call(self[0], source); //call with child element as this

            });
        });
    };

})(jQuery);
