<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>deprecated/event.js</filename>
    </added>
    <added>
      <filename>foundation/mixins/array.js</filename>
    </added>
    <added>
      <filename>foundation/mixins/collection_view_delegate.js</filename>
    </added>
    <added>
      <filename>foundation/mixins/control.js</filename>
    </added>
    <added>
      <filename>foundation/mixins/delegate_support.js</filename>
    </added>
    <added>
      <filename>foundation/mixins/editable.js</filename>
    </added>
    <added>
      <filename>foundation/mixins/enumerable.js</filename>
    </added>
    <added>
      <filename>foundation/mixins/inline_editor_delegate.js</filename>
    </added>
    <added>
      <filename>foundation/mixins/observable.js</filename>
    </added>
    <added>
      <filename>foundation/mixins/scrollable.js</filename>
    </added>
    <added>
      <filename>foundation/mixins/selection_support.js</filename>
    </added>
    <added>
      <filename>foundation/mixins/validatable.js</filename>
    </added>
    <added>
      <filename>foundation/system/browser.js</filename>
    </added>
    <added>
      <filename>foundation/system/core_query.js</filename>
    </added>
    <added>
      <filename>foundation/system/ready.js</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -49,8 +49,8 @@ source.  Keep in mind that all of this source is combined into a single file
 when your application is built:
 
 system:
-  This directory contains the low-level files concerned with starting an
-  app and providing basic classes such as SC.Object.
+  Files here implement low-level APIs and utility functions that integrate 
+  with the browser.
   
 mixins:
   This directory contains mixins and protocols you might include on other</diff>
      <filename>HACKING</filename>
    </modified>
    <modified>
      <diff>@@ -4,8 +4,8 @@
 // ========================================================================
 
 require('controllers/controller') ;
-require('mixins/array') ;
-require('mixins/selection_support') ;
+require('foundation/mixins/array') ;
+require('foundation/mixins/selection_support') ;
 require('foundation/system/binding') ;
 
 /** @class</diff>
      <filename>controllers/array.js</filename>
    </modified>
    <modified>
      <diff>@@ -3,7 +3,7 @@
 // copyright 2006-2008 Sprout Systems, Inc.
 // ========================================================================
 
-require('mixins/selection_support') ;
+require('foundation/mixins/selection_support') ;
 require('controllers/object') ;
 
 /** @class</diff>
      <filename>controllers/collection.js</filename>
    </modified>
    <modified>
      <diff>@@ -3,7 +3,7 @@
 // copyright 2006-2008 Sprout Systems, Inc.
 // ========================================================================
 
-require('system/browser');
+require('foundation/system/browser');
 
 /**
   @deprecated</diff>
      <filename>deprecated/browser.js</filename>
    </modified>
    <modified>
      <diff>@@ -5,8 +5,8 @@
 
 require('core') ;
 require('foundation/system/benchmark') ;
-require('mixins/observable') ;
-require('mixins/array') ;
+require('foundation/mixins/observable') ;
+require('foundation/mixins/array') ;
 
 SC.BENCHMARK_OBJECTS = NO;
 </diff>
      <filename>foundation/object.js</filename>
    </modified>
    <modified>
      <diff>@@ -3,7 +3,7 @@
 // copyright 2006-2008 Sprout Systems, Inc.
 // ========================================================================
 
-require('system/ready') ;
+require('foundation/system/ready') ;
 require('foundation/path_module') ;
 
 /**</diff>
      <filename>foundation/page.js</filename>
    </modified>
    <modified>
      <diff>@@ -3,8 +3,8 @@
 // copyright 2006-2008, Sprout Systems, Inc. and contributors.
 // ==========================================================================
 
-require('mixins/enumerable') ;
-require('mixins/observable') ;
+require('foundation/mixins/enumerable') ;
+require('foundation/mixins/observable') ;
 
 /**
   @class </diff>
      <filename>foundation/set.js</filename>
    </modified>
    <modified>
      <diff>@@ -1,36 +1,664 @@
-// ==========================================================================
-// SproutCore -- JavaScript Application Framework
-// copyright 2006-2008, Sprout Systems, Inc. and contributors.
-// ==========================================================================
+// ========================================================================
+// SproutCore
+// copyright 2006-2008 Sprout Systems, Inc.
+// ========================================================================
 
-// This file defines some basic extensions to the built-in Event object to
-// provide some common utility functions.
+require('core');
+require('foundation/system/core_query') ;
 
-SC.mixin(Event,{
+/**
+  The event class provides a simple cross-platform library for capturing and
+  delivering events on DOM elements and other objects.  While this library
+  is based on code from both jQuery and Prototype.js, it includes a number of
+  additional features including support for handler objects and event 
+  delegation.
+
+  Since native events are implemented very unevenly across browsers,
+  SproutCore will convert all native events into a standardized instance of
+  this special event class.  
+  
+  SproutCore events implement the standard W3C event API as well as some 
+  additional helper methods.
+
+  @constructor
+  @param {Event} originalEvent
+  @returns {SC.Event} event instance
+  
+  @since SproutCore 1.0
+*/
+SC.Event = function(originalEvent) { 
+
+  // copy properties from original event, if passed in.
+  if (originalEvent) {
+    this.originalEvent = originalEvent ;
+    var props = SC.Event._props, len = props.length, idx = len ;
+    while(--idx &gt;= 0) {
+      var key = props[idx] ;
+      this[key] = originalEvent[key] ;
+    }
+  }
+
+  // Fix timeStamp
+  this.timeStamp = this.timeStamp || Date.now();
+
+  // Fix target property, if necessary
+  // Fixes #1925 where srcElement might not be defined either
+  if (!this.target) this.target = this.srcElement || document; 
+
+  // check if target is a textnode (safari)
+  if (this.target.nodeType == 3 ) this.target = this.target.parentNode;
+
+  // Add relatedTarget, if necessary
+  if (!this.relatedTarget &amp;&amp; this.fromElement) {
+    this.relatedTarget = (this.fromElement === this.target) ? this.toElement : this.fromElement;
+  }
+
+  // Calculate pageX/Y if missing and clientX/Y available
+  if ( this.pageX == null &amp;&amp; this.clientX != null ) {
+    var doc = document.documentElement, body = document.body;
+    this.pageX = this.clientX + (doc &amp;&amp; doc.scrollLeft || body &amp;&amp; body.scrollLeft || 0) - (doc.clientLeft || 0);
+    this.pageY = this.clientY + (doc &amp;&amp; doc.scrollTop || body &amp;&amp; body.scrollTop || 0) - (doc.clientTop || 0);
+  }
+
+  // Add which for key events
+  if (!this.which &amp;&amp; ((this.charCode || event.charCode === 0) ? this.charCode : this.keyCode)) {
+    this.which = this.charCode || this.keyCode;
+  }
+
+  // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+  if (!this.metaKey &amp;&amp; this.ctrlKey) this.metaKey = this.ctrlKey;
+
+  // Add which for click: 1 == left; 2 == middle; 3 == right
+  // Note: button is not normalized, so don't use it
+  if (!this.which &amp;&amp; this.button) {
+    this.which = (this.button &amp; 1 ? 1 : ( this.button &amp; 2 ? 3 : ( this.button &amp; 4 ? 2 : 0 ) ));
+  }
   
-  // get the character code for key pressed events.
-  getCharCode: function(e) {
-    return (e.keyCode) ? e.keyCode : ((e.which)?e.which:0) ; 
+  return this; 
+} ;
+
+SC.mixin(SC.Event, /** @scope SC.Event */ {
+
+  /** 
+    Standard method to create a new event.  Pass the native browser event you
+    wish to wrap if needed.
+  */
+  create: function(e) { return new SC.Event(e); },
+
+  // the code below was borrowed from jQuery, Dean Edwards, and Prototype.js
+  
+  /**
+    Bind an event to an element.
+
+    This method will cause the passed handler to be executed whenever a
+    relevant event occurs on the named element.  This method supports a
+    variety of handler types, depending on the kind of support you need.
+    
+    h2. Simple Function Handlers
+    
+      SC.Event.add(anElement, &quot;click&quot;, myClickHandler) ;
+      
+    The most basic type of handler you can pass is a function.  This function
+    will be executed everytime an event of the type you specify occurs on the
+    named element.  You can optionally pass an additional context object which
+    will be included on the event in the event.data property.
+    
+    When your handler function is called the, the function's &quot;this&quot; property
+    will point to the element the event occurred on.
+    
+    The click handler for this method must have a method signature like:
+    
+      function(event) { return YES|NO; }
+      
+    h2. Method Invocations
+    
+      SC.Event.add(anElement, &quot;click&quot;, myObject, myObject.aMethod) ;
+      
+    Optionally you can specify a target object and a method on the object to 
+    be invoked when the event occurs.  This will invoke the method function
+    with the target object you pass as &quot;this&quot;.  The method should have a 
+    signature like:
+    
+      function(event, targetElement) { return YES|NO; }
+      
+    Like function handlers, you can pass an additional context data paramater
+    that will be included on the event in the event.data property.
+      
+    h2. Handler Return Values
+    
+    Both handler functions should return YES if you want the event to 
+    continue to propagate and NO if you want it to stop.  Returning NO will
+    both stop bubbling of the event and will prevent any default action 
+    taken by the browser.  You can also control these two behaviors separately
+    by calling the stopPropogation() or preventDefault() methods on the event
+    itself, returning YES from your method.
+    
+    h2. Limitations
+    
+    Although SproutCore's event implementation is based on jQuery, it is 
+    much simpler in design.  Notably, it does not support namespaced events
+    and you can only pass a single type at a time.
+    
+    If you need more advanced event handling, consider the SC.Responder 
+    functionality provided by SproutCore or use your favorite DOM library.
+
+    @param {Element} elem a DOM element, window, or document object
+    @param {String} eventType the event type you want to respond to
+    @param {Object} target The target object for a method call or a function.
+    @param {Object} method optional method or method name if target passed
+    @param {Object} context optional context to pass to the handler as event.data
+    @returns {Object} receiver
+  */
+  add: function(elem, eventType, target, method, context) {
+    
+    // cannot register events on text nodes, etc.
+    if ( elem.nodeType == 3 || elem.nodeType == 8 ) return SC.Event;
+
+    // For whatever reason, IE has trouble passing the window object
+    // around, causing it to be cloned in the process
+    if (SC.browser.msie &amp;&amp; elem.setInterval) elem = window;
+
+    // if target is a function, treat it as the method, with optional context
+    if (SC.typeOf(target) === SC.T_FUNCTION) {
+      context = method; method = target; target = null;
+      
+    // handle case where passed method is a key on the target.
+    } else if (target &amp;&amp; SC.typeOf(method) === SC.T_STRING) {
+      method = target[method] ;
+    }
+
+    // Get the handlers queue for this element/eventType.  If the queue does
+    // not exist yet, create it and also setup the shared listener for this
+    // eventType.
+    var events = SC.data(elem, &quot;events&quot;) || SC.data(elem, &quot;events&quot;, {}) ;
+    var handlers = events[eventType]; 
+    if (!handlers) {
+      handlers = events[eventType] = {} ;
+      this._addEventListener(elem, eventType) ;
+    }
+    
+    // Build the handler array and add to queue
+    handlers[SC.guidFor(method)] = [target, method, context];
+    SC.Event._global[eventType] = YES ; // optimization for global triggers
+
+    // Nullify elem to prevent memory leaks in IE
+    elem = events = handlers = null ;
+    return this ;
+  },
+
+  /**
+    Removes a specific handler or all handlers for an event or event+type.
+
+    To remove a specific handler, you must pass in the same function or the
+    same target and method as you passed into SC.Event.add().  See that method
+    for full documentation on the parameters you can pass in.
+    
+    If you omit a specific handler but provide both an element and eventType,
+    then all handlers for that element will be removed.  If you provide only
+    and element, then all handlers for all events on that element will be
+    removed.
+    
+    h2. Limitations
+    
+    Although SproutCore's event implementation is based on jQuery, it is 
+    much simpler in design.  Notably, it does not support namespaced events
+    and you can only pass a single type at a time.
+    
+    If you need more advanced event handling, consider the SC.Responder 
+    functionality provided by SproutCore or use your favorite DOM library.
+    
+    @param {Element} elem a DOM element, window, or document object
+    @param {String} eventType the event type to remove
+    @param {Object} target The target object for a method call.  Or a function.
+    @param {Object} method optional name of method
+    @returns {Object} receiver
+  */
+  remove: function(elem, eventType, target, method) {
+    
+    // don't do events on text and comment nodes
+    if ( elem.nodeType == 3 || elem.nodeType == 8 ) return SC.Event;
+
+    // For whatever reason, IE has trouble passing the window object
+    // around, causing it to be cloned in the process
+    if (SC.browser.msie &amp;&amp; elem.setInterval) elem = window;
+
+    var handlers, key, events = SC.data(elem, &quot;events&quot;) ;
+    if (!events) return this ; // nothing to do if no events are registered
+
+    // if no type is provided, remove all types for this element.
+    if (eventType == undefined) {
+      for(eventType in events) this.remove(elem, eventType) ;
+
+    // otherwise, remove the handler for this specific eventType if found
+    } else if (handlers = events[eventType]) {
+
+      var cleanupHandlers = NO ;
+      
+      // if a target/method is provided, remove only that one
+      if (target || method) {
+        
+        // normalize the target/method
+        if (SC.typeOf(target) === SC.T_FUNCTION) {
+          method = target; target = null ;
+        } else if (SC.typeOf(method) === SC.T_STRING) {
+          method = target[method] ;
+        }
+        
+        delete events[SC.guidFor(method)] ;
+        
+        // check to see if there are handlers left on this event/eventType.
+        // if not, then cleanup the handlers.
+        key = null ;
+        for(var key in handlers) break ;
+        if (key == null) cleanupHandlers = YES ;
+
+      // otherwise, just cleanup all handlers
+      } else cleanupHandlers = YES ;
+      
+      // If there are no more handlers left on this event type, remove 
+      // eventType hash from queue.
+      if (cleanupHandlers) {
+        delete events[eventType] ;
+        this._removeEventListener(elem, eventType) ;
+      }
+      
+      // verify that there are still events registered on this element.  If 
+      // there aren't, cleanup the element completely to avoid memory leaks.
+      key = null ;
+      for(key in events) break;
+      if(!key) {
+        SC.removeData(elem, &quot;events&quot;) ;
+        delete this._elements[SC.guidFor(elem)]; // important to avoid leaks
+      }
+      
+    }
+    
+    elem = events = handlers = null ; // avoid memory leaks
+    return this ;
+  },
+
+  /**
+    Trigger an event execution immediately.  You can use this method to 
+    simulate arbitrary events on arbitary elements.
+
+    h2. Limitations
+    
+    Note that although this is based on the jQuery implementation, it is 
+    much simpler.  Notably namespaced events are not supported and you cannot
+    trigger events globally.
+    
+    If you need more advanced event handling, consider the SC.Responder 
+    functionality provided by SproutCore or use your favorite DOM library.
+
+    @param elem {Element} the target element
+    @param eventType {String} the event type
+    @param args {Array} optional argument or arguments to pass to handler.
+    @param donative ??
+    @returns {Boolean} Return value of trigger or undefined if not fired
+  */
+  trigger: function(elem, eventType, args, donative) {
+
+    // don't do events on text and comment nodes
+    if ( elem.nodeType == 3 || elem.nodeType == 8 ) return undefined;
+    
+    // Normalize to an array
+    args = SC.$A(args) ;
+
+    var ret, fn = SC.typeOf(elem[eventType] || null) === T_FUNCTION ;
+
+    // Get the event to pass, creating a fake one if necessary
+    var event = args[0];
+    if (!event || !event.preventDefault) {
+      event = {
+        type: eventType,
+        target: elem,
+        preventDefault: function(){},
+        stopPropagation: function(){},
+        timeStamp: Date.now(),
+        normalized: YES
+      } ;
+      args.unshift(event) ;
+    }
+
+    event.type = eventType ;
+
+    // Trigger the event
+    ret = SC.Event.handle.apply(elem, args) ;
+
+    // Handle triggering native .onfoo handlers
+    var onfoo = elem[&quot;on&quot; + eventType] ;
+    var isClick = SC.CoreQuery.nodeName(elem, 'a') &amp;&amp; eventType === 'click';
+    if ((!fn || isClick) &amp;&amp; onfoo &amp;&amp; onfoo.apply(elem, args) === NO) ret = NO;
+
+    // Trigger the native events (except for clicks on links)
+    if (fn &amp;&amp; donative !== NO &amp;&amp; ret !== NO &amp;&amp; !isClick) {
+      this.triggered = YES;
+      try {
+        elem[ eventType ]();
+      // prevent IE from throwing an error for some hidden elements
+      } catch (e) {}
+    }
+    
+    this.triggered = NO;
+
+    return ret;
+  },
+
+  /**
+    This method will handle the passed event, finding any registered listeners
+    and executing them.  If you have an event you want handled, you can 
+    manually invoke this method.  This function expects it's &quot;this&quot; value to
+    be the element the event occurred on, so you should always call this 
+    method like:
+    
+      SC.Event.handle.call(element, event) ;
+      
+    Note that like other parts of this library, the handle function does not
+    support namespaces.
+    
+    @param event {Event} the event to handle
+    @returns {Boolean}
+  */
+  handle: function(event) {
+
+    // ignore events triggered after window is unloaded or if double-called
+    // from within a trigger.
+    if ((typeof SC === &quot;undefined&quot;) || SC.Event.triggered) return YES ;
+    
+    // returned undefined or NO
+    var val, ret, namespace, all, handlers;
+
+    // normalize event across browsers.  The new event will actually wrap the
+    // real event with a normalized API.
+    event = arguments[0] = SC.Event._normalizeEvent(event || window.event) ;
+
+    // get the handlers for this event type
+    handlers = (SC.data(this, &quot;events&quot;) || {})[event.type];
+    if (handlers) return NO ; // nothing to do
+
+    // invoke all handlers
+    for (var key in handlers ) {
+      var handler = handlers[key];
+      var method = handler[1] ;
+
+      // Pass in a reference to the handler function itself
+      // So that we can later remove it
+      event.handler = method;
+      event.data = event.context = handler[2];
+
+      var target = handler[0] || this ;
+      ret = method.apply( target, arguments );
+      if (val !== NO) val = ret;
+
+      // if method returned NO, do not continue.  Stop propogation and
+      // return default.  Note that we test explicitly for NO since 
+      // if the handler returns no specific value, we do not want to stop.
+      if ( ret === NO ) {
+        event.preventDefault();
+        event.stopPropagation();
+      }
+    }
+
+    return val;
+  },
+
+  /**
+    This method is called just before the window unloads to unhook all 
+    registered events.
+  */
+  unload: function() {
+    var key, elements = this._elements ;
+    for(key in elements) this.remove(elements[key]) ;
+    
+    // just in case some book-keeping was screwed up.  avoid memory leaks
+    for(key in elements) delete elements[key] ;
+    delete this._elements ; 
   },
   
-  // get the pressed char as a string.
-  getCharString: function(e) {
-    return String.fromCharCode(Event.getCharCode(e)) ;
+  /**
+    This hash contains handlers for special or custom events.  You can add
+    your own handlers for custom events here by simply naming the event and
+    including a hash with the following properties:
+    
+     - setup: this function should setup the handler or return NO
+     - teardown: this function should remove the event listener
+     
+  */
+  special: {
+    
+    ready: {
+      setup: function() {
+        // Make sure the ready event is setup
+        SC._bindReady() ;
+        return;
+      },
+
+      teardown: function() { return; }
+
+    },
+
+    /** @private
+        Implement support for mouseenter on browsers other than IE */
+    mouseenter: {
+      setup: function() {
+        if ( SC.browser.msie ) return NO;
+        SC.Event.add(this, 'mouseover', SC.Event.special.mouseover.handler);
+        return YES;
+      },
+
+      teardown: function() {
+        if ( jQuery.browser.msie ) return NO;
+        SC.Event.remove(this, 'mouseover', SC.Event.special.mouseover.handler);
+        return YES;
+      },
+
+      handler: function(event) {
+        // If we actually just moused on to a sub-element, ignore it
+        if ( SC.Event._withinElement(event, this) ) return YES;
+        // Execute the right handlers by setting the event type to mouseenter
+        event.type = &quot;mouseenter&quot;;
+        return SC.Event.handle.apply(this, arguments);
+      }
+    },
+
+    /** @private
+        Implement support for mouseleave on browsers other than IE */
+    mouseleave: {
+      setup: function() {
+        if ( SC.browser.msie ) return NO;
+        SC.Event.add(this, &quot;mouseout&quot;, SC.Event.special.mouseleave.handler);
+        return YES;
+      },
+
+      teardown: function() {
+        if ( SC.browser.msie ) return NO;
+        SC.Event.remove(this, &quot;mouseout&quot;, SC.Event.special.mouseleave.handler);
+        return YES;
+      },
+
+      handler: function(event) {
+        // If we actually just moused on to a sub-element, ignore it
+        if ( SC.Event._withinElement(event, this) ) return YES;
+        // Execute the right handlers by setting the event type to mouseleave
+        event.type = &quot;mouseleave&quot;;
+        return SC.Event.handle.apply(this, arguments);
+      }
+    }
+  },
+
+  KEY_BACKSPACE: 8,
+  KEY_TAB:       9,
+  KEY_RETURN:   13,
+  KEY_ESC:      27,
+  KEY_LEFT:     37,
+  KEY_UP:       38,
+  KEY_RIGHT:    39,
+  KEY_DOWN:     40,
+  KEY_DELETE:   46,
+  KEY_HOME:     36,
+  KEY_END:      35,
+  KEY_PAGEUP:   33,
+  KEY_PAGEDOWN: 34,
+  KEY_INSERT:   45,
+    
+  _withinElement: function(event, elem) {
+    // Check if mouse(over|out) are still within the same parent element
+    var parent = event.relatedTarget;
+    
+    // Traverse up the tree
+    while ( parent &amp;&amp; parent != elem ) {
+      try { parent = parent.parentNode; } catch(error) { parent = elem; }
+    }
+
+    // Return YES if we actually just moused on to a sub-element
+    return parent === elem;
   },
   
-  pointerLocation: function(event) {
-    var ret = {
-      x: event.pageX || (event.clientX +
-        (document.documentElement.scrollLeft || document.body.scrollLeft)),
-      y: event.pageY || (event.clientY +
-        (document.documentElement.scrollTop || document.body.scrollTop))
+  /** @private
+    Adds the primary event listener for the named type on the element.
+    
+    If the event type has a special handler defined in SC.Event.special, 
+    then that handler will be used.  Otherwise the normal browser method will
+    be used.
+    
+    @param elem {Element} the target element
+    @param eventType {String} the event type
+  */
+  _addEventListener: function(elem, eventType) {
+    var listener, special = this.special[eventType] ;
+
+    // Check for a special event handler
+    // Only use addEventListener/attachEvent if the special
+    // events handler returns NO
+    if ( !special || special.setup.call(elem)===NO) {
+      
+      // Save element in cache.  This must be removed later to avoid 
+      // memory leaks.
+      var guid = SC.guidFor(elem) ;
+      this._elements[guid] = elem;
+      
+      var listener = SC.data(elem, &quot;listener&quot;) || SC.data(elem, &quot;listener&quot;, 
+       function() {
+         return SC.Event.handle.apply(SC.Event._elements[guid], arguments); 
+      }) ;
       
-    };
-    return ret ;
+      // Bind the global event handler to the element
+      if (elem.addEventListener) {
+        elem.addEventListener(eventType, listener, NO);
+      } else if (elem.attachEvent) {
+        elem.attachEvent(&quot;on&quot; + eventType, listener);
+      }
+    }
+    
+    elem = special = listener = null ; // avoid memory leak
   },
+
+  /** @private
+    Removes the primary event listener for the named type on the element.
+    
+    If the event type has a special handler defined in SC.Event.special, 
+    then that handler will be used.  Otherwise the normal browser method will
+    be used.
+    
+    Note that this will not clear the _elements hash from the element.  You
+    must call SC.Event.unload() on unload to make sure that is cleared.
+    
+    @param elem {Element} the target element
+    @param eventType {String} the event type
+  */
+  _removeEventListener: function(elem, eventType) {
+    var listener, special = SC.Event.special[eventType] ;
+    if (!special || (special.teardown.call(elem)===NO)) {
+      listener = SC.data(elem, &quot;listener&quot;) ;
+      if (listener) if (elem.removeEventListener) {
+        elem.removeEventListener(eventType, listener, NO);
+      } else if (elem.detachEvent) {
+        elem.detachEvent(&quot;on&quot; + eventType, listener);
+      }
+    }
+    
+    elem = special = listener = null ;
+  },
+
+  _elements: {},
   
-  ALT_KEY: '_ALT',
-  CTRL_KEY: '_CTRL',
-  SHIFT_KEY: '_SHIFT'
+  // implement preventDefault() in a cross platform way
   
-});
+  /** @private Take an incoming event and convert it to a normalized event. */
+  _normalizeEvent: function(event) {
+    return (event.normalized) ? event : SC.Event.create(event) ;
+  },
+  
+  _global: {},
+
+  /** @private properties to copy from native event onto the event */
+  _props: &quot;altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target timeStamp toElement type view wheelDelta which&quot;.split(&quot; &quot;)
+  
+}) ;
+
+SC.Event.prototype = {
+
+  /** 
+    Implements W3C standard.  Will prevent the browser from performing its
+    default action on this event.
+    
+    @returns {SC.Event} receiver
+  */
+  preventDefault: function() {
+    var evt = this.originalEvent ;
+    if (evt) {
+      if (evt.preventDefault) evt.preventDefault() ;
+      evt.returnValue = NO ; // IE
+    }
+    return this ;
+  },
+
+  /**
+    Implements W3C standard.  Prevents further bubbling of the event.
+    
+    @returns {SC.Event} receiver
+  */
+  stopPropagation: function() {
+    var evt = this.originalEvent ;
+    if (evt) {
+      if (evt.stopPropogation) evt.stopPropagation() ;
+      evt.cancelBubble = YES ; // IE
+    }
+    return this ;
+  },
+
+  /** 
+    Stops both the default action and further propogation.  This is more 
+    convenient than calling both.
+    
+    @returns {SC.Event} receiver
+  */
+  stop: function() {
+    return this.preventDefault().stopPropogation();
+  },
+  
+  /** Always YES to indicate the event was normalized. */
+  normalized: YES,
+
+  /** Returns the pressed character (found in this.which) as a string. */
+  getCharString: function() { 
+    return String.fromCharCode(this.which) ;
+  }
+    
+} ;
+
+// Also provide a Prototype-like API so that people can use either one.
+
+/** Alias for add() method.  This provides a Prototype-like API. */
+SC.Event.observe = SC.Event.add ;
+
+/** Alias for remove() method.  This provides a Prototype-like API */
+SC.Event.stopObserving = SC.Event.remove ;
+
+/** Alias for trigger() method.  This provides a Prototype-like API */
+SC.Event.fire = SC.Event.trigger;
+
+// Register unload handler to eliminate any registered handlers
+// This avoids leaks in IE and issues with mouseout or other handlers on 
+// other browsers.
+SC.Event.add(window, 'unload', SC.Event, SC.Event.unload) ;</diff>
      <filename>foundation/system/event.js</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,7 @@
 // ==========================================================================
 
 // These are helpful utility functions for calculating range and rect values
-require('system/browser');
+require('foundation/system/browser');
 
 SC.mixin( 
 /** @scope SC */</diff>
      <filename>foundation/system/utils.js</filename>
    </modified>
    <modified>
      <diff>@@ -5,7 +5,7 @@
 
 require('views/view') ;
 require('views/container') ;
-require('system/ready') ;
+require('foundation/system/ready') ;
 
 /**
   @class Manages the panels on a page.</diff>
      <filename>globals/panels.js</filename>
    </modified>
    <modified>
      <diff>@@ -6,7 +6,7 @@
 require('views/view') ;
 require('views/container') ;
 require('globals/panels') ;
-require('system/ready') ;
+require('foundation/system/ready') ;
 
 // This singleton manages the popups on the page.  It will show an element
 // called 'popups', which is appended to the end of the body node.  To show</diff>
      <filename>globals/popups.js</filename>
    </modified>
    <modified>
      <diff>@@ -6,7 +6,7 @@
 require('core') ;
 require('foundation/responder');
 require('panes/pane');
-require('system/browser');
+require('foundation/system/browser');
 
 SC.CAPTURE_BACKSPACE_KEY = NO ;
 </diff>
      <filename>globals/window.js</filename>
    </modified>
    <modified>
      <diff>@@ -5,7 +5,7 @@
 
 require('views/view') ;
 require('views/label') ;
-require('mixins/control') ;
+require('foundation/mixins/control') ;
 
 // Constants
 SC.TOGGLE_BEHAVIOR = 'toggle';</diff>
      <filename>views/button/button.js</filename>
    </modified>
    <modified>
      <diff>@@ -5,7 +5,7 @@
 
 require('views/view') ;
 require('views/label') ;
-require('mixins/collection_view_delegate') ;
+require('foundation/mixins/collection_view_delegate') ;
 
 SC.BENCHMARK_UPDATE_CHILDREN = NO ;
 SC.VALIDATE_COLLECTION_CONSISTANCY = NO ;</diff>
      <filename>views/collection/collection.js</filename>
    </modified>
    <modified>
      <diff>@@ -2,7 +2,7 @@
 // SC.LabelView
 // ==========================================================================
 
-require('mixins/control') ;
+require('foundation/mixins/control') ;
 require('views/image') ;
 
 /** @class</diff>
      <filename>views/collection/image_cell.js</filename>
    </modified>
    <modified>
      <diff>@@ -4,8 +4,8 @@
 // ========================================================================
 
 require('views/view') ;
-require('mixins/control') ;
-require('mixins/validatable') ;
+require('foundation/mixins/control') ;
+require('foundation/mixins/validatable') ;
 
 /**
   @class</diff>
      <filename>views/field/field.js</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,7 @@
 // ========================================================================
 
 require('views/field/field') ;
-require('mixins/editable') ;
+require('foundation/mixins/editable') ;
 
 /**
   @class</diff>
      <filename>views/field/text_field.js</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,7 @@
 // ========================================================================
 
 require('views/view') ;
-require('mixins/control') ;
+require('foundation/mixins/control') ;
 
 lc_cnt = 0 ;
 </diff>
      <filename>views/image.js</filename>
    </modified>
    <modified>
      <diff>@@ -4,10 +4,10 @@
 // ========================================================================
 
 require('views/view') ;
-require('mixins/delegate_support') ;
+require('foundation/mixins/delegate_support') ;
 require('views/field/text_field') ;
 require('views/field/textarea_field') ;
-require('mixins/inline_editor_delegate');
+require('foundation/mixins/inline_editor_delegate');
 
 /**
   @class</diff>
      <filename>views/inline_text_field.js</filename>
    </modified>
    <modified>
      <diff>@@ -4,10 +4,10 @@
 // ========================================================================
 
 require('views/view') ;
-require('mixins/control') ;
-require('mixins/delegate_support');
+require('foundation/mixins/control') ;
+require('foundation/mixins/delegate_support');
 require('views/inline_text_field');
-require('mixins/inline_editor_delegate');
+require('foundation/mixins/inline_editor_delegate');
 
 /**
   @class</diff>
      <filename>views/label.js</filename>
    </modified>
    <modified>
      <diff>@@ -4,8 +4,8 @@
 
 require('core') ;
 require('views/view') ;
-require('mixins/control');
-require('mixins/inline_editor_delegate');
+require('foundation/mixins/control');
+require('foundation/mixins/inline_editor_delegate');
 
 SC.LIST_ITEM_ACTION_CANCEL = 'sc-list-item-cancel-action';
 SC.LIST_ITEM_ACTION_REFRESH = 'sc-list-item-cancel-refresh';</diff>
      <filename>views/list_item.js</filename>
    </modified>
    <modified>
      <diff>@@ -2,7 +2,7 @@
 // SC.ScrollView
 // ==========================================================================
 
-require('mixins/scrollable') ;
+require('foundation/mixins/scrollable') ;
 require('views/container') ;
 
 /** </diff>
      <filename>views/scroll.js</filename>
    </modified>
    <modified>
      <diff>@@ -3,7 +3,7 @@
 // ==========================================================================
 
 require('views/view');
-require('mixins/control');
+require('foundation/mixins/control');
 
 /** @class
 </diff>
      <filename>views/slider.js</filename>
    </modified>
    <modified>
      <diff>@@ -3,8 +3,8 @@
 // ==========================================================================
 
 require('views/view') ;
-require('mixins/delegate_support');
-require('mixins/control') ;
+require('foundation/mixins/delegate_support');
+require('foundation/mixins/control') ;
 require('views/button/disclosure');
 
 /** @class</diff>
      <filename>views/source_list_group.js</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,7 @@
 // ========================================================================
 
 require('views/view') ;
-require('mixins/delegate_support');
+require('foundation/mixins/delegate_support');
 
 SC.HORIZONTAL = 'horizontal' ;
 SC.VERTICAL = 'vertical' ;</diff>
      <filename>views/split.js</filename>
    </modified>
    <modified>
      <diff>@@ -3,14 +3,14 @@
 // copyright 2006-2008 Sprout Systems, Inc.
 // ========================================================================
 
-require('system/browser');
+require('foundation/system/browser');
 
 require('foundation/object') ;
 require('foundation/responder') ;
 require('foundation/node_descriptor') ;
 require('foundation/system/binding');
 require('foundation/path_module');
-require('mixins/delegate_support') ;
+require('foundation/mixins/delegate_support') ;
 
 SC.BENCHMARK_OUTLETS = NO ;
 SC.BENCHMARK_CONFIGURE_OUTLETS = NO ;</diff>
      <filename>views/view.js</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>mixins/array.js</filename>
    </removed>
    <removed>
      <filename>mixins/collection_view_delegate.js</filename>
    </removed>
    <removed>
      <filename>mixins/control.js</filename>
    </removed>
    <removed>
      <filename>mixins/delegate_support.js</filename>
    </removed>
    <removed>
      <filename>mixins/editable.js</filename>
    </removed>
    <removed>
      <filename>mixins/enumerable.js</filename>
    </removed>
    <removed>
      <filename>mixins/inline_editor_delegate.js</filename>
    </removed>
    <removed>
      <filename>mixins/observable.js</filename>
    </removed>
    <removed>
      <filename>mixins/scrollable.js</filename>
    </removed>
    <removed>
      <filename>mixins/selection_support.js</filename>
    </removed>
    <removed>
      <filename>mixins/validatable.js</filename>
    </removed>
    <removed>
      <filename>system/browser.js</filename>
    </removed>
    <removed>
      <filename>system/core_query.js</filename>
    </removed>
    <removed>
      <filename>system/event.js</filename>
    </removed>
    <removed>
      <filename>system/ready.js</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>a7bfd95c17e2506b393a3b520eb51a484ff18525</id>
    </parent>
  </parents>
  <author>
    <name>Charles Jolley</name>
    <email>charles@sproutit.com</email>
  </author>
  <url>http://github.com/sproutit/sproutcore/commit/757af9b983f6d6504ea0b5ee1015b77dbb227051</url>
  <id>757af9b983f6d6504ea0b5ee1015b77dbb227051</id>
  <committed-date>2008-10-21T11:30:46-07:00</committed-date>
  <authored-date>2008-10-21T11:30:46-07:00</authored-date>
  <message>Renamed SC.event to SC.Event, made into a proper class. Moved system and mixins into foundation directory (prep for split)</message>
  <tree>6caeb34b6d34cad841e1f6eb1b0eb5800e91aae9</tree>
  <committer>
    <name>Charles Jolley</name>
    <email>charles@sproutit.com</email>
  </committer>
</commit>
