function $(x) { return ( q = document.getElementById(x) ) ? q : alert('["'+x+'" not found]'); }
String.prototype.trim = function () {
    return this.replace(/^\s*/, "").replace(/\s*$/, "");
    }
    
sjfw = { 

    timers: new Array,

    _timer_step: 9999999,
    _timer_id: 0,
    _timer_handle_single: function(i, force) {
            var q = sjfw.timers[i];
            
            if ( force || ( sjfw.timers[i].counter += sjfw._timer_step ) > q.next )
            {
                var res = q.handler( i, q.step == q.maxstep-1 ); //sjfw.timers[i] );
                sjfw.timers[i].next = q.counter + q.period;
                sjfw.timers[i].step++;

                if ( res || sjfw.timers[i].step >= q.maxstep )
                {
                  sjfw.timers.splice(i,1);
                  if ( !sjfw.timers.length )
                  {
                    clearInterval( sjfw._timer_id );
                    sjfw._timer_step = 9999999;
                  }
                  
                  //$$("info").innerHTML = "timers count: " + sjfw.timers.length;
                }
            }
    },
    
    _timer_handle: function() {
        var i;
        for ( i = sjfw.timers.length-1; i >= 0; i-- )
          sjfw._timer_handle_single(i);
    },

    timerSetup: function( period, duration, cv, handler ) {

      if ( !period ) return;

      var id = 0;
      this.timers[ id = this.timers.length ] = {
        step: 0,
        maxstep: Math.ceil( duration / period ),
        
        counter: 0,
        next: period,
        
        duration: duration,
        period: period,
        cv: cv,
        handler: handler
      };
      sjfw._timer_handle_single( id, true );
      
      if ( this._timer_step > period )
      {
        this._timer_step = period;

        if ( this._timer_id ) clearInterval( this._timer_id );
        this._timer_id = setInterval( this._timer_handle, this._timer_step );
        
        //$$("info").innerHTML = "timer step: " + this._timer_step;
      }
      

    },

  opacity: function( e, v, extrafilter )
  {
    v = Math.ceil(v < 0 ? 0 : ( v > 100 ? 100 : v ));
    e.style.opacity = v/100;
    e.style.filter = extrafilter ? extrafilter : 'alpha(opacity=' + Math.floor(v) + ')';
  }

};
// ---------------------------------------
// written by Dean Edwards, 2005
// with input from Tino Zijdel, Matthias Miller, Diego Perini

// http://dean.edwards.name/weblog/2005/10/add-event/

function addEvent(element, type, handler) {
	if (element.addEventListener) {
		element.addEventListener(type, handler, false);
	} else {
		// assign each event handler a unique ID
		if (!handler.$$guid) handler.$$guid = addEvent.guid++;
		// create a hash table of event types for the element
		if (!element.events) element.events = {};
		// create a hash table of event handlers for each element/event pair
		var handlers = element.events[type];
		if (!handlers) {
			handlers = element.events[type] = {};
			// store the existing event handler (if there is one)
			if (element["on" + type]) {
				handlers[0] = element["on" + type];
			}
		}
		// store the event handler in the hash table
		handlers[handler.$$guid] = handler;
		// assign a global event handler to do all the work
		element["on" + type] = handleEvent;
	}
};
// a counter used to create unique IDs
addEvent.guid = 1;

function removeEvent(element, type, handler) {
	if (element.removeEventListener) {
		element.removeEventListener(type, handler, false);
	} else {
		// delete the event handler from the hash table
		if (element.events && element.events[type]) {
			delete element.events[type][handler.$$guid];
		}
	}
};

function handleEvent(event) {
	var returnValue = true;
	// grab the event object (IE uses a global event object)
	event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
	// get a reference to the hash table of event handlers
	var handlers = this.events[event.type];
	// execute each event handler
	for (var i in handlers) {
		this.$$handleEvent = handlers[i];
		if (this.$$handleEvent(event) === false) {
			returnValue = false;
		}
	}
	return returnValue;
};

function fixEvent(event) {
	// add W3C standard event methods
	event.preventDefault = fixEvent.preventDefault;
	event.stopPropagation = fixEvent.stopPropagation;
	return event;
};
fixEvent.preventDefault = function() {
	this.returnValue = false;
};
fixEvent.stopPropagation = function() {
	this.cancelBubble = true;
};


// ---------------------------------------
// ajaxer
var onHashChange = function(event) {
    
        //get hash function
        var getHashValue = function() {
            
        var arr = window.location.hash.split("#");
                    
        var hasValue = arr[1];
                          
        //sets default
        if (typeof hasValue == "undefined") {
              return false;
        }

        var hashLen = hasValue.indexOf("?");
        if(0<=hashLen){ 
            hasValue = hasValue.substring(0,hashLen);
        }
        return hasValue;
        }
        
        //last hash
        var lastHash = getHashValue();

        //checker
        (function watchHash() {
          var hash = getHashValue();
          if (hash !== lastHash) {
                event();
                lastHash = hash;
          }
          var t = setTimeout(watchHash, 100);
        })();
};

ajaxed = {
  hashon: true,
  marks: null,
  domain: '',
  loader: null,

  init: function( sitedomain )
  {
    if (navigator.appName == 'Microsoft Internet Explorer')
      return;
    
    this.loader = document.createElement('DIV');
    this.loader.style.display = "none";

    
    this.domain = sitedomain;
    this.rescan(); 
    this.click( window.location.hash.substr(1) );

    onHashChange(function() {
      //your on-change code here
      if ( ajaxed.hashon )
          ajaxed.click( window.location.hash.substr(1) );
    });
  },

  rescan: function()
  {
    var a = document.getElementsByTagName("A");
    var k, aa, href, ok;
    
    
    for ( k = 0; k < a.length; k++ )
    {
      aa = a[k];

      var already = aa.getAttribute("jsed");
      if ( already == "jsed" )
        continue;

      href = aa.getAttribute("href");
//      h2 = aa.getAttribute("HREF");
      if ( !href )
      {
        //alert( [ a[k].innerHTML, aa.tagName, href, h2, aa.className ] );
        continue;
      }
      
      ok = false;
      
      if ( href.substr( 0, this.domain.length ) == this.domain )
      {
        href = href.substr( this.domain.length );
        ok = true;
      }
      else
      if ( href.substr( 0, 1 ) == '/' )
        ok = true;
        
      if ( href == '' )
        continue;
        
      if ( !ok )
        continue;
        
/*      var already = aa.getAttribute("jsed");
      
      if ( already == "jsed" )
        continue;*/
        
      /*aa.href = "javascript:ajaxed.click('" + href +"')"; */
      addEvent( aa, "click", this.onClick );
      aa.setAttribute( "jsed", "jsed" );
    }
  },

  onClick: function(e)
  {
    e.preventDefault();
    
    if ( !ajaxed.hashon )
      return;

    ajaxed.hashon = false;
      
    var target = e.srcElement ? e.srcElement : e.target;
    
    while ( target && ( !target.tagName || target.tagName != 'A' ) )
      target = target.parentNode;
      
    if ( !target )
      return;
      
    var url = target.getAttribute("href");
    if ( !url )
      return;
      
    if ( url.substr( 0, ajaxed.domain.length ) == ajaxed.domain )
         url = url.substr( ajaxed.domain.length );
    
    ajaxed.click( url );
  },

  click: function(url)
  {
      if ( url == '' )
        return;
      
      if ( !this.loader )
      {
         window.location = url;
         return;
      }
      
      //  alert( url );
      document.body.style.cursor = 'wait';
      this.hashon = false;
      window.location.hash = url;
      this.load( url );
  },


  load: function(value) {
      // Create new JsHttpRequest object.
      var req = new JsHttpRequest();
      // Code automatically called on load finishing.
      req.onreadystatechange = function() {
              //alert( req.readyState );
          if (req.readyState == 4) {
  //            alert( req.responseText );
              ajaxed.onPage( req.responseText );
              ajaxed.rescan();
              ajaxed.hashon = true;
              document.body.style.cursor = 'default';
          }
      }
      // Prepare request object (automatically choose GET or POST).
      req.open(null, '/smpl_backend.php', true);
      // Send data to backend.
      req.send( { q: value } );
  },

  onPage: function( text )
  {
      var pbody = text.indexOf('<'+'body');
      var tmp = text.substr( 0, pbody );
      
      tmp = tmp.substr( tmp.indexOf( '<title' ) );
      tmp = tmp.substr( 0, tmp.indexOf( '</title' ) );
      
      this.loader.innerHTML = tmp.replace( "title", "abbr" );
      
      var title = this.loader.getElementsByTagName('ABBR'); 
      if ( title.length > 0 )
        document.title = title[0].innerHTML;
      
      
      this.loader.innerHTML = text.substr( pbody );
      this.marks = new Array();
      var nodes = this.loader.childNodes;
      var k;
    
      // search for first DIV == 'all'
      for ( k = 0; k < nodes.length; k++ )
      {
          if ( this.loader.childNodes[k].scanned ||
               nodes[k].tagName != 'DIV' )
            continue;

         this.scan( this.loader.childNodes[k], $$('all') );
         break; // DO NOT REMOVE
      }
    
//      sjfw.timerSetup( 15, 61, null, this.onOpacity );
      sjfw.timerSetup( 8, 33, null, this.onOpacity );
  },

  scan: function( a, b )
  {
    if ( a.scanned )
      return;
      
    a.scanned = true;
    
    
    var atag = a ? a.tagName : null;
    var btag = b ? b.tagName : null;
    
/*    if ( !a.tagName ) a.tagName = null;
    if ( !b.tagName ) b.tagName = null;*/
    
    if ( atag == null && btag ||
         atag && btag == null ||
         atag != btag )
    {
//        alert( [ "tagNames are different: ", a.tagName, b.tagName ] );
        this.dirty( a.parentNode, b.parentNode );
        return;
    }

    if ( atag == "IMG" && a.src != b.src )
    {
        //alert( [ a.src, b.src ] );
        this.dirty( a.parentNode, b.parentNode ); 
        return;
    }

    if ( atag == "A" && a.href != b.href )
        b.href = a.href;

    if ( a.getAttribute && 
         b.getAttribute &&
         a.getAttribute("class") != b.getAttribute("class") )
    {
//        alert( [ 'className is different: ', a.tagName, a.id, a.className, b.tagName, b.id, b.className ] );
      b.className = a.className;
    } 

    if ( a.childElementCount != b.childElementCount )
    {
//       alert( [ 'childNodes.length is different: ', a.tagName, a.id, a.childNodes.length, b.tagName, b.id, b.childNodes.length ] );
//          alert( [ 'childElementCount is different: ', a.tagName, a.id, a.childElementCount, b.tagName, b.id, b.childElementCount ] );
        this.dirty( a, b );
        return;
    }

    if ( !a.childElementCount && !b.childElementCount )
    {
      if ( a['nodeValue'] &&
           b['nodeValue'] &&
/*      if ( a.nodeValue &&
           b.nodeValue &&*/
           a.nodeValue.trim() != b.nodeValue.trim()
        )
      {
//        alert( "'"+b.nodeValue.trim()+"'" );
//          alert( [ a.nodeValue, b.nodeValue ] );
//          alert( [ 'nodeValue is different: ', a.tagName, a.id, a.nodeValue, b.tagName, b.id, b.nodeValue ] );
          this.dirty( a.parentNode, b.parentNode );
          return;
      }
    }

    var anodes = a.childNodes,
        bnodes = b.childNodes;
        
    var k = 0;

    for ( k = 0; k < anodes.length && k < bnodes.length; k++ )
    if ( !anodes[k].scanned )
        this.scan( anodes[k], bnodes[k] );

    var anodes = a.childNodes,
        bnodes = b.childNodes;
    var k = 0;
    for ( k = 0; k < anodes.length && k < bnodes.length; k++ )
    if ( !anodes[k].scanned )
        this.scan( anodes[k], bnodes[k] );
  },

  dirty: function( a, b )
  {
    sjfw.opacity( b, 0 );
    b.innerHTML = a.innerHTML;
    this.marks[ this.marks.length ] = b;
  },

  onOpacity: function( timerIndex, done )
  {
      var data = sjfw.timers[ timerIndex ];
      var i;
      for ( i = 0; i < ajaxed.marks.length; i++ )
      {
        sjfw.opacity( ajaxed.marks[i], done ? 100 : data.step*25 );
      }
  }

}


