;(function($$){ 'use strict';
  
  // Collection functions that toggle a boolean value
  ////////////////////////////////////////////////////////////////////////////////////////////////////
  
  
  function defineSwitchFunction(params){
    return function(){
      var args = arguments;
      
      // e.g. cy.nodes().select( data, handler )
      if( args.length === 2 ){
        var data = args[0];
        var handler = args[1];
        this.bind( params.event, data, handler );
      } 
      
      // e.g. cy.nodes().select( handler )
      else if( args.length === 1 ){
        var handler = args[0];
        this.bind( params.event, handler );
      }
      
      // e.g. cy.nodes().select()
      else if( args.length === 0 ){
        for( var i = 0; i < this.length; i++ ){
          var ele = this[i];
          var able = !params.ableField || ele._private[params.ableField];

          if( params.overrideAble ){
            var overrideAble = params.overrideAble(ele);

            if( overrideAble !== undefined ){
              able = overrideAble;

              if( !overrideAble ){ return this; } // to save cycles assume not able for all on override
            }
          }

          if( able ){
            ele._private[params.field] = params.value;
          }
        }
        this.updateStyle(); // change of state => possible change of style
        this.trigger( params.event );
      }

      return this;
    };
  }
  
  function defineSwitchSet( params ){
    $$.elesfn[ params.field ] = function(){
      var ele = this[0];

      if( ele ){
        if( params.overrideField ){
          var val = params.overrideField(ele);

          if( val !== undefined ){
            return val;
          }
        }

        return ele._private[ params.field ];
      }
    };
    
    $$.elesfn[ params.on ] = defineSwitchFunction({
      event: params.on,
      field: params.field,
      ableField: params.ableField,
      overrideAble: params.overrideAble,
      value: true
    });

    $$.elesfn[ params.off ] = defineSwitchFunction({
      event: params.off,
      field: params.field,
      ableField: params.ableField,
      overrideAble: params.overrideAble,
      value: false
    });
  }
  
  defineSwitchSet({
    field: 'locked',
    overrideField: function(ele){
      return ele.cy().autolock() ? true : undefined;
    },
    on: 'lock',
    off: 'unlock'
  });
  
  defineSwitchSet({
    field: 'grabbable',
    overrideField: function(ele){
      return ele.cy().autoungrabify() ? false : undefined;
    },
    on: 'grabify',
    off: 'ungrabify'
  });
  
  defineSwitchSet({
    field: 'selected',
    ableField: 'selectable',
    overrideAble: function(ele){
      return ele.cy().autounselectify() ? false : undefined;
    },
    on: 'select',
    off: 'unselect'
  });
  
  defineSwitchSet({
    field: 'selectable',
    overrideField: function(ele){
      return ele.cy().autounselectify() ? false : undefined;
    },
    on: 'selectify',
    off: 'unselectify'
  });

  $$.elesfn.deselect = $$.elesfn.unselect;
  
  $$.elesfn.grabbed = function(){
    var ele = this[0];
    if( ele ){
      return ele._private.grabbed;
    }
  };

  defineSwitchSet({
    field: 'active',
    on: 'activate',
    off: 'unactivate'
  });

  $$.elesfn.inactive = function(){
    var ele = this[0];
    if( ele ){
      return !ele._private.active;
    }
  };
  
})( cytoscape );

@@ -281,16 +281,44 @@
 uments;%0A
+      var changedEles = %5B%5D;%0A
       %0A 
@@ -910,16 +910,84 @@
 eField%5D;
+%0A          var changed = ele._private%5Bparams.field%5D != params.value;
 %0A%0A      
@@ -1365,16 +1365,85 @@
 .value;%0A
+%0A            if( changed )%7B%0A              changedEles.push( ele );%0A  
         
@@ -1438,32 +1438,34 @@
 ;%0A            %7D%0A
+  
         %7D%0A      
@@ -1466,20 +1466,105 @@
         
-this
+%7D%0A%0A        var changedColl = $$.Collection( this.cy(), changedEles );%0A        changedColl
 .updateS
@@ -1626,20 +1626,27 @@
         
-this
+changedColl
 .trigger

Switch functions should be scoped on changed eles for style and event updates #832