/**
 * Autocompleter
 *
 * http://digitarald.de/project/autocompleter/
 *
 * @version      1.1.2
 *
 * @license      MIT-style license
 * @author      Harald Kirschner <mail [at] digitarald.de>
 * @copyright   Author
 */

var Autocompleter2 = new Class({

   Implements: [Options, Events],

   options: {/*
      onOver: $empty,
      onSelect: $empty,
      onSelection: $empty,
      onShow: $empty,
      onHide: $empty,
      onBlur: $empty,
      onFocus: $empty,*/
      minLength: 1,
      markQuery: true,
      width: 'inherit',
      maxChoices: 6,
      injectChoice: null,
      customChoices: null,
      emptyChoices: null,
      visibleChoices: true,
      className: 'autocompleter-choices',
      zIndex: 42,
      delay: 400,
      observerOptions: {},
      fxOptions: {},

      autoSubmit: false,
      overflow: false,
      overflowMargin: 25,
      selectFirst: false,
      filter: null,
      filterCase: false,
      filterSubset: false,
      forceSelect: false,
      selectMode: true,
      choicesMatch: null,

      multiple: false,
      separator: ', ',
      separatorSplit: /\s*[,;]\s*/,
      autoTrim: false,
      allowDupes: false,

      cache: true,
      relative: false
   },

   initialize: function(element, options) {
      this.element = $(element);
      this.setOptions(options);
      this.build();
      this.observer = new Observer(this.element, this.prefetch.bind(this), $merge({
         'delay': this.options.delay
      }, this.options.observerOptions));
      this.queryValue = null;
      if (this.options.filter) this.filter = this.options.filter.bind(this);
      var mode = this.options.selectMode;
      this.typeAhead = (mode == 'type-ahead');
      this.selectMode = (mode === true) ? 'selection' : mode;
      this.cached = [];
   },

   /**
    * build - Initialize DOM
    *
    * Builds the html structure for choices and appends the events to the element.
    * Override this function to modify the html generation.
    */
   build: function() {
      if ($(this.options.customChoices)) {
         this.choices = this.options.customChoices;
      } else {
         this.choices = new Element('ul', {
            'class': this.options.className,
            'styles': {
               'zIndex': this.options.zIndex
            }
         }).inject(document.body);
         this.relative = false;
         if (this.options.relative) {
            this.choices.inject(this.element, 'after');
            this.relative = this.element.getOffsetParent();
         }
         this.fix = new OverlayFix(this.choices);
      }
      if (!this.options.separator.test(this.options.separatorSplit)) {
         this.options.separatorSplit = this.options.separator;
      }
      this.fx = (!this.options.fxOptions) ? null : new Fx.Tween(this.choices, $merge({
         'property': 'opacity',
         'link': 'cancel',
         'duration': 200
      }, this.options.fxOptions)).addEvent('onStart', Chain.prototype.clearChain).set(0);
      this.element.setProperty('autocomplete', 'off')
         .addEvent((Browser.Engine.trident || Browser.Engine.webkit) ? 'keydown' : 'keypress', this.onCommand.bind(this))
         .addEvent('click', this.onCommand.bind(this, [false]))
         .addEvent('focus', this.toggleFocus.create({bind: this, arguments: true, delay: 100}))
         //.addEvent('blur', this.toggleFocus.create({bind: this, arguments: false, delay: 100}));
         .addEvent('click', function(e){
         if (e.target != this.choices) this.toggleFocus(false);
         }.bind(this));

   },

   destroy: function() {
      if (this.fix) this.fix.destroy();
      this.choices = this.selected = this.choices.destroy();
   },

   toggleFocus: function(state) {
      this.focussed = state;
      if (!state) this.hideChoices(true);
      this.fireEvent((state) ? 'onFocus' : 'onBlur', [this.element]);
   },

   onCommand: function(e) {
      if (!e && this.focussed) return this.prefetch();
      if (e && e.key && !e.shift) {
         switch (e.key) {
            case 'enter':
               if (this.element.value != this.opted) return true;
               if (this.selected && this.visible) {
                  this.choiceSelect(this.selected);
                  return !!(this.options.autoSubmit);
               }
               break;
            case 'up': case 'down':
               if (!this.prefetch() && this.queryValue !== null) {
                  var up = (e.key == 'up');
                  this.choiceOver((this.selected || this.choices)[
                     (this.selected) ? ((up) ? 'getPrevious' : 'getNext') : ((up) ? 'getLast' : 'getFirst')
                  ](this.options.choicesMatch), true);
               }
               return false;
            case 'esc': case 'tab':
               this.hideChoices(true);
               break;
         }
      }
      return true;
   },

   setSelection: function(finish) {

      var input = this.selected.inputValue, value = input;

      //angelegt von Bo
      var input1 = this.selected.inputValue1, value1 = input1;
      var input2 = this.selected.inputValue2, value2 = input2;
      document.getElementById('frm_ort_inland_id').value=input1;


   if(noplz!=1){
      anzAlt = document.getElementById('plz_select').childNodes.length;
               if(anzAlt >0){//wenn alte einträge
                  for(i=0;i<anzAlt;i++){
                     $('plz_select').removeChild($('plz_select').firstChild);
                  }
               }
      var sel = 0;
      var plz=input2.split(",");
      var anz =  plz.length;

      if(anz>=2||anz==0){
                     option = document.createElement("option");
                     text = document.createTextNode('Bitte wählen');
                     option.appendChild(text);
                     option.value='0';
                     document.getElementById('plz_select').appendChild(option);
      }

      for(i=1;i<=anz;i++){//alert(root_node.childNodes[i].nodeValue+anz);
                     option = document.createElement("option");
                     text = document.createTextNode(plz[i-1]);
                     option.appendChild(text);
                     option.value=plz[i-1];

                     document.getElementById('plz_select').appendChild(option);

      }

   }

      //Ende
      var start = this.queryValue.length, end = input.length;
      if (input.substr(0, start).toLowerCase() != this.queryValue.toLowerCase()) start = 0;
      if (this.options.multiple) {
         var split = this.options.separatorSplit;
         value = this.element.value;
         start += this.queryIndex;
         end += this.queryIndex;
         var old = value.substr(this.queryIndex).split(split, 1)[0];
         value = value.substr(0, this.queryIndex) + input + value.substr(this.queryIndex + old.length);
         if (finish) {
            var tokens = value.split(this.options.separatorSplit).filter(function(entry) {
               return this.test(entry);
            }, /[^\s,]+/);
            if (!this.options.allowDupes) tokens = [].combine(tokens);
            var sep = this.options.separator;
            value = tokens.join(sep) + sep;
            end = value.length;
         }
      }
      this.observer.setValue(value);
      this.opted = value;
      if (finish || this.selectMode == 'pick') start = end;
      this.element.selectRange(start, end);
      this.fireEvent('onSelection', [this.element, this.selected, value, input]);
   },

   showChoices: function() {
      var match = this.options.choicesMatch, first = this.choices.getFirst(match);
      this.selected = this.selectedValue = null;
      if (this.fix) {
         var pos = this.element.getCoordinates(this.relative), width = this.options.width || 'auto';
         this.choices.setStyles({
            'left': pos.left,
            'top': pos.bottom,
            'width': (width === true || width == 'inherit') ? pos.width : width
         });
      }
      if (!first) return;
      if (!this.visible) {
         this.visible = true;
         this.choices.setStyle('display', '');
         if (this.fx) this.fx.start(1);
         this.fireEvent('onShow', [this.element, this.choices]);
      }
      if (this.options.selectFirst || this.typeAhead || first.inputValue == this.queryValue) this.choiceOver(first, this.typeAhead);
      var items = this.choices.getChildren(match), max = this.options.maxChoices;
      var styles = {'overflowY': 'hidden', 'height': ''};
      this.overflown = false;
      if (items.length > max) {
         var item = items[max - 1];
         styles.overflowY = 'scroll';
         styles.height = item.getCoordinates(this.choices).bottom;
         this.overflown = true;
      };
      this.choices.setStyles(styles);
      this.fix.show();
      if (this.options.visibleChoices) {
         var scroll = document.getScroll(),
         size = document.getSize(),
         coords = this.choices.getCoordinates();
         if (coords.right > scroll.x + size.x) scroll.x = coords.right - size.x;
         if (coords.bottom > scroll.y + size.y) scroll.y = coords.bottom - size.y;
         window.scrollTo(Math.min(scroll.x, coords.left), Math.min(scroll.y, coords.top));
      }
   },

   hideChoices: function(clear) {
      if (clear) {
         var value = this.element.value;
         if (this.options.forceSelect) value = this.opted;
         if (this.options.autoTrim) {
            value = value.split(this.options.separatorSplit).filter($arguments(0)).join(this.options.separator);
         }
         this.observer.setValue(value);
      }
      if (!this.visible) return;
      this.visible = false;
      if (this.selected) this.selected.removeClass('autocompleter-selected');
      this.observer.clear();
      var hide = function(){
         this.choices.setStyle('display', 'none');
         this.fix.hide();
      }.bind(this);
      if (this.fx) this.fx.start(0).chain(hide);
      else hide();
      this.fireEvent('onHide', [this.element, this.choices]);
   },

   prefetch: function() {
      var value = this.element.value, query = value;
      if (this.options.multiple) {
         var split = this.options.separatorSplit;
         var values = value.split(split);
         var index = this.element.getSelectedRange().start;
         var toIndex = value.substr(0, index).split(split);
         var last = toIndex.length - 1;
         index -= toIndex[last].length;
         query = values[last];
      }
      if (query.length < this.options.minLength) {
         this.hideChoices();
      } else {
         if (query === this.queryValue || (this.visible && query == this.selectedValue)) {
            if (this.visible) return false;
            this.showChoices();
         } else {
            this.queryValue = query;
            this.queryIndex = index;
            if (!this.fetchCached()) this.query();
         }
      }
      return true;
   },

   fetchCached: function() {
      return false;
      if (!this.options.cache
         || !this.cached
         || !this.cached.length
         || this.cached.length >= this.options.maxChoices
         || this.queryValue) return false;
      this.update(this.filter(this.cached));
      return true;
   },

   update: function(tokens) {
      this.choices.empty();
      this.cached = tokens;
      var type = tokens && $type(tokens);
      if (!type || (type == 'array' && !tokens.length) || (type == 'hash' && !tokens.getLength())) {
         (this.options.emptyChoices || this.hideChoices).call(this);
      } else {
         if (this.options.maxChoices < tokens.length && !this.options.overflow) tokens.length = this.options.maxChoices;
         tokens.each(this.options.injectChoice || function(token){
            var choice = new Element('li', {'html': this.markQueryValue(token)});
            choice.inputValue = token;
            this.addChoiceEvents(choice).inject(this.choices);
         }, this);
         this.showChoices();
      }
   },

   choiceOver: function(choice, selection) {
      if (!choice || choice == this.selected) return;
      if (this.selected) this.selected.removeClass('autocompleter-selected');
      this.selected = choice.addClass('autocompleter-selected');
      this.fireEvent('onSelect', [this.element, this.selected, selection]);
      if (!this.selectMode) this.opted = this.element.value;
      if (!selection) return;
      this.selectedValue = this.selected.inputValue;
      if (this.overflown) {
         var coords = this.selected.getCoordinates(this.choices), margin = this.options.overflowMargin,
            top = this.choices.scrollTop, height = this.choices.offsetHeight, bottom = top + height;
         if (coords.top - margin < top && top) this.choices.scrollTop = Math.max(coords.top - margin, 0);
         else if (coords.bottom + margin > bottom) this.choices.scrollTop = Math.min(coords.bottom - height + margin, bottom);
      }
      if (this.selectMode) this.setSelection();
   },

   choiceSelect: function(choice) {
      if (choice) this.choiceOver(choice);
      this.setSelection(true);
      this.queryValue = false;
      this.hideChoices();
   },

   filter: function(tokens) {
      return (tokens || this.tokens).filter(function(token) {
         return this.test(token);
      }, new RegExp(((this.options.filterSubset) ? '' : '^') + this.queryValue.escapeRegExp(), (this.options.filterCase) ? '' : 'i'));
   },

   /**
    * markQueryValue
    *
    * Marks the queried word in the given string with <span class="autocompleter-queried">*</span>
    * Call this i.e. from your custom parseChoices, same for addChoiceEvents
    *
    * @param      {String} Text
    * @return      {String} Text
    */
   markQueryValue: function(str) {
      return (!this.options.markQuery || !this.queryValue) ? str
         : str.replace(new RegExp('(' + ((this.options.filterSubset) ? '' : '^') + this.queryValue.escapeRegExp() + ')', (this.options.filterCase) ? '' : 'i'), '<span class="autocompleter-queried">$1</span>');
   },

   /**
    * addChoiceEvents
    *
    * Appends the needed event handlers for a choice-entry to the given element.
    *
    * @param      {Element} Choice entry
    * @return      {Element} Choice entry
    */
   addChoiceEvents: function(el) {
      return el.addEvents({
         'mouseover': this.choiceOver.bind(this, [el]),
         'click': this.choiceSelect.bind(this, [el])
      });
   }
});

var OverlayFix = new Class({

   initialize: function(el) {
      if (Browser.Engine.trident) {
         this.element = $(el);
         this.relative = this.element.getOffsetParent();
         this.fix = new Element('iframe', {
            'frameborder': '0',
            'scrolling': 'no',
            'src': 'javascript:false;',
            'styles': {
               'position': 'absolute',
               'border': 'none',
               'display': 'none',
               'filter': 'progid:DXImageTransform.Microsoft.Alpha(opacity=0)'
            }
         }).inject(this.element, 'after');
      }
   },

   show: function() {
      if (this.fix) {
         var coords = this.element.getCoordinates(this.relative);
         delete coords.right;
         delete coords.bottom;
         this.fix.setStyles($extend(coords, {
            'display': '',
            'zIndex': (this.element.getStyle('zIndex') || 1) - 1
         }));
      }
      return this;
   },

   hide: function() {
      if (this.fix) this.fix.setStyle('display', 'none');
      return this;
   },

   destroy: function() {
      if (this.fix) this.fix = this.fix.destroy();
   }

});

Element.implement({

   getSelectedRange: function() {
      if (!Browser.Engine.trident) return {start: this.selectionStart, end: this.selectionEnd};
      var pos = {start: 0, end: 0};
      var range = this.getDocument().selection.createRange();
      if (!range || range.parentElement() != this) return pos;
      var dup = range.duplicate();
      if (this.type == 'text') {
         pos.start = 0 - dup.moveStart('character', -100000);
         pos.end = pos.start + range.text.length;
      } else {
         var value = this.value;
         var offset = value.length - value.match(/[\n\r]*$/)[0].length;
         dup.moveToElementText(this);
         dup.setEndPoint('StartToEnd', range);
         pos.end = offset - dup.text.length;
         dup.setEndPoint('StartToStart', range);
         pos.start = offset - dup.text.length;
      }
      return pos;
   },

   selectRange: function(start, end) {
      if (Browser.Engine.trident) {
         var diff = this.value.substr(start, end - start).replace(/\r/g, '').length;
         start = this.value.substr(0, start).replace(/\r/g, '').length;
         var range = this.createTextRange();
         range.collapse(true);
         range.moveEnd('character', start + diff);
         range.moveStart('character', start);
         range.select();
      } else {
         this.focus();
         this.setSelectionRange(start, end);
      }
      return this;
   }

});

/* compatibility */

Autocompleter.Base = Autocompleter;
