function rating(container_id, hodnoceno_id, object_type, object_id, initial_value, max_value, step_size, column_height, custom_values, init_on_create)
{ 
  //this.ajaxURL = "/user_ajax/rating";
  this.ajaxURL = "/box/hodnoceni/ajax_hlasuj";
  //this.ajaxURL = "/rating.xml";
  
  this.containerElement = null;
  
  this.objectType = object_type;
  
  this.objectId = object_id;
  
  this.initialValue = initial_value;
  
  this.currentValue = initial_value;
  
  this.votedValue = null;
  
  this.maxValue = max_value;
  
  this.stepSize = step_size;
  
  this.buttonClass = "rating_button";
  this.buttonElement = null;
  this.sliderClass = "rating_slider";
  this.sliderElement = null;
  this.handleClass = "rating_handle";
  this.handleElement = null;
  this.indicatorClass = "rating_indicator";
  this.indicatorElement = null;
  this.loadingIndicatorClass = 'rating_loader';
  this.loadingIndicatorLoadingClass = 'loading';
  this.loadingIndicator = null;
  
  this.usersRatingIndicatorClass = 'users_rating';
  this.usersRatingIndicator = null;
  this.usersRatingColumnClass = 'users_column';
  this.usersRatingColumn = null;
  this.usersRatingColumnTop = null;
  
  this.hodnocenoElementId = hodnoceno_id;
  this.hodnocenoElement = null;
  
  this.sliderControl = null;
  
  this.moved = false;
  
  this.init_on_create = init_on_create==undefined?true:init_on_create;
  
  this.column_height = column_height==undefined?null:column_height;
  
  this.custom_values = custom_values==undefined?null:custom_values;
  
  rating.prototype.initialize = function() { 
    if(!container_id) {
      this.containerElement = document;
    } else {
      this.containerElement = document.getElementById(container_id);
    } 
    var elements = this.getDescendantsByClass(this.buttonClass, this.containerElement);
    this.buttonElement = elements[0];
    var elements = this.getDescendantsByClass(this.sliderClass, this.containerElement);
    this.sliderElement = elements[0];
    var elements = this.getDescendantsByClass(this.handleClass, this.containerElement);
    this.handleElement = elements[0];
    var elements = this.getDescendantsByClass(this.indicatorClass, this.containerElement);
    this.indicatorElement = elements[0];
    var elements = this.getDescendantsByClass(this.usersRatingIndicatorClass, this.containerElement);
    this.usersRatingIndicator = elements[0];
    var elements = this.getDescendantsByClass(this.usersRatingColumnClass, this.containerElement);
    this.usersRatingColumn = elements[0];
    var elements = this.getDescendantsByClass('column_top', this.usersRatingColumn);
    this.usersRatingColumnTop = elements[0];
    var elements = this.getDescendantsByClass(this.loadingIndicatorClass, this.containerElement);
    this.loadingIndicator = elements[0];
    if(this.hodnocenoElementId) {
      this.hodnocenoElement = document.getElementById(this.hodnocenoElementId);
    }
    
    this.initializeSlider();
    this.initializeButton();

    this.moved = true; // kvuli this.setSliderValue
    this.setSliderValue(this.initialValue, true);
  }
  
  rating.prototype.setSliderValue = function(value, apply_correction) {
    var new_value = parseInt((parseInt(value)+(this.stepSize/2))/this.stepSize)*this.stepSize;
    if(apply_correction && this.moved) {
      this.moved = false;
      this.sliderControl.setValue(this.maxValue-new_value);
    }
    if(apply_correction && new_value != this.initialValue) {
      this.buttonElement.style.display = '';
    } else {
      this.buttonElement.style.display = 'none';
    }

    if(this.custom_values) {
      var index = parseInt(new_value/this.stepSize);
      var indicator_text = this.custom_values[index]!=undefined?this.custom_values[index]:new_value;
    } else {
      var indicator_text = new_value?new_value:'?';
    }
    $(this.indicatorElement).update(indicator_text);
    
    this.currentValue = new_value;
    
    this.sliderElement.style.backgroundPosition = '0px '+(this.column_height?((this.column_height/this.maxValue)*(this.maxValue - new_value)):(this.maxValue - new_value) + 0)+'px';
  }
  
  rating.prototype.initializeSlider = function() {
    var values = new Array();
    for(var i = 0; i <= this.maxValue/this.stepSize; i++) {
      values[i] = i*this.stepSize;
    }
    
    var rating_object = this;
    
    this.sliderControl = new Control.Slider(this.handleElement, this.sliderElement, {
      axis: 'vertical',
      range: $R(0, this.maxValue),
      sliderValue: this.maxValue,
      values: values,
      onSlide: function(value) {
        rating_object.setSliderValue(rating_object.maxValue-value, false);
        rating_object.moved = true;
      },
      onChange: function(value) {
        rating_object.setSliderValue(rating_object.maxValue-value, true);
      }  
    });
  }
  
  rating.prototype.initializeButton = function() { 
    this.addEventListener(this.buttonElement, "click", this.createVoteCallback(), this);
  }
  
  rating.prototype.createVoteCallback = function() {
    var ratingObj = this;
    return function () {
      ratingObj.vote();
    };
  }

  rating.prototype.vote = function() {
    this.votedValue = this.currentValue; 
    this.addClassName(this.loadingIndicator, this.loadingIndicatorLoadingClass);
  
    var ajaxRequest = new ajaxObject(this.ajaxURL);
    var ratingObj = this;
    ajaxRequest.callback = function(responseText, responseStatus, responseXML) {
      ratingObj.processResponse(responseText, responseStatus, responseXML);
    }
    ajaxRequest.update('v='+encodeURIComponent(this.currentValue)+'&type='+encodeURIComponent(this.objectType)+'&id='+encodeURIComponent(this.objectId),'GET');
  }
  
  rating.prototype.processResponse = function(responseText, responseStatus, responseXML) {
    this.removeClassName(this.loadingIndicator, this.loadingIndicatorLoadingClass);
    this.buttonElement.style.display = 'none';
    if (responseStatus==200) {
      var xmldoc = responseXML;
      
      var root = xmldoc.getElementsByTagName("root").item(0);
      
      var celkove_skore = root.getElementsByTagName("celkovehodnoceni").item(0).firstChild.nodeValue;
      if(celkove_skore != 'x') {
        this.usersRatingIndicator.firstChild.nodeValue = celkove_skore;
        this.usersRatingColumn.style.backgroundPosition = '0px '+(this.column_height?((this.column_height/this.maxValue)*(this.maxValue - celkove_skore)):(this.maxValue - celkove_skore) + 0)+'px';
        this.usersRatingColumnTop.style.top = (this.column_height?((this.column_height/this.maxValue)*(this.maxValue - celkove_skore)):(this.maxValue - celkove_skore) + 0)+'px';
      }
      if (this.hodnocenoElement != null)
      { 
        var pocet_hodnoceni = root.getElementsByTagName("pocet_hodnoceni").item(0).firstChild.nodeValue;
        var historie_hodnoceni = root.getElementsByTagName("hodnoceni");
        
        var a = new Array();  //pole elementu Hodnotitel k odstraneni
        
        //projit cely blok Hodnoceno
        var h = this.hodnocenoElement.getElementsByTagName("li");
        for (i=0; i<h.length; i++)
        {
          if (this.hasClassName(h.item(i), "pocet_hodnoceni")) { // nastavi novou hodnotu celkoveho poctu hodnoceni
            h.item(i).getElementsByTagName("span").item(0).firstChild.nodeValue = pocet_hodnoceni;
          } else {
            a.push(h.item(i));  //prida do pole elementu dalsi zaznam
          }
        }
        //smazat vsechny stavajici (ulozene) elementy Hodnotitel
        for (i=0; i<a.length; i++) {
          a[i].parentNode.removeChild(a[i]);
        }
        
        //vygenerovat blok hodnotitelelu
        for (i=0;i<historie_hodnoceni.length; i++)
        {
          var uzivatel = historie_hodnoceni.item(i).getElementsByTagName("uzivatel").item(0).firstChild.nodeValue;
          var hodnota = historie_hodnoceni.item(i).getElementsByTagName("hodnota").item(0).firstChild.nodeValue;
          
          //<div class="hodnotitel">uzivatel<span>75</span></div>
          var n1 = document.createElement("li");
          if(i%2 == 0) {
            n1.className = "svetlejsi";
          }
          n1.appendChild(document.createTextNode(uzivatel));
          var n2 = document.createElement("span");
          n2.appendChild(document.createTextNode(hodnota));
          n1.appendChild(n2);
          this.hodnocenoElement.appendChild(n1); 
        }
      }

      this.initialValue = this.votedValue;
    }
    else
    {
      //chyba AJAX prenosu
    }
  }
  
  rating.prototype.updateIndicator = function(is_fav) {
    for (var i = 0; i < this.indicatorElements.length; i++) {
    this.removeClassName(this.indicatorElements[i], is_fav?this.indicatorNoClass:this.indicatorYesClass);
    this.addClassName(this.indicatorElements[i], is_fav?this.indicatorYesClass:this.indicatorNoClass);
    }
  }
  
  rating.prototype.getDescendantsByClass = function(class_name, container_element) {
    if(container_element == undefined) return false;
    var elements = new Array();
    var reg = new RegExp('\\b'+class_name+'\\b');
    var all = container_element.getElementsByTagName('*');
    for (var i = 0; i < all.length; i++) {
      if (reg.test(all[i].className)) {
        elements.push(all[i]);
      }
    }
    return elements;
  }
  
  rating.prototype.addEventListener = function(obj,evt,fnc,scope,useCapture) {
    if (!useCapture) useCapture=false;
    var scoped = scope ? function(e) { fnc.apply(scope, [e]); } : fnc;
  	if (obj.addEventListener){ 
  		obj.addEventListener(evt,scoped,useCapture);
  		return true;
  	} else if (obj.attachEvent) {
      return obj.attachEvent("on"+evt,scoped);
    }
  }
  
  rating.prototype.hasClassName = function(element, class_name) {
    return element.className.match(new RegExp('(\\s|^)'+class_name+'(\\s|$)'));
  }
  
  rating.prototype.addClassName = function(element, class_name) {
    if(!element.className) {
      element.className = class_name;
    } else if(!this.hasClassName(element, class_name)) {
      element.className = element.className + " " + class_name;
    }
  }
  
  rating.prototype.removeClassName = function(element, class_name) {
  	if (this.hasClassName(element, class_name)) {
  		var reg = new RegExp('(\\s|^)'+class_name+'(\\s|$)');
  		element.className = element.className.replace(reg, ' ');
  	}
  }
  
  if(this.init_on_create) {
    this.initialize();
  }
}