Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
<head>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
  <script src="http://canjs.com/release/2.2.6/can.jquery.js"></script>
  <script src="http://canjs.com/release/2.2.6/can.map.define.js"></script>
  <script src="http://canjs.com/release/2.2.6/can.stache.js"></script>
  
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
  <div id="test"></div>
  <script id="template" type="text/stache">
    {{#items}}
      <p>Previous: {{_prevItem.name}}</p>
      <p>Current: {{name}}</p>
    {{/items}}
  </script>
</body>
</html>
 
//Gets the define properties, extends them and returns result
var DefineExtend = function () {
    var defines = [];
    can.each(arguments, function (item) {
      //if passing an object with define at the top
        if (item.define) {
            defines.push(item.define);
            return;
        }
      // if passing something like a can.Map constructor
        if (item.prototype && item.prototype.define) {
            defines.push(item.prototype.define);
        }
    });
    return {define: can.extend.apply(can, defines)};
};
// 
var PenultimateList = can.List.extend({
  init: function () {
    var self = this;
    this.each(function (item) {
      // Can't do this because JSON.stringify don't like it.
      item.attr('_parent', self);
      // This works but feels hacky...
      item._parent = function () {
        return self;
      };
    });
    
    // Still looking into why this causes issues with updating the list
    this.bind('length', function (opts, child) {
        child._parent = function () {
            return self;
        };
    });
  }
});
var PenultimateMap = can.Map.extend({
  define: {
    _parent: {
        value: function () {
            return can.noop;
        },
        serialize: false
    },
    _prevItem: {
      get: function () {
            var items = this._parent();
            var index = items ? items.indexOf(this) - 1: -1;
            if ( index > -1) {
              return items[index];
            }
            return {};
      },
      serialize: false
    }
  }
});
// I thought that doing this:
//var ExtendedMap = PenultimateMap.extend({define:{}});
// would extend one define into the other, but it actually compeltely overwrites the define object
// DefineExtend properly extends the two.
var ExtendedMap = can.Map.extend(DefineExtend(PenultimateMap, {
  define: {
    name: {
      type:'string'
    }
  }
}));
PenultimateList.Map = ExtendedMap;
var DemoMap = can.Map.extend({
  define: {
    items: {
      value: [{name:"juan"},{name:"cheese"}],
      Type: PenultimateList
    }
  }
});
var template = can.view.render('template');
$('#test').html(template(new DemoMap({})));
Output

You can jump to the latest bin by adding /latest to your URL

Dismiss x
public
Bin info
Guamasopro
0viewers