/*  Prototype
var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
}

var Abstract = new Object();

Object.extend = function(destination, source) {
  for ( property in source ) { destination[property] = source[property]; }
  return destination;
}

Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() { return __method.apply( object, args.concat($A(arguments)) ); }
}

//--------------------------------------------------------------------------

Object.extend(String.prototype, {

  camelize: function() {
    var oStringList = this.split('-');
    if (oStringList.length == 1) return oStringList[0];

    var camelizedString = this.indexOf('-') == 0
      ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
      : oStringList[0];

    for (var i = 1, len = oStringList.length; i < len; i++) {
      var s = oStringList[i];
      camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
    }

    return camelizedString;
  },

  inspect: function() {
    return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";
  }
});

var Enumerable = {
  each: function(iterator) {
    var index = 0;
    try {
      this._each(function(value) {
        try {
          iterator(value, index++);
        } catch (e) {
          if (e != $continue) throw e;
        }
      });
    } catch (e) {
      if (e != $break) throw e;
    }
  },

  collect: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      results.push(iterator(value, index));
    });
    return results;
  },

  include: function(object) {
    var found = false;
    this.each(function(value) {
      if (value == object) {
        found = true;
        throw $break;
      }
    });
    return found;
  },

  inject: function(memo, iterator) {
    this.each(function(value, index) {
      memo = iterator(memo, value, index);
    });
    return memo;
  },

  invoke: function(method) {
    var args = $A(arguments).slice(1);
    return this.collect(function(value) {
      return value[method].apply(value, args);
    });
  },

  reject: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      if (!iterator(value, index))
        results.push(value);
    });
    return results;
  },

  inspect: function() {
    return '#<Enumerable:' + this.toArray().inspect() + '>';
  }
}

var $A = Array.from = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0; i < iterable.length; i++)
      results.push(iterable[i]);
    return results;
  }
}

Object.extend(Array.prototype, Enumerable);

Array.prototype._reverse = Array.prototype.reverse;

Object.extend(Array.prototype, {
  _each: function(iterator) {
    for (var i = 0; i < this.length; i++)
      iterator(this[i]);
  },

  inspect: function() {
    return '[' + this.map(Object.inspect).join(', ') + ']';
  }
});

var Hash = {
  _each: function(iterator) {
    for (key in this) {
      var value = this[key];
      if (typeof value == 'function') continue;

      var pair = [key, value];
      pair.key = key;
      pair.value = value;
      iterator(pair);
    }
  },

  keys: function() {
    return this.pluck('key');
  },

  values: function() {
    return this.pluck('value');
  },

  merge: function(hash) {
    return $H(hash).inject($H(this), function(mergedHash, pair) {
      mergedHash[pair.key] = pair.value;
      return mergedHash;
    });
  },

  toQueryString: function() {
    return this.map(function(pair) {
      return pair.map(encodeURIComponent).join('=');
    }).join('&');
  },

  inspect: function() {
    return '#<Hash:{' + this.map(function(pair) {
      return pair.map(Object.inspect).join(': ');
    }).join(', ') + '}>';
  }
}

function $H(object) {
  var hash = Object.extend({}, object || {});
  Object.extend(hash, Enumerable);
  Object.extend(hash, Hash);
  return hash;
}


ObjectRange = Class.create();

//--------------------------------------------------------------------------

if ( !window.Element ) { var Element = new Object(); }

Object.extend(Element, { 
  
  hide: function() { arguments[0].style.display = 'none'; },

  setStyle: function(element, style) { for (name in style)  element.style[name.camelize()] = style[name]; },

  getStyle: function(element, style) { 
    var value = element.style[style.camelize()];
    if (!value) {
      if (document.defaultView && document.defaultView.getComputedStyle) {
        var css = document.defaultView.getComputedStyle(element, null);
        value = css ? css.getPropertyValue(style) : null;
      } else if (element.currentStyle) {
        value = element.currentStyle[style.camelize()];
      }
    }

    if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
      if (Element.getStyle(element, 'position') == 'static') value = 'auto';

    return value == 'auto' ? null : value;
  },


  getDimensions: function(element) {
    if (Element.getStyle(element, 'display') != 'none') return {width: element.offsetWidth, height: element.offsetHeight};

    var els = element.style;
    var originalVisibility = els.visibility;
    var originalPosition = els.position;
    els.visibility = 'hidden';
    els.position = 'absolute';
    els.display = '';
    var originalWidth = element.clientWidth;
    var originalHeight = element.clientHeight;
    els.display = 'none';
    els.position = originalPosition;
    els.visibility = originalVisibility;
    return {width: originalWidth, height: originalHeight};
  },

  makeClipping: function(element) {
    if ( element._overflow ) return;
    element._overflow = element.style.overflow;
    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') element.style.overflow = 'hidden';
  },

  undoClipping: function(element) {
    if (element._overflow) return;
    element.style.overflow = element._overflow;
    element._overflow = undefined;
  }
});


Array.prototype.call = function() {
  var args = arguments;
  this.each(function(f){ f.apply(this, args) });
}
//--------------------------------------------------------------------------

var Effect = {
  tagifyText: function(element) {
    var tagifyStyle = 'position:relative';
    if(/MSIE/.test(navigator.userAgent)) tagifyStyle += ';zoom:1';
    element = $(element);
    $A(element.childNodes).each( function(child) {
      if(child.nodeType==3) {
        child.nodeValue.toArray().each( function(character) {
          element.insertBefore(
            Builder.node('span',{style: tagifyStyle},
              character == ' ' ? String.fromCharCode(160) : character), 
              child);
        });
        Element.remove(child);
      }
    });
  },
  multiple: function(element, effect) {
    var elements;
    if(((typeof element == 'object') || 
        (typeof element == 'function')) && 
       (element.length))
      elements = element;
    else
      elements = $(element).childNodes;
      
    var options = Object.extend({
      speed: 0.1,
      delay: 0.0
    }, arguments[2] || {});
    var masterDelay = options.delay;

    $A(elements).each( function(element, index) {
      new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
    });
  },
  PAIRS: {
    'slide':  ['SlideDown','SlideUp'],
    'blind':  ['BlindDown','BlindUp'],
    'appear': ['Appear','Fade']
  },
  toggle: function(element, effect) {
    element = $(element);
    effect = (effect || 'appear').toLowerCase();
    var options = Object.extend({
      queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
    }, arguments[2] || {});
    Effect[Element.visible(element) ? 
      Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
  }
};

// ------------- transitions ------------- 
Effect.Transitions = {}

// ------------- core effects -------------

Effect.ScopedQueue = Class.create();
Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
  initialize: function() {
    this.effects  = [];
    this.interval = null;
  },
  _each: function(iterator) {
    this.effects._each(iterator);
  },
  add: function(effect) {
    var timestamp = new Date().getTime();
    
    var position = (typeof effect.options.queue == 'string') ? 
      effect.options.queue : effect.options.queue.position;
    
    switch(position) {
      case 'front':
        // move unstarted effects after this effect  
        this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
            e.startOn  += effect.finishOn;
            e.finishOn += effect.finishOn;
          });
        break;
      case 'end':
        // start effect after last queued effect has finished
        timestamp = this.effects.pluck('finishOn').max() || timestamp;
        break;
    }
    
    effect.startOn  += timestamp;
    effect.finishOn += timestamp;

    if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
      this.effects.push(effect);
    
    if(!this.interval) 
      this.interval = setInterval(this.loop.bind(this), 40);
  },
  remove: function(effect) {
    this.effects = this.effects.reject(function(e) { return e==effect });
    if(this.effects.length == 0) {
      clearInterval(this.interval);
      this.interval = null;
    }
  },
  loop: function() {
    var timePos = new Date().getTime();
    this.effects.invoke('loop', timePos);
  }
});

Effect.Queues = {
  instances: $H(),
  get: function(queueName) {
    if(typeof queueName != 'string') return queueName;
    
    if(!this.instances[queueName])
      this.instances[queueName] = new Effect.ScopedQueue();
      
    return this.instances[queueName];
  }
}
Effect.Queue = Effect.Queues.get('global');

Effect.DefaultOptions = {
  transition: Effect.Transitions.sinoidal,
  duration:   1.0,   // seconds
  fps:        25.0,  // max. 25fps due to Effect.Queue implementation
  sync:       false, // true for combining
  from:       0.0,
  to:         1.0,
  delay:      0.0,
  queue:      'parallel'
}

Effect.Base = function() {};
Effect.Base.prototype = {
  position: null,
  start: function(options) {
    this.options      = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
    this.currentFrame = 0;
    this.state        = 'idle';
    this.startOn      = this.options.delay*1000;
    this.finishOn     = this.startOn + (this.options.duration*1000);
    this.event('beforeStart');
    if(!this.options.sync)
      Effect.Queues.get(typeof this.options.queue == 'string' ? 
        'global' : this.options.queue.scope).add(this);
  },
  loop: function(timePos) {
    if(timePos >= this.startOn) {
      if(timePos >= this.finishOn) {
        this.render(1.0);
        this.cancel();
        this.event('beforeFinish');
        if(this.finish) this.finish(); 
        this.event('afterFinish');
        return;  
      }
      var pos   = (timePos - this.startOn) / (this.finishOn - this.startOn);
      var frame = Math.round(pos * this.options.fps * this.options.duration);
      if(frame > this.currentFrame) {
        this.render(pos);
        this.currentFrame = frame;
      }
    }
  },
  render: function(pos) {
    if(this.state == 'idle') {
      this.state = 'running';
      this.event('beforeSetup');
      if(this.setup) this.setup();
      this.event('afterSetup');
    }
    if(this.state == 'running') {
      if(this.options.transition) pos = this.options.transition(pos);
      pos *= (this.options.to-this.options.from);
      pos += this.options.from;
      this.position = pos;
      this.event('beforeUpdate');
      if(this.update) this.update(pos);
      this.event('afterUpdate');
    }
  },
  cancel: function() {
    if(!this.options.sync)
      Effect.Queues.get(typeof this.options.queue == 'string' ? 
        'global' : this.options.queue.scope).remove(this);
    this.state = 'finished';
  },
  event: function(eventName) {
    if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
    if(this.options[eventName]) this.options[eventName](this);
  },
  inspect: function() {
    return '#<Effect:' + $H(this).inspect() + ',options:' + $H(this.options).inspect() + '>';
  }
}

Effect.Scale = Class.create();

Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
  initialize: function(element, percent) {
    this.element = $(element)
    var options = Object.extend({
      scaleX: true,
      scaleY: true,
      scaleContent: true,
      scaleFromCenter: false,
      scaleMode: 'box',        // 'box' or 'contents' or {} with provided values
      scaleFrom: 100.0,
      scaleTo:   percent
    }, arguments[2] || {});
    this.start(options);
  },
  setup: function() {
    this.restoreAfterFinish = this.options.restoreAfterFinish || false;
    this.elementPositioning = Element.getStyle(this.element,'position');
    
    this.originalStyle = {};
    ['top','left','width','height','fontSize'].each( function(k) {
      this.originalStyle[k] = this.element.style[k];
    }.bind(this));
      
    this.originalTop  = this.element.offsetTop;
    this.originalLeft = this.element.offsetLeft;
    
    var fontSize = Element.getStyle(this.element,'font-size') || '100%';
    ['em','px','%'].each( function(fontSizeType) {
      if(fontSize.indexOf(fontSizeType)>0) {
        this.fontSize     = parseFloat(fontSize);
        this.fontSizeType = fontSizeType;
      }
    }.bind(this));
    
    this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
    
    this.dims = null;
    if(this.options.scaleMode=='box')
      this.dims = [this.element.offsetHeight, this.element.offsetWidth];
    if(/^content/.test(this.options.scaleMode))
      this.dims = [this.element.scrollHeight, this.element.scrollWidth];
    if(!this.dims)
      this.dims = [this.options.scaleMode.originalHeight,
                   this.options.scaleMode.originalWidth];
  },
  update: function(position) {
    var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
    if(this.options.scaleContent && this.fontSize)
      Element.setStyle(this.element, {fontSize: this.fontSize * currentScale + this.fontSizeType });
    this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
  },
  finish: function(position) {
    if (this.restoreAfterFinish) Element.setStyle(this.element, this.originalStyle);
  },
  setDimensions: function(height, width) {
    var d = {};
    if(this.options.scaleX) d.width = width + 'px';
    if(this.options.scaleY) d.height = height + 'px';
    if(this.options.scaleFromCenter) {
      var topd  = (height - this.dims[0])/2;
      var leftd = (width  - this.dims[1])/2;
      if(this.elementPositioning == 'absolute') {
        if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
        if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
      } else {
        if(this.options.scaleY) d.top = -topd + 'px';
        if(this.options.scaleX) d.left = -leftd + 'px';
      }
    }
    Element.setStyle( this.element, d );
  }
});

function $() {
  var elements = new Array();

  for (var i = 0; i < arguments.length; i++) {
    var element = arguments[i];
    if (typeof element == 'string')
      element = document.getElementById(element);

    if (arguments.length == 1)
      return element;

    elements.push(element);
  }

  return elements;
}
//---------------------------------------------------------------------------------------------
function isCollapsed( id ){
    var element = document.getElementById( id );

    if( !element ) return false;

    if( element.style.display == 'none' ) return true;

    return false;
}

*/

function collapseBox( id, dopen, dclose ){  $( "#"+id ).slideToggle( 'slow' );
 //var element = document.getElementById( id );
 // if( !element ) return false;

 // if( element.style.display == 'none' ) $( "#"+id ).slideDown( 'slow' );
 // else $( "#"+id ).slideUp( 'slow' );
 // if( !element.blinding ){
 // element.blinding=true;
 // if( element.style.display == 'none' ) Effect.BlindDown( element, dopen ); 
 // else Effect.BlindUp( element, dclose );
 //}
 return true;
}

function collapseBoxm( id, dopen, dclose ){
    var element = document.getElementById( id+'_div' ); if( !element ) return false;

    if( !collapseBox( id, dopen, dclose ) ) return false;
    if( element.className == 'expanded' ) element.className = 'collapsed'; else element.className = 'expanded';
}

function collapseBoxs( id, dopen, dclose ){

    if( !document.getElementById( id+'Div' ) ) return false; 
    var element = document.getElementById( id+'Link' );

    if( element ) element.innerHTML = ( document.getElementById( id+'Div' ).style.display == 'none' ? '[cвернуть]' : '[развернуть]' );
   
    return collapseBox( id+'Div', dopen, dclose );
}
/*
Effect.BlindUp = function(element, speed) {
  element.blinding=false;
  Element.makeClipping(element);

  return new Effect.Scale( element, 0, 
    Object.extend( { scaleContent: false, 
      scaleX: false, 
      restoreAfterFinish: true,
      duration: speed,
      afterFinishInternal: function(effect) { with(Element) {[hide, undoClipping].call(effect.element);} } 
    }, {} )
  );
}

Effect.BlindDown = function( element, speed ) {
  var elementDimensions = Element.getDimensions(element);
  element.blinding=false;

  return new Effect.Scale( element, 100, 
    Object.extend( {
      scaleContent: false, 
      scaleX: false,
      scaleFrom: 0,
      scaleMode: { originalHeight: elementDimensions.height, originalWidth: elementDimensions.width },
      restoreAfterFinish: true,
      duration: speed,
      afterSetup: function(effect) { 
                   with(Element) {
                                  makeClipping(effect.element);
        			  setStyle(effect.element, {height: '0px'});
        			  element.style.display = 'block'; 
      }},
      afterFinishInternal: function(effect) { Element.undoClipping(effect.element); }
    }, {} )
  );
}
*/
function description_init( ){
    if( document.getElementById('dsc') ) return false;
    layer = document.createElement('div'); layer.style.width  = 200 + 'px'; // layer.style.height = 50 + 'px';
    layer.style.position = 'absolute';     layer.style.zIndex = 999; layer.style.visibility = 'hidden'; 
    layer.style.border   = '1px solid #BBBBBB';
    layer.style.backgroundColor = '#FFFFFF'; 
    
    if( document.all ){ layer.style.filter = 'alpha(opacity: 93)'; }else{ layer.style.opacity = 0.93; }

    layer.style.padding = '2px 5px'; layer.id = 'dsc'; document.body.appendChild(layer);
}
function descriptionMove(evt, desc_string){
    var hlp = document.getElementById('supload'); if( hlp && hlp.style.display == 'block' ) return false;
    var e = new xEvent(evt); var span = document.getElementById('dsc');
    span.style.top = (e.pageY + 25)+'px'; span.style.left = (e.pageX - 5)+'px';
    span.style.visibility = 'visible'; 
    span.innerHTML = desc_string; 
}
function descriptionClose( ){ var span = document.getElementById('dsc'); span.style.visibility = 'hidden'; }    

/*
Tiny Scrolling - a smooth navigation between internal links and their destinations
by Marco Rosella - http://www.centralscrutinizer.it/en/design/js-php/tiny-scrolling
based on the works by Travis Beckham and Brian McAllister.
v0.3 - March 27, 2006
*/
// tinyScrolling.init();
var tinyScrolling = {
    speed : 30,      //set here the scroll speed: when this value increase, the speed decrease. 
    maxStep: 150,    //set here the "uniform motion" step for long distances
    brakeK: 5,       //set here the coefficient of slowing down
    hash:null,
    currentBlock:null,
    requestedY:0,
    init: function() {
	var lnks = document.getElementsByTagName('a');   
	for(var i = 0, lnk; lnk = lnks[i]; i++) {   
	    if ((lnk.href && lnk.href.indexOf('#') != -1) &&  ( (lnk.pathname == location.pathname) ||
								('/'+lnk.pathname == location.pathname) ) && (lnk.search == location.search)) {  
		lnk.onclick = tinyScrolling.initScroll;   
	    }   
	}
    },
    getElementYpos: function(el){
	var y = 0;
	while(el.offsetParent){  
	    y += el.offsetTop    
		el = el.offsetParent;
	}return y;
    },
    getScrollTop: function(){
	if(document.all) return (document.documentElement.scrollTop) ? document.documentElement.scrollTop : document.body.scrollTop;
	else return window.pageYOffset;   
    },
    getWindowHeight: function(){
	if (window.innerHeight)return window.innerHeight;
	if(document.documentElement && document.documentElement.clientHeight) return document.documentElement.clientHeight;
    },
    getDocumentHeight: function(){
	if (document.height) return document.height;
	if(document.body.offsetHeight) return document.body.offsetHeight;
    },
    initScroll: function(e){
	var targ;  
	if (!e) var e = window.event;
	if (e.target) targ = e.target;
	else if (e.srcElement) targ = e.srcElement;   
	tinyScrolling.hash = targ.href.substr(targ.href.indexOf('#')+1,targ.href.length); 
	tinyScrolling.currentBlock = document.getElementById(tinyScrolling.hash);   
	if(!tinyScrolling.currentBlock) return;
	tinyScrolling.requestedY = tinyScrolling.getElementYpos(tinyScrolling.currentBlock); 
	tinyScrolling.scroll();  
	return false;
    },
    scroll: function(){
	var top  = tinyScrolling.getScrollTop();
	if(tinyScrolling.requestedY > top) {  
	    var endDistance = Math.round((tinyScrolling.getDocumentHeight() - (top + tinyScrolling.getWindowHeight())) / tinyScrolling.brakeK);
	    endDistance = Math.min(Math.round((tinyScrolling.requestedY-top)/ tinyScrolling.brakeK), endDistance);
	    var offset = Math.max(2, Math.min(endDistance, tinyScrolling.maxStep));
	} else { var offset = - Math.min(Math.abs(Math.round((tinyScrolling.requestedY-top)/ tinyScrolling.brakeK)), tinyScrolling.maxStep);
	} window.scrollTo(0, top + offset);  
	if(Math.abs(top-tinyScrolling.requestedY) <= 1 || tinyScrolling.getScrollTop() == top) {
	    window.scrollTo(0, tinyScrolling.requestedY);
	    if(!document.all || window.opera) location.hash = tinyScrolling.hash;
	    tinyScrolling.hash = null;
	} else setTimeout(tinyScrolling.scroll,tinyScrolling.speed);
    }
}
