import “selection”;

d3_selectionPrototype.property = function(name, value) {

if (arguments.length < 2) {

  // For property(string), return the property value for the first node.
  if (typeof name === "string") return this.node()[name];

  // For property(object), the object specifies the names and values of the
  // properties to set or remove. The values may be functions that are
  // evaluated for each element.
  for (value in name) this.each(d3_selection_property(value, name[value]));
  return this;
}

// Otherwise, both a name and a value are specified, and are handled as below.
return this.each(d3_selection_property(name, value));

};

function d3_selection_property(name, value) {

// For property(name, null), remove the property with the specified name.
function propertyNull() {
  delete this[name];
}

// For property(name, string), set the property with the specified name.
function propertyConstant() {
  this[name] = value;
}

// For property(name, function), evaluate the function for each element, and
// set or remove the property as appropriate.
function propertyFunction() {
  var x = value.apply(this, arguments);
  if (x == null) delete this[name];
  else this[name] = x;
}

return value == null
    ? propertyNull : (typeof value === "function"
    ? propertyFunction : propertyConstant);

}