if(!s1JS.Event.addListener)
{
   s1JS.Event = function()
   {
       var pageLoaded   = false;
       var events       = [];
       var legacyEvents = [];
       var legacyMap    = [];
       var preloadStack = [];

       return  {

          isSafari:(/Safari|Konqueror|KHTML/gi).test(navigator.userAgent),
          isIE:(!this.isSafari && !navigator.userAgent.match(/opera/gi) && navigator.userAgent.match(/msie/gi)),
          pollHandle: null,
          pollInterval: 20,
          retryCount:100,
          
          /**
           *  Indexes for the events and their properties in the event queue
           *    EL  = element(id), 
           *    ET  = event type, 
           *    FN  = callback function
           *    TR  = scope element (in EventQueue) or the wrapper function (in events)
           *    UT  = use target (in EventQueue) or the scope element (in events)
           */
          EL:0,
          ET:1,
          FN:2,
          TR:3,
          UT:4,

          onElementReady:function(id, fn)
          {
             preloadStack.push( { id: id, fn: fn, reqReady: true } );
             this._beginPreload();
          }, 

          onElementExists:function(id, fn)
          {
             preloadStack.push( { id: id, fn: fn, reqReady: false } );
             this._beginPreload();
          }, 

          addListener:function(el, action, fn, target, useTarget)
          {
             if(this._isValidCollection(el))
             {
                var success = true;
                for(i = 0; i < el.length; i++)
                {
                   success = this.addListener(el[i], action, fn, target, useTarget) && success; 
                }
                return success;
             }
             else if(typeof el == "string")
             {
                var check_el = this._get(el);

                if(!check_el && !pageLoaded)
                {
                   this.onElementExists(el, function() { s1JS.Event.addListener(el, action, fn, target, useTarget); });
                   return true;
                }
                else
                {
                   el = check_el;
                }
             }

             if(!el) { return false; }

             if(useTarget) { target = this._get(target); } 
           
             var scope = (useTarget) ? target : el;

             var wrapper = function(e) { 

                 var fixed_event = e;
		
                 if(!fixed_event.target)
                 {
                    fixed_event.target = fixed_event.srcElement || document;
                 }

                 if(fixed_event.target.nodeType == 3) 
                 {
                    fixed_event.target = e.target.parentNode;
                 } 

                 return fn.call(scope, s1JS.Event.getEvent(fixed_event)); 
             };

             var ev = [el, action, fn, wrapper, target];
             var index = events.length;
             events[index] = ev;

             if(this.useLegacyEventModel(el, action))
             {
                var legacyIndex = this.getLegacyIndex(el,action);
                if(legacyIndex==-1)
                {
                   legacyIndex = legacyEvents.length;
                   legacyEvents[legacyIndex] = [el,action,el["on"+action]];
                   legacyMap[legacyIndex] = [];
                   el["on"+action]=function(e)
                   {
                      s1JS.Event.fireLegacyEvent(s1JS.Event.getEvent(e),legacyIndex);
                   };
                }
                legacyMap[legacyIndex].push(index);
             }
             else if(el.addEventListener)
             {
                el.addEventListener(action, wrapper, false);
             }
             else if(el.attachEvent)
             {
                el.attachEvent("on"+action, wrapper);
             }

             return true;
          },

          _beginPreload:function()
          {
             if(!this.pollHandle)
             {
                var scope = this;
                var callback = function() { scope._doPreload(); };
                this.pollHandle = setInterval( callback, this.pollInterval );
             }
          },

          _doPreload:function()
          {
             var retry = !pageLoaded;

             if(!retry)
             {
                retry = (this.retryCount > 0);
             }

             var notReady = [];
             for(var i = 0; i < preloadStack.length; i++)
             {
                var item = preloadStack[i];
                if(item)
                {
                   var el = this._get(item.id);

                   if(el)
                   {
                      if( !item.reqReady || pageLoaded || el.nextSibling || (document && document.body) )
                      {
                         item.fn.call(el);
                         delete preloadStack[i];
                      }
                      else
                      {
                         notReady.push(el);
                      }
                   }                   
                }
             }

             this.retryCount = (notReady.length === 0) ? 0 : this.retryCount - 1;

             if(retry) 
             {
                this._beginPreload();
             }
             else
             {
                clearInterval(this.pollHandle);
                this.pollHandle = null;
             }
          },

          useLegacyEventModel:function(el, action) 
          {
             if (!el.addEventListener && !el.attachEvent) 
             {
                 return true;
             }
             return false;
          },

          getLegacyIndex:function(el,action)
          {
             for(var i = 0; i < legacyEvents.length; ++i)
             {
                var le = legacyEvents[i];
                if(le && le[0] == el && le[1] == action)
                {
                   return i;
                }
             }
             return-1;
          },

          fireLegacyEvent:function(e,legacyIndex)
          {
             var ok = true;
             var le = legacyMap[legacyIndex];
             for(i = 0; i < le.length; ++i)
             {
                var index = le[i];
                if(index)
                {
                   var li = events[index];
                   var scope = li[this.UT]; 
                   var ret = li[this.TR].call(scope,e);
                   ok = (ok && ret);
                }
             }
             return ok;
          },

          getEvent:function(e)
          {
             var ev = e || window.event;
             return ev;
          },

          getTarget: function(e) 
          {
             var targ = e.target || e.srcElement;

             if (targ && targ.nodeType == 3) 
             {
                return targ.parentNode;
             } 
             else 
             {
                return targ;
             }
          },

          stopEvent:function(e)
          {
             if (e.stopPropagation) 
             {
                e.stopPropagation();
             }
             else
             {
                e.cancelBubble = true;
             }
 
             if (e.preventDefault) 
             {
                e.preventDefault();
             } 
             else 
             {
                e.returnValue = false;
             }
             return false; // for IE
          },

          _get:function(id)
          {
             if(typeof id == 'string')
             {
                id = document.getElementById(id);
             }
             return id;
          },

          _setPageLoaded:function()
          {
             pageLoaded = true;
          },

          _isValidCollection:function(o)
          {
             return ( o           &&   
             o.length             &&    
             typeof o != "string" &&    
             !o.tagName           &&      // not a HTML Element
             !o.alert             &&      // not a window
             typeof o[0] != "undefined")  // it is populated ;
          }
    
       };    
   } ();

   if(document && document.body)
   {
      s1JS.Event._setPageLoaded();
   }
   else
   {
      s1JS.Event.addListener(window,"load",s1JS.Event._setPageLoaded);  
   }
   s1JS.Event._doPreload();     
}
