public/lib/emberjs/ember.js
function bindClasses(context, classBindings, view, bindAttrId, options) {
      var ret = [];
      var newClass, value, elem;

      // Helper method to retrieve the property from the context and
      // determine which class string to return, based on whether it is
      // a Boolean or not.
      var classStringForPath = function(root, parsedPath, options) {
        var val;
        var path = parsedPath.path;

        if (path === 'this') {
          val = root;
        } else if (path === '') {
          val = true;
        } else {
          val = handlebarsGet(root, path, options);
        }

        return View._classStringForValue(path, val, parsedPath.className, parsedPath.falsyClassName);
      };

      // For each property passed, loop through and setup
      // an observer.
      forEach.call(classBindings.split(' '), function(binding) {

        // Variable in which the old class value is saved. The observer function
        // closes over this variable, so it knows which string to remove when
        // the property changes.
        var oldClass;
        var observer;
        var parsedPath = View._parsePropertyPath(binding);
        var path = parsedPath.path;
        var pathRoot = context;
        var normalized;

        if (path !== '' && path !== 'this') {
          normalized = normalizePath(context, path, options.data);

          pathRoot = normalized.root;
          path = normalized.path;
        }

        // Set up an observer on the context. If the property changes, toggle the
        // class name.
        observer = function() {
          // Get the current value of the property
          newClass = classStringForPath(context, parsedPath, options);
          elem = bindAttrId ? view.$("[data-bindattr-" + bindAttrId + "='" + bindAttrId + "']") : view.$();

          // If we can't find the element anymore, a parent template has been
          // re-rendered and we've been nuked. Remove the observer.
          if (!elem || elem.length === 0) {
            removeObserver(pathRoot, path, observer);
          } else {
            // If we had previously added a class to the element, remove it.
            if (oldClass) {
              elem.removeClass(oldClass);
            }

            // If necessary, add a new class. Make sure we keep track of it so
            // it can be removed in the future.
            if (newClass) {
              elem.addClass(newClass);
              oldClass = newClass;
            } else {
              oldClass = null;
            }
          }
        };

        if (path !== '' && path !== 'this') {
          view.registerObserver(pathRoot, path, observer);
        }

        // We've already setup the observer; now we just need to figure out the
        // correct behavior right now on the first pass through.
        value = classStringForPath(context, parsedPath, options);

        if (value) {
          ret.push(value);

          // Make sure we save the current value so that it can be removed if the
          // observer fires.
          oldClass = value;
        }
      });

      return ret;
    }
function bindClasses(context, classBindings, view, bindAttrId, options) {
      var ret = [];
      var newClass, value, elem;

      // Helper method to retrieve the property from the context and
      // determine which class string to return, based on whether it is
      // a Boolean or not.
      var classStringForPath = function(root, parsedPath, options) {
        var val;
        var path = parsedPath.path;

        if (path === 'this') {
          val = root;
        } else if (path === '') {
          val = true;
        } else {
          val = handlebarsGet(root, path, options);
        }

        return View._classStringForValue(path, val, parsedPath.className, parsedPath.falsyClassName);
      };

      // For each property passed, loop through and setup
      // an observer.
      forEach.call(classBindings.split(' '), function(binding) {

        // Variable in which the old class value is saved. The observer function
        // closes over this variable, so it knows which string to remove when
        // the property changes.
        var oldClass;
        var observer;
        var parsedPath = View._parsePropertyPath(binding);
        var path = parsedPath.path;
        var pathRoot = context;
        var normalized;

        if (path !== '' && path !== 'this') {
          normalized = normalizePath(context, path, options.data);

          pathRoot = normalized.root;
          path = normalized.path;
        }

        // Set up an observer on the context. If the property changes, toggle the
        // class name.
        observer = function() {
          // Get the current value of the property
          newClass = classStringForPath(context, parsedPath, options);
          elem = bindAttrId ? view.$("[data-bindattr-" + bindAttrId + "='" + bindAttrId + "']") : view.$();

          // If we can't find the element anymore, a parent template has been
          // re-rendered and we've been nuked. Remove the observer.
          if (!elem || elem.length === 0) {
            removeObserver(pathRoot, path, observer);
          } else {
            // If we had previously added a class to the element, remove it.
            if (oldClass) {
              elem.removeClass(oldClass);
            }

            // If necessary, add a new class. Make sure we keep track of it so
            // it can be removed in the future.
            if (newClass) {
              elem.addClass(newClass);
              oldClass = newClass;
            } else {
              oldClass = null;
            }
          }
        };

        if (path !== '' && path !== 'this') {
          view.registerObserver(pathRoot, path, observer);
        }

        // We've already setup the observer; now we just need to figure out the
        // correct behavior right now on the first pass through.
        value = classStringForPath(context, parsedPath, options);

        if (value) {
          ret.push(value);

          // Make sure we save the current value so that it can be removed if the
          // observer fires.
          oldClass = value;
        }
      });

      return ret;
    }
function bindClasses ( context , classBindings , view , bindAttrId , options ) { var ret = [ ] ; var newClass , value , elem ; // Helper method to retrieve the property from the context and // determine which class string to return, based on whether it is // a Boolean or not. var classStringForPath = function ( root , parsedPath , options ) { var val ; var path = parsedPath . path ; if ( path === 'this' ) { val = root ; } else if ( path === '' ) { val = true ; } else { val = handlebarsGet ( root , path , options ) ; } return View . _classStringForValue ( path , val , parsedPath . className , parsedPath . falsyClassName ) ; } ; // For each property passed, loop through and setup // an observer. forEach . call ( classBindings . split ( ' ' ) , function ( binding ) { // Variable in which the old class value is saved. The observer function // closes over this variable, so it knows which string to remove when // the property changes. var oldClass ; var observer ; var parsedPath = View . _parsePropertyPath ( binding ) ; var path = parsedPath . path ; var pathRoot = context ; var normalized ; if ( path !== '' && path !== 'this' ) { normalized = normalizePath ( context , path , options . data ) ; pathRoot = normalized . root ; path = normalized . path ; } // Set up an observer on the context. If the property changes, toggle the // class name. observer = function ( ) { // Get the current value of the property newClass = classStringForPath ( context , parsedPath , options ) ; elem = bindAttrId ? view . $ ( "[data-bindattr-" + bindAttrId + "='" + bindAttrId + "']" ) : view . $ ( ) ; // If we can't find the element anymore, a parent template has been // re-rendered and we've been nuked. Remove the observer. if ( ! elem || elem . length === 0 ) { removeObserver ( pathRoot , path , observer ) ; } else { // If we had previously added a class to the element, remove it. if ( oldClass ) { elem . removeClass ( oldClass ) ; } // If necessary, add a new class. Make sure we keep track of it so // it can be removed in the future. if ( newClass ) { elem . addClass ( newClass ) ; oldClass = newClass ; } else { oldClass = null ; } } } ; if ( path !== '' && path !== 'this' ) { view . registerObserver ( pathRoot , path , observer ) ; } // We've already setup the observer; now we just need to figure out the // correct behavior right now on the first pass through. value = classStringForPath ( context , parsedPath , options ) ; if ( value ) { ret . push ( value ) ; // Make sure we save the current value so that it can be removed if the // observer fires. oldClass = value ; } } ) ; return ret ; }
Helper that, given a space-separated string of property paths and a context,
returns an array of class names. Calling this method also has the side
effect of setting up observers at those property paths, such that if they
change, the correct class name will be reapplied to the DOM element.

For example, if you pass the string "fooBar", it will first look up the
"fooBar" value of the context. If that value is true, it will add the
"foo-bar" class to the current element (i.e., the dasherized form of
"fooBar"). If the value is a string, it will add that string as the class.
Otherwise, it will not add any new class name.

@private
@method bindClasses
@for Ember.Handlebars
@param {Ember.Object} context The context from which to lookup properties
@param {String} classBindings A string, space-separated, of class bindings
to use
@param {View} view The view in which observers should look for the
element to update
@param {Srting} bindAttrId Optional bindAttr id used to lookup elements
@return {Array} An array of class names to add
Helper that given a space - separated string of property paths and a context returns an array of class names . Calling this method also has the side effect of setting up observers at those property paths such that if they change the correct class name will be reapplied to the DOM element .