<commit_before>vars.default_params["productspace"] = function(scope) {

  var params = {};

  params.x_scale = [{
    func: d3.scale.linear()
            .range([0, vars.width-vars.margin.left-vars.margin.right])
            .domain(d3.extent(vars.new_data, function(d) { return d[vars.var_x]; })).nice()
  }];

  params.y_scale = [{
    func: d3.scale.linear()
            .range([vars.height-vars.margin.top-vars.margin.bottom, vars.margin.top])
            .domain(d3.extent(vars.new_data, function(d) { return d[vars.var_y]; })).nice(),
  }];

  params.r_scale = d3.scale.linear()
              .range([10, 30])
              .domain(d3.extent(vars.new_data, function(d) { return d[vars.var_r]; }));

  params.items = [{
    marks: [{
      type: "circle",
      r_scale: d3.scale.linear()
                  .range([10, 30])
                  .domain(d3.extent(vars.new_data, function(d) { return d[vars.var_r]; })),
      fill: function(d) { return vars.color(vars.accessor_items(d)[vars.var_color]); }
    }, {
      type: "text",
      rotate: "30",
      translate: null
    }]
  }];

  params.connect = [{
    attr: "links",
    type: "items",
    marks: [{
      type: "line",
      rotate: "0",
      func: null,
    }]
  }];

  params.x_axis_show = false;
  params.x_grid_show = false;

  params.y_axis_show = false;
  params.y_grid_show = false;

  vars.evt.register("highlightOn", function(d) {

    // Make sure the highlighted node is above other nodes
    vars.svg.selectAll('.mark__group').sort(function(a, b) { return a.__highlighted ;})

    var adjacent_links = utils.find_adjacent_links(d, vars.links);

    adjacent_links.forEach(function(e) {

        // Redraw adjacent links
        e.__highlighted__adjacent = true;
        e.__redraw = true;

       vars.new_data.forEach(function(f, k) {

         if(f[vars.var_id] === e.target[vars.var_id] || f[vars.var_id] === e.source[vars.var_id]) {
          // Redraw adjacent nodes
           f.__highlighted__adjacent = true;
           f.__redraw = true;
         }

       });

    });

  });

  vars.evt.register("highlightOut", function(d) {

    vars.new_data.forEach(function(f, k) {
      if(f.__highlighted__adjacent) {
        f.__highlighted__adjacent = false;
        f.__redraw = true;
      }
    });

    vars.links.forEach(function(f, k) {
      if(f.__highlighted__adjacent) {
        f.__highlighted__adjacent = false;
        f.__redraw = true;
      }
    });

    d3.select(vars.container).selectAll(".connect__line")
      .classed("highlighted", function(d, i) { return false; })
      .classed("highlighted__adjacent", function(d, i) { return false; })

    d3.select(vars.container).selectAll("circle")
      .classed("highlighted", function(d, i) { return false; })
      .classed("highlighted__adjacent", function(d, i) { return false; })

//    var adjacent_links = utils.find_adjacent_links(d, vars.links);
/*
    adjacent_links.forEach(function(e) {

      e.__highlighted__adjacent = false;
      e.__redraw = true;

      vars.new_data.forEach(function(f, k) {

         if(f[vars.var_id] === e.target[vars.var_id]) {

           f.__highlighted__adjacent = false;
           f.__redraw = true;

         }

       });

    });
*/
  });

  vars.evt.register("selection", function(d) {
    console.log("HERE", d)
    // Make sure the highlighted node is above other nodes
    // vars.svg.selectAll('.mark__group').sort(function(a, b) { return a.__highlighted ;})

    vars.new_data.forEach(function(f, k) {
      if(f.__selected) {
        f.__selected = false;
        f.__redraw = true;
      }

      if(f.__selected__adjacent) {
        f.__selected__adjacent = false;
        f.__redraw = true;
      }

    });

    vars.links.forEach(function(f, k) {
      if(f.__selected) {
        f.__selected = false;
        f.__redraw = true;
      }

      if(f.__selected__adjacent) {
        f.__selected__adjacent = false;
        f.__redraw = true;
      }

    });

    d.__selected = true;
    d.__redraw = true;

    var adjacent_links = utils.find_adjacent_links(d, vars.links);

    adjacent_links.forEach(function(e) {

      // Update links
      e.__selected = true;
      e.__selected__adjacent = true;
      e.__redraw = true;

      vars.new_data.forEach(function(f, k) {

        if(f[vars.var_id] === e.target[vars.var_id] || f[vars.var_id] === e.source[vars.var_id]) {

          // Update nodes
          f.__selected = true;
          f.__selected__adjacent = true;
          f.__redraw = true;
        }

      });

    });

    d3.select(vars.container).selectAll(".connect__line")
      .classed("selected", function(d, i) { return d.__selected; })
      .classed("selected__adjacent", function(d, i) { return d.__selected__adjacent; })

    d3.select(vars.container).selectAll("circle")
      .classed("selected", function(d, i) { return d.__selected; })
      .classed("selected__adjacent", function(d, i) { return d.__selected__adjacent; })

  });

  return params;

};
<commit_msg>Cleanup<commit_after>vars.default_params["productspace"] = function(scope) {

  var params = {};

  params.x_scale = [{
    func: d3.scale.linear()
            .range([0, vars.width-vars.margin.left-vars.margin.right])
            .domain(d3.extent(vars.new_data, function(d) { return d[vars.var_x]; })).nice()
  }];

  params.y_scale = [{
    func: d3.scale.linear()
            .range([vars.height-vars.margin.top-vars.margin.bottom, vars.margin.top])
            .domain(d3.extent(vars.new_data, function(d) { return d[vars.var_y]; })).nice(),
  }];

  params.r_scale = d3.scale.linear()
              .range([10, 30])
              .domain(d3.extent(vars.new_data, function(d) { return d[vars.var_r]; }));

  params.items = [{
    marks: [{
      type: "circle",
      r_scale: d3.scale.linear()
                  .range([10, 30])
                  .domain(d3.extent(vars.new_data, function(d) { return d[vars.var_r]; })),
      fill: function(d) { return vars.color(vars.accessor_items(d)[vars.var_color]); }
    }, {
      type: "text",
      rotate: "30",
      translate: null
    }]
  }];

  params.connect = [{
    attr: "links",
    type: "items",
    marks: [{
      type: "line",
      rotate: "0",
      func: null,
    }]
  }];

  params.x_axis_show = false;
  params.x_grid_show = false;

  params.y_axis_show = false;
  params.y_grid_show = false;

  vars.evt.register("highlightOn", function(d) {

    // Make sure the highlighted node is above other nodes
    vars.svg.selectAll('.mark__group').sort(function(a, b) { return a.__highlighted ;})

    var adjacent_links = utils.find_adjacent_links(d, vars.links);

    adjacent_links.forEach(function(e) {

        // Redraw adjacent links
        e.__highlighted__adjacent = true;
        e.__redraw = true;

       vars.new_data.forEach(function(f, k) {

         if(f[vars.var_id] === e.target[vars.var_id] || f[vars.var_id] === e.source[vars.var_id]) {
          // Redraw adjacent nodes
           f.__highlighted__adjacent = true;
           f.__redraw = true;
         }

       });

    });

  });

  vars.evt.register("highlightOut", function(d) {

    vars.new_data.forEach(function(f, k) {
      if(f.__highlighted__adjacent) {
        f.__highlighted__adjacent = false;
        f.__redraw = true;
      }
    });

    vars.links.forEach(function(f, k) {
      if(f.__highlighted__adjacent) {
        f.__highlighted__adjacent = false;
        f.__redraw = true;
      }
    });

    d3.select(vars.container).selectAll(".connect__line")
      .classed("highlighted", function(d, i) { return false; })
      .classed("highlighted__adjacent", function(d, i) { return false; })

    d3.select(vars.container).selectAll("circle")
      .classed("highlighted", function(d, i) { return false; })
      .classed("highlighted__adjacent", function(d, i) { return false; })

//    var adjacent_links = utils.find_adjacent_links(d, vars.links);
/*
    adjacent_links.forEach(function(e) {

      e.__highlighted__adjacent = false;
      e.__redraw = true;

      vars.new_data.forEach(function(f, k) {

         if(f[vars.var_id] === e.target[vars.var_id]) {

           f.__highlighted__adjacent = false;
           f.__redraw = true;

         }

       });

    });
*/
  });

  vars.evt.register("selection", function(d) {

    // Make sure the highlighted node is above other nodes
    // vars.svg.selectAll('.mark__group').sort(function(a, b) { return a.__highlighted ;})

    vars.new_data.forEach(function(f, k) {
      if(f.__selected) {
        f.__selected = false;
        f.__redraw = true;
      }

      if(f.__selected__adjacent) {
        f.__selected__adjacent = false;
        f.__redraw = true;
      }

    });

    vars.links.forEach(function(f, k) {
      if(f.__selected) {
        f.__selected = false;
        f.__redraw = true;
      }

      if(f.__selected__adjacent) {
        f.__selected__adjacent = false;
        f.__redraw = true;
      }

    });

    d.__selected = true;
    d.__redraw = true;

    var adjacent_links = utils.find_adjacent_links(d, vars.links);

    adjacent_links.forEach(function(e) {

      // Update links
      e.__selected = true;
      e.__selected__adjacent = true;
      e.__redraw = true;

      vars.new_data.forEach(function(f, k) {

        if(f[vars.var_id] === e.target[vars.var_id] || f[vars.var_id] === e.source[vars.var_id]) {

          // Update nodes
          f.__selected = true;
          f.__selected__adjacent = true;
          f.__redraw = true;
        }

      });

    });

    d3.select(vars.container).selectAll(".connect__line")
      .classed("selected", function(d, i) { return d.__selected; })
      .classed("selected__adjacent", function(d, i) { return d.__selected__adjacent; })

    d3.select(vars.container).selectAll("circle")
      .classed("selected", function(d, i) { return d.__selected; })
      .classed("selected__adjacent", function(d, i) { return d.__selected__adjacent; })

  });

  return params;

};
<|endoftext|>


<commit_before>describe("app.views.StreamFaces", function(){
  beforeEach(function(){
    var rebeccaBlack = factory.author({name : "Rebecca Black", id : 1492})
    this.post1 = factory.post({author : rebeccaBlack})
    this.post2 = factory.post({author : factory.author({name : "John Stamos", id : 1987})})
    this.post3 = factory.post({author : factory.author({name : "Michelle Tanner", id : 1986})})
    this.post4 = factory.post({author : factory.author({name : "Barack Obama", id : 2000})})
    this.post5 = factory.post({author : factory.author({name : "Obie-won Kenobie", id : 2020})})
    this.post6 = factory.post({author : rebeccaBlack})
    this.post7 = factory.post({author : rebeccaBlack})

    app.stream = new app.models.Stream()
    app.stream.add([this.post1, this.post2, this.post3, this.post4, this.post5, this.post6, this.post7]);
    this.posts = app.stream.items

    this.view = new app.views.StreamFaces({collection : this.posts})
  })

  it("should take them unique", function(){
    this.view.render()
    expect(this.view.people.length).toBe(5)
  })

  it("findsPeople when the collection changes", function(){
    this.posts.add(factory.post({author : factory.author({name : "Harriet Tubman"})}))
    expect(this.view.people.length).toBe(6)
  })

  describe(".render", function(){
    beforeEach(function(){
      this.view.render()
    })

    it("appends the people's avatars", function(){
      expect(this.view.$("img").length).toBe(5)
    })

    it("links to the people", function(){
      expect(this.view.$("a").length).toBe(5)
    })

    it("rerenders when people are added, but caps to 15 people", function(){
      var posts = _.map(_.range(20), function(){ return factory.post()})
      this.posts.reset(posts) //add 20 posts silently to the collection
      this.posts.add(factory.post()) //trigger an update
      expect(this.view.$("img").length).toBe(15)
    })
  })
})
<commit_msg>Someone isn't a StarWars fan.<commit_after>describe("app.views.StreamFaces", function(){
  beforeEach(function(){
    var rebeccaBlack = factory.author({name : "Rebecca Black", id : 1492})
    this.post1 = factory.post({author : rebeccaBlack})
    this.post2 = factory.post({author : factory.author({name : "John Stamos", id : 1987})})
    this.post3 = factory.post({author : factory.author({name : "Michelle Tanner", id : 1986})})
    this.post4 = factory.post({author : factory.author({name : "Barack Obama", id : 2000})})
    this.post5 = factory.post({author : factory.author({name : "Obi-wan Kenobi", id : 2020})})
    this.post6 = factory.post({author : rebeccaBlack})
    this.post7 = factory.post({author : rebeccaBlack})

    app.stream = new app.models.Stream()
    app.stream.add([this.post1, this.post2, this.post3, this.post4, this.post5, this.post6, this.post7]);
    this.posts = app.stream.items

    this.view = new app.views.StreamFaces({collection : this.posts})
  })

  it("should take them unique", function(){
    this.view.render()
    expect(this.view.people.length).toBe(5)
  })

  it("findsPeople when the collection changes", function(){
    this.posts.add(factory.post({author : factory.author({name : "Harriet Tubman"})}))
    expect(this.view.people.length).toBe(6)
  })

  describe(".render", function(){
    beforeEach(function(){
      this.view.render()
    })

    it("appends the people's avatars", function(){
      expect(this.view.$("img").length).toBe(5)
    })

    it("links to the people", function(){
      expect(this.view.$("a").length).toBe(5)
    })

    it("rerenders when people are added, but caps to 15 people", function(){
      var posts = _.map(_.range(20), function(){ return factory.post()})
      this.posts.reset(posts) //add 20 posts silently to the collection
      this.posts.add(factory.post()) //trigger an update
      expect(this.view.$("img").length).toBe(15)
    })
  })
})
<|endoftext|>


<commit_before>// Copyright (c) 2014, DLH
// See LICENSE.txt for license info.

"use strict";

if (typeof DEBUG === "undefined")
  window.DEBUG = true;

var Vue = require("vue");
var _ = require("lodash");

var animate = require("./animate")
var gid = require("./gid");

var INITIAL_MESSAGE = "Fetching validation";
var INITIAL_DESCRIPTION = "fa fa-refresh fa-spin validating"

function cssDescription(description) {
    if (description === "invalid") {
        return "fa fa-exclamation-triangle invalid";
    }
    else if (description === "valid-suggested-name") {
        return "fa fa-exchange";
    }
    else if (description === "valid-with-warning") {
        return "fa fa-meh-o warning";
    }
    else if (description === "valid") {
        return "fa fa-check valid";
    }
}

function focusOnFirstAttributedElement(rootElement) {
    var e = rootElement.querySelector("[data-focus-after-scroll]:first-child");
    if (e)
        e.focus();
}

var app = new Vue({
    el: "#app-view",
    // lazy: true,
    data: {
        currentKey: 0,
        players: [],
    },
    computed: {
        numberErrors: function() {
            return this.players.reduce(function(sum, p) {
                return sum + (p.valid ? 0 : 1);
            }, 0);
        }
    },
    ready: function() {
        focusOnFirstAttributedElement(this.$el);
        this.$on("add-names", this.addNames);
        this.$on("validate-player", this.validatePlayer);
        this.$on("remove-players", this.removePlayers);
        this.$on("move-to-anchor", this.moveToAnchor);
    },
    methods: {
        addNames: function(userLevel, names) {
            var xs = names.map(function(name, index) {
                return {
                    name: name,
                    userLevel: userLevel,
                    valid: false,
                    message: INITIAL_MESSAGE,
                    description: INITIAL_DESCRIPTION,
                    key: this.currentKey++
                };
            }, this);
            this.players = this.players.concat(xs);
            xs.forEach(function(entry) { this.validatePlayer(entry); }, this);
        },
        validatePlayer: function(entry) {
            entry.message = INITIAL_MESSAGE;
            entry.description = INITIAL_DESCRIPTION;
            gid.validateName(entry.name, function(name, newName, valid, message, description) {
                entry.name = newName;
                entry.valid = valid;
                entry.message = message;
                entry.description = cssDescription(description);
                this.removeDuplicateNames(newName);
            }.bind(this));
        },
        removePlayers: function(players) {
            var keys = _.pluck(players, "key");
            Vue.nextTick(function() {
                this.players = this.players.filter(function(p) { return !_.contains(keys, p.key) });
            }.bind(this));
        },
        moveToAnchor: function(anchor) {
            // document.getElementById(anchor).scrollIntoView();
            var el = document.getElementById(anchor);
            animate.scrollTo(el.offsetTop, 500, function() {
                focusOnFirstAttributedElement(el)
            });
        },
        removeDuplicateNames: function(name) {
            var dups = _.filter(this.players, {name: name});
            if (dups.length > 1) {
                // Keep most elevated user level
                var sortedDups = _.sortBy(dups, "userLevel");
                var toRemove = _.rest(sortedDups);
                this.removePlayers(toRemove);
            }
        }
    },
    components: {
        "extract": require("./component/extract"),
        "navigation": require("./component/navigation"),
        "publish": require("./component/publish"),
        "user-level": require("./component/user-level"),
        "verify": require("./component/verify")
    }
});

if (DEBUG) {
    window.app = app;
    window._ = _;
}
<commit_msg>Simplify query selector.<commit_after>// Copyright (c) 2014, DLH
// See LICENSE.txt for license info.

"use strict";

if (typeof DEBUG === "undefined")
  window.DEBUG = true;

var Vue = require("vue");
var _ = require("lodash");

var animate = require("./animate")
var gid = require("./gid");

var INITIAL_MESSAGE = "Fetching validation";
var INITIAL_DESCRIPTION = "fa fa-refresh fa-spin validating"

function cssDescription(description) {
    if (description === "invalid") {
        return "fa fa-exclamation-triangle invalid";
    }
    else if (description === "valid-suggested-name") {
        return "fa fa-exchange";
    }
    else if (description === "valid-with-warning") {
        return "fa fa-meh-o warning";
    }
    else if (description === "valid") {
        return "fa fa-check valid";
    }
}

function focusOnFirstAttributedElement(rootElement) {
    var e = rootElement.querySelector("[data-focus-after-scroll]");
    if (e)
        e.focus();
}

var app = new Vue({
    el: "#app-view",
    // lazy: true,
    data: {
        currentKey: 0,
        players: [],
    },
    computed: {
        numberErrors: function() {
            return this.players.reduce(function(sum, p) {
                return sum + (p.valid ? 0 : 1);
            }, 0);
        }
    },
    ready: function() {
        focusOnFirstAttributedElement(this.$el);
        this.$on("add-names", this.addNames);
        this.$on("validate-player", this.validatePlayer);
        this.$on("remove-players", this.removePlayers);
        this.$on("move-to-anchor", this.moveToAnchor);
    },
    methods: {
        addNames: function(userLevel, names) {
            var xs = names.map(function(name, index) {
                return {
                    name: name,
                    userLevel: userLevel,
                    valid: false,
                    message: INITIAL_MESSAGE,
                    description: INITIAL_DESCRIPTION,
                    key: this.currentKey++
                };
            }, this);
            this.players = this.players.concat(xs);
            xs.forEach(function(entry) { this.validatePlayer(entry); }, this);
        },
        validatePlayer: function(entry) {
            entry.message = INITIAL_MESSAGE;
            entry.description = INITIAL_DESCRIPTION;
            gid.validateName(entry.name, function(name, newName, valid, message, description) {
                entry.name = newName;
                entry.valid = valid;
                entry.message = message;
                entry.description = cssDescription(description);
                this.removeDuplicateNames(newName);
            }.bind(this));
        },
        removePlayers: function(players) {
            var keys = _.pluck(players, "key");
            Vue.nextTick(function() {
                this.players = this.players.filter(function(p) { return !_.contains(keys, p.key) });
            }.bind(this));
        },
        moveToAnchor: function(anchor) {
            // document.getElementById(anchor).scrollIntoView();
            var el = document.getElementById(anchor);
            animate.scrollTo(el.offsetTop, 500, function() {
                focusOnFirstAttributedElement(el)
            });
        },
        removeDuplicateNames: function(name) {
            var dups = _.filter(this.players, {name: name});
            if (dups.length > 1) {
                // Keep most elevated user level
                var sortedDups = _.sortBy(dups, "userLevel");
                var toRemove = _.rest(sortedDups);
                this.removePlayers(toRemove);
            }
        }
    },
    components: {
        "extract": require("./component/extract"),
        "navigation": require("./component/navigation"),
        "publish": require("./component/publish"),
        "user-level": require("./component/user-level"),
        "verify": require("./component/verify")
    }
});

if (DEBUG) {
    window.app = app;
    window._ = _;
}
<|endoftext|>


<commit_before>var nqp = require('nqp-runtime');
var CodeRef = require('nqp-runtime/code-ref');
var NQPArray = require('nqp-runtime/array');
var op = {};

var Scalar, True, False, Int, Num, Str, Code;

op.p6settypes = function(types) {
  Scalar = types.content.get('Scalar');
  True = types.content.get('True');
  False = types.content.get('False');
  Int = types.content.get('Int');
  Num = types.content.get('Num');
  Str = types.content.get('Str');
  Code = types.content.get('Code');
  Mu = types.content.get('Mu');
  return types;
};

op.p6bool = function(value) {
  return value ? True : False;
};

op.p6definite = function(obj) {
  return obj.typeObject_ ? False : True;
};

op.p6typecheckrv = function(rv, routine, bypassType) {
  // STUB
  return rv;
};

op.p6decontrv = function(rountine, cont) {
  // STUB
  return cont;
};

op.p6box_i = function(int) {
  var repr = Int._STable.REPR;
  var boxed = repr.allocate(Int._STable);
  boxed.$$setInt(int);
  return boxed;
};

op.p6box_n = function(num) {
  var repr = Num._STable.REPR;
  var boxed = repr.allocate(Num._STable);
  boxed.$$setNum(num);
  return boxed;
};

op.p6box_s = function(str) {
  var repr = Str._STable.REPR;
  var boxed = repr.allocate(Str._STable);
  boxed.$$setStr(str);
  return boxed;
};

op.p6captureouters2 = function(ctx, capList, target) {
  var cf = (target.outerCtx || closure.forcedOuter);

  if (cf === null) {
    return capList;
  }

  var elems = capList.$$elems();

  for (var i = 0; i < elems; i++) {
      var codeObj = capList.$$atpos(i);

      var closure = codeObj.$$getattr(Code, "$!do");

      var ctxToDiddle = (closure.outerCtx || closure.forcedOuter);
      ctxToDiddle.$$outer = cf;
  }

  return capList;
};

op.p6captureouters = function(ctx, capList) {

  var elems = capList.$$elems();

  for (var i = 0; i < elems; i++) {
      var codeObj = capList.$$atpos(i);
      var closure = codeObj.$$getattr(Code, "$!do");
      var ctxToDiddle = (closure.outerCtx || closure.forcedOuter);
      ctxToDiddle.$$outer = ctx;
  }

  return capList;
};

op.p6capturelex = function(ctx, codeObj) {

  var closure = codeObj.$$getattr(Code, "$!do");
  var wantedStaticInfo = closure.staticCode.outerCodeRef;

  if (ctx.codeRef().staticCode === wantedStaticInfo) {
    closure.forcedOuter = ctx;
  } else if (ctx.$$outer.codeRef().staticCode === wantedStaticInfo) {
    closure.forcedOuter = ctx.$$outer;
  }

  return codeObj;
};

op.p6var = function(cont) {
  if (cont != null && cont.$$iscont && cont.$$iscont()) {
    var wrapper = Scalar._STable.REPR.allocate(Scalar._STable);
    wrapper.$$bindattr(Scalar, '$!value', cont);
    return wrapper;
  } else {
    return cont;
  }
}

op.p6bindassert = function(ctx, value, type) {
  if (type !== Mu) {
    var decont = nqp.op.decont(ctx, value);
    if (nqp.op.istype(decont, type) == 0) {
      ctx.die("Type check failed in binding");
    }
  }
  return value;
};

op.p6store = function(ctx, cont, value) {
  if (cont) {
    cont.$$assign(ctx, nqp.op.decont(ctx, value));
  } else {
    if (!cont.STORE) {
      // TODO throw typed exception X::Assignment::RO
      ctx.die("Cannot assign to a non-container");
    } else {
      cont.STORE(ctx, null, cont, value);
    }
  }
  return cont;
};

op.p6argvmarray = function(ctx, args) {
  var array = [];
  console.log("in p6argvmarray");
  for (var i=2; i < args.length; i++) {
    array[i-2] = nqp.op.hllizefor(ctx, args[i], 'perl6');
  }
  return new NQPArray(array);
};

var containerSpecs = require('nqp-runtime/container-specs.js');

function RakudoScalar(STable) {
  this.STable = STable;
}

RakudoScalar.prototype.configure = function(conf) {
  this.setupSTable();
};

RakudoScalar.prototype.setupSTable = function() {
  this.STable.addInternalMethod('$$assignunchecked', function(ctx, value) {
    console.log('storing into rakudo_scalar unchecked');
    return this.$$bindattr(Scalar, '$!value', value);
  });

  this.STable.addInternalMethod('$$assign', function(ctx, value) {
    /* TODO - checking and WHENCE */
    return this.$$bindattr(Scalar, '$!value', value);
  });

  this.STable.addInternalMethod('$$decont', function(ctx) {
    return this.$$getattr(Scalar, '$!value');
  });

  this.STable.addInternalMethod('$$getInt', function(ctx) {
    return this.$$decont().$$getInt();
  });

  this.STable.addInternalMethod('$$getNum', function(ctx) {
    return this.$$decont().$$getNum();
  });

  this.STable.addInternalMethod('$$getStr', function(ctx) {
    return this.$$decont().$$getStr();
  });

  this.STable.addInternalMethod('$$iscont', function() {
    return 1;
  });
};

RakudoScalar.prototype.serialize = function(cursor) {
  console.log('// serializing rakudo_scalar');
};

RakudoScalar.prototype.deserialize = function(cursor) {
  console.log('// deserializing rakudo_scalar');
};

RakudoScalar.prototype.name = 'rakudo_scalar';

containerSpecs.rakudo_scalar = RakudoScalar;

nqp.loadOps({op: op});
module.exports = null;

<commit_msg>[js] Call $$decont directly instead of using the no longer present nqp.op.decont.<commit_after>var nqp = require('nqp-runtime');
var CodeRef = require('nqp-runtime/code-ref');
var NQPArray = require('nqp-runtime/array');
var op = {};

var Scalar, True, False, Int, Num, Str, Code;

op.p6settypes = function(types) {
  Scalar = types.content.get('Scalar');
  True = types.content.get('True');
  False = types.content.get('False');
  Int = types.content.get('Int');
  Num = types.content.get('Num');
  Str = types.content.get('Str');
  Code = types.content.get('Code');
  Mu = types.content.get('Mu');
  return types;
};

op.p6bool = function(value) {
  return value ? True : False;
};

op.p6definite = function(obj) {
  return obj.typeObject_ ? False : True;
};

op.p6typecheckrv = function(rv, routine, bypassType) {
  // STUB
  return rv;
};

op.p6decontrv = function(rountine, cont) {
  // STUB
  return cont;
};

op.p6box_i = function(int) {
  var repr = Int._STable.REPR;
  var boxed = repr.allocate(Int._STable);
  boxed.$$setInt(int);
  return boxed;
};

op.p6box_n = function(num) {
  var repr = Num._STable.REPR;
  var boxed = repr.allocate(Num._STable);
  boxed.$$setNum(num);
  return boxed;
};

op.p6box_s = function(str) {
  var repr = Str._STable.REPR;
  var boxed = repr.allocate(Str._STable);
  boxed.$$setStr(str);
  return boxed;
};

op.p6captureouters2 = function(ctx, capList, target) {
  var cf = (target.outerCtx || closure.forcedOuter);

  if (cf === null) {
    return capList;
  }

  var elems = capList.$$elems();

  for (var i = 0; i < elems; i++) {
      var codeObj = capList.$$atpos(i);

      var closure = codeObj.$$getattr(Code, "$!do");

      var ctxToDiddle = (closure.outerCtx || closure.forcedOuter);
      ctxToDiddle.$$outer = cf;
  }

  return capList;
};

op.p6captureouters = function(ctx, capList) {

  var elems = capList.$$elems();

  for (var i = 0; i < elems; i++) {
      var codeObj = capList.$$atpos(i);
      var closure = codeObj.$$getattr(Code, "$!do");
      var ctxToDiddle = (closure.outerCtx || closure.forcedOuter);
      ctxToDiddle.$$outer = ctx;
  }

  return capList;
};

op.p6capturelex = function(ctx, codeObj) {

  var closure = codeObj.$$getattr(Code, "$!do");
  var wantedStaticInfo = closure.staticCode.outerCodeRef;

  if (ctx.codeRef().staticCode === wantedStaticInfo) {
    closure.forcedOuter = ctx;
  } else if (ctx.$$outer.codeRef().staticCode === wantedStaticInfo) {
    closure.forcedOuter = ctx.$$outer;
  }

  return codeObj;
};

op.p6var = function(cont) {
  if (cont != null && cont.$$iscont && cont.$$iscont()) {
    var wrapper = Scalar._STable.REPR.allocate(Scalar._STable);
    wrapper.$$bindattr(Scalar, '$!value', cont);
    return wrapper;
  } else {
    return cont;
  }
}

op.p6bindassert = function(ctx, value, type) {
  if (type !== Mu) {
    if (nqp.op.istype(value.$$decont(ctx), type) == 0) {
      ctx.die("Type check failed in binding");
    }
  }
  return value;
};

op.p6store = function(ctx, cont, value) {
  if (cont) {
    cont.$$assign(ctx, value.$$decont(ctx));
  } else {
    if (!cont.STORE) {
      // TODO throw typed exception X::Assignment::RO
      ctx.die("Cannot assign to a non-container");
    } else {
      cont.STORE(ctx, null, cont, value);
    }
  }
  return cont;
};

op.p6argvmarray = function(ctx, args) {
  var array = [];
  console.log("in p6argvmarray");
  for (var i=2; i < args.length; i++) {
    array[i-2] = nqp.op.hllizefor(ctx, args[i], 'perl6');
  }
  return new NQPArray(array);
};

var containerSpecs = require('nqp-runtime/container-specs.js');

function RakudoScalar(STable) {
  this.STable = STable;
}

RakudoScalar.prototype.configure = function(conf) {
  this.setupSTable();
};

RakudoScalar.prototype.setupSTable = function() {
  this.STable.addInternalMethod('$$assignunchecked', function(ctx, value) {
    console.log('storing into rakudo_scalar unchecked');
    return this.$$bindattr(Scalar, '$!value', value);
  });

  this.STable.addInternalMethod('$$assign', function(ctx, value) {
    /* TODO - checking and WHENCE */
    return this.$$bindattr(Scalar, '$!value', value);
  });

  this.STable.addInternalMethod('$$decont', function(ctx) {
    return this.$$getattr(Scalar, '$!value');
  });

  this.STable.addInternalMethod('$$getInt', function(ctx) {
    return this.$$decont().$$getInt();
  });

  this.STable.addInternalMethod('$$getNum', function(ctx) {
    return this.$$decont().$$getNum();
  });

  this.STable.addInternalMethod('$$getStr', function(ctx) {
    return this.$$decont().$$getStr();
  });

  this.STable.addInternalMethod('$$iscont', function() {
    return 1;
  });
};

RakudoScalar.prototype.serialize = function(cursor) {
  console.log('// serializing rakudo_scalar');
};

RakudoScalar.prototype.deserialize = function(cursor) {
  console.log('// deserializing rakudo_scalar');
};

RakudoScalar.prototype.name = 'rakudo_scalar';

containerSpecs.rakudo_scalar = RakudoScalar;

nqp.loadOps({op: op});
module.exports = null;

<|endoftext|>


<commit_before>var _ = require('lodash');
var assign = require('object-assign');
var async = require('async');
var FieldType = require('../Type');
var keystone = require('../../../');
var util = require('util');

function getEmptyValue () {
	return {
		public_id: '',
		version: 0,
		signature: '',
		format: '',
		resource_type: '',
		url: '',
		width: 0,
		height: 0,
		secure_url: '',
	};
}

function truthy (value) {
	return value;
}

/**
 * CloudinaryImages FieldType Constructor
 */
function cloudinaryimages (list, path, options) {
	this._underscoreMethods = ['format'];
	this._fixedSize = 'full';
	this._properties = ['select', 'selectPrefix', 'autoCleanup', 'publicID', 'folder', 'filenameAsPublicID'];

	cloudinaryimages.super_.call(this, list, path, options);

	// validate cloudinary config
	if (!keystone.get('cloudinary config')) {
		throw new Error('Invalid Configuration\n\n'
			+ 'CloudinaryImages fields (' + list.key + '.' + this.path + ') require the "cloudinary config" option to be set.\n\n'
			+ 'See http://keystonejs.com/docs/configuration/#services-cloudinary for more information.\n');
	}
}
cloudinaryimages.properName = 'CloudinaryImages';
util.inherits(cloudinaryimages, FieldType);

/**
 * Gets the folder for images in this field
 */
cloudinaryimages.prototype.getFolder = function () {
	var folder = null;
	if (keystone.get('cloudinary folders') || this.options.folder) {
		if (typeof this.options.folder === 'string') {
			folder = this.options.folder;
		} else {
			var folderList = keystone.get('cloudinary prefix') ? [keystone.get('cloudinary prefix')] : [];
			folderList.push(this.list.path);
			folderList.push(this.path);
			folder = folderList.join('/');
		}
	}
	return folder;
};

/**
 * Registers the field on the List's Mongoose Schema.
 */
cloudinaryimages.prototype.addToSchema = function (schema) {

	var cloudinary = require('cloudinary');
	var mongoose = keystone.mongoose;
	var field = this;

	this.paths = {
		// virtuals
		folder: this.path + '.folder',
		// form paths
		upload: this.path + '_upload',
		uploads: this.path + '_uploads',
		action: this.path + '_action',
	};

	var ImageSchema = new mongoose.Schema({
		public_id: String,
		version: Number,
		signature: String,
		format: String,
		resource_type: String,
		url: String,
		width: Number,
		height: Number,
		secure_url: String,
	});

	// The .folder virtual returns the cloudinary folder used to upload/select images
	schema.virtual(field.paths.folder).get(function () {
		return ImageSchema.folder.apply(this);
	});

	var src = function (img, options) {
		if (keystone.get('cloudinary secure')) {
			options = options || {};
			options.secure = true;
		}
		options.format = options.format || img.format;
		return img.public_id ? cloudinary.url(img.public_id, options) : '';
	};

	var addSize = function (options, width, height, other) {
		if (width) options.width = width;
		if (height) options.height = height;
		if (typeof other === 'object') {
			assign(options, other);
		}
		return options;
	};
	ImageSchema.method('folder', function (options) {
		return this.getFolder();
	});
	ImageSchema.method('src', function (options) {
		return src(this, options);
	});
	ImageSchema.method('scale', function (width, height, options) {
		return src(this, addSize({ crop: 'scale' }, width, height, options));
	});
	ImageSchema.method('fill', function (width, height, options) {
		return src(this, addSize({ crop: 'fill', gravity: 'faces' }, width, height, options));
	});
	ImageSchema.method('lfill', function (width, height, options) {
		return src(this, addSize({ crop: 'lfill', gravity: 'faces' }, width, height, options));
	});
	ImageSchema.method('fit', function (width, height, options) {
		return src(this, addSize({ crop: 'fit' }, width, height, options));
	});
	ImageSchema.method('limit', function (width, height, options) {
		return src(this, addSize({ crop: 'limit' }, width, height, options));
	});
	ImageSchema.method('pad', function (width, height, options) {
		return src(this, addSize({ crop: 'pad' }, width, height, options));
	});
	ImageSchema.method('lpad', function (width, height, options) {
		return src(this, addSize({ crop: 'lpad' }, width, height, options));
	});
	ImageSchema.method('crop', function (width, height, options) {
		return src(this, addSize({ crop: 'crop', gravity: 'faces' }, width, height, options));
	});
	ImageSchema.method('thumbnail', function (width, height, options) {
		return src(this, addSize({ crop: 'thumb', gravity: 'faces' }, width, height, options));
	});

	schema.add(this._path.addTo({}, [ImageSchema]));

	this.removeImage = function (item, id, method, callback) {
		var images = item.get(field.path);
		if (typeof id !== 'number') {
			for (var i = 0; i < images.length; i++) {
				if (images[i].public_id === id) {
					id = i;
					break;
				}
			}
		}
		var img = images[id];
		if (!img) return;
		if (method === 'delete') {
			cloudinary.uploader.destroy(img.public_id, function () {});
		}
		images.splice(id, 1);
		if (callback) {
			item.save((typeof callback !== 'function') ? callback : undefined);
		}
	};
	this.underscoreMethod('remove', function (id, callback) {
		field.removeImage(this, id, 'remove', callback);
	});
	this.underscoreMethod('delete', function (id, callback) {
		field.removeImage(this, id, 'delete', callback);
	});
	this.bindUnderscoreMethods();
};

/**
 * Formats the field value
 */
cloudinaryimages.prototype.format = function (item) {
	return _.map(item.get(this.path), function (img) {
		return img.src();
	}).join(', ');
};

/**
 * Gets the field's data from an Item, as used by the React components
 */
cloudinaryimages.prototype.getData = function (item) {
	var value = item.get(this.path);
	return Array.isArray(value) ? value : [];
};

/**
 * Validates that a value for this field has been provided in a data object
 *
 * Deprecated
 */
cloudinaryimages.prototype.inputIsValid = function (data) { // eslint-disable-line no-unused-vars
	// TODO - how should image field input be validated?
	return true;
};

/**
 * Updates the value for this field in the item from a data object
 */
cloudinaryimages.prototype.updateItem = function (item, data, files, callback) {
	if (typeof files === 'function') {
		callback = files;
		files = {};
	} else if (!files) {
		files = {};
	}

	var cloudinary = require('cloudinary');
	var field = this;
	var values = this.getValueFromData(data);

	// TODO: This logic needs to block uploading of files from the data argument,
	// see CloudinaryImage for a reference on how it should be implemented

	// Early exit path: reset value when falsy, or bail if no value was provided
	if (!values) {
		if (values !== undefined) {
			item.set(field.path, []);
		}
		return process.nextTick(callback);
	}

	// When the value exists, but isn't an array, turn it into one (this just
	// means a single field was submitted in the formdata)
	if (!Array.isArray(values)) {
		values = [values];
	}

	// We cache options to avoid recalculating them on each iteration in the map below
	var cachedUploadOptions;
	function getUploadOptions () {
		if (cachedUploadOptions) {
			return cachedUploadOptions;
		}
		var tagPrefix = keystone.get('cloudinary prefix') || '';
		var uploadOptions = {
			tags: [],
			resource_type: 'auto',
		};
		if (tagPrefix.length) {
			uploadOptions.tags.push(tagPrefix);
			tagPrefix += '_';
		}
		uploadOptions.tags.push(tagPrefix + field.list.path + '_' + field.path);
		if (keystone.get('env') !== 'production') {
			uploadOptions.tags.push(tagPrefix + 'dev');
		}
		var folder = field.getFolder();
		if (folder) {
			uploadOptions.folder = folder;
		}
		cachedUploadOptions = uploadOptions;
		return uploadOptions;
	}

	// Preprocess values to deserialise JSON, detect mappings to uploaded files
	// and flatten out arrays
	values = values.map(function (value) {
		// When the value is a string, it may be JSON serialised data.
		if (typeof value === 'string'
			&& value.charAt(0) === '{'
			&& value.charAt(value.length - 1) === '}'
		) {
			try {
				return JSON.parse(value);
			} catch (e) { /* value isn't JSON */ }
		}
		if (typeof value === 'string') {
			// detect file upload (field value must be a reference to a field in the
			// uploaded files object provided by multer)
			if (value.substr(0, 7) === 'upload:') {
				var uploadFieldPath = value.substr(7);
				return files[uploadFieldPath];
			}
			// detect a URL or Base64 Data
			else if (/^(data:[a-z\/]+;base64)|(https?\:\/\/)/.test(value)) {
				return { path: value };
			}
		}
		return value;
	});
	values = _.flatten(values);

	async.map(values, function (value, next) {
		if (typeof value === 'object' && 'public_id' in value) {
			// Setting "autoCleanup" the property "remove:true" removes the file and resets the field
			if (field.options.autoCleanup && value.public_id && value.remove) {
				cloudinary.uploader.destroy(value.public_id, function (result) {
					if (result.error || result === 'not found') {
						return next(result.error || 'not found');
					} else {
						// Remove value
						return next();
					}
				}, {
					resource_type: value.resource_type,
				});
			// Cloudinary Image data provided
			} else if (value.public_id) {
				// Default the object with empty values
				var v = assign(getEmptyValue(), value);
				return next(null, v);
			} else {
				// public_id is falsy, remove the value
				return next();
			}
		} else if (typeof value === 'object' && value.path) {
			// File provided - upload it
			var uploadOptions = getUploadOptions();
			// NOTE: field.options.publicID has been deprecated (tbc)
			if (field.options.filenameAsPublicID && value.originalname && typeof value.originalname === 'string') {
				uploadOptions = assign({}, uploadOptions, {
					public_id: value.originalname.substring(0, value.originalname.lastIndexOf('.')),
				});
			}
			// TODO: implement autoCleanup; should delete existing images before uploading
			cloudinary.uploader.upload(value.path, function (result) {
				if (result.error) {
					next(result.error);
				} else {
					next(null, result);
				}
			}, uploadOptions);
		} else {
			// Nothing to do
			// TODO: We should really also support deleting images from cloudinary,
			// see the CloudinaryImageType field for reference
			return next();
		}
	}, function (err, result) {
		if (err) return callback(err);
		result = result.filter(truthy);
		item.set(field.path, result);
		return callback();
	});
};

module.exports = cloudinaryimages;
<commit_msg>Adds etag (MD5) to field attributes, useful for local comparisons<commit_after>var _ = require('lodash');
var assign = require('object-assign');
var async = require('async');
var FieldType = require('../Type');
var keystone = require('../../../');
var util = require('util');

function getEmptyValue () {
	return {
		public_id: '',
		version: 0,
		signature: '',
		format: '',
		resource_type: '',
		url: '',
		width: 0,
		height: 0,
		secure_url: '',
		etag: '',
	};
}

function truthy (value) {
	return value;
}

/**
 * CloudinaryImages FieldType Constructor
 */
function cloudinaryimages (list, path, options) {
	this._underscoreMethods = ['format'];
	this._fixedSize = 'full';
	this._properties = ['select', 'selectPrefix', 'autoCleanup', 'publicID', 'folder', 'filenameAsPublicID'];

	cloudinaryimages.super_.call(this, list, path, options);

	// validate cloudinary config
	if (!keystone.get('cloudinary config')) {
		throw new Error('Invalid Configuration\n\n'
			+ 'CloudinaryImages fields (' + list.key + '.' + this.path + ') require the "cloudinary config" option to be set.\n\n'
			+ 'See http://keystonejs.com/docs/configuration/#services-cloudinary for more information.\n');
	}
}
cloudinaryimages.properName = 'CloudinaryImages';
util.inherits(cloudinaryimages, FieldType);

/**
 * Gets the folder for images in this field
 */
cloudinaryimages.prototype.getFolder = function () {
	var folder = null;
	if (keystone.get('cloudinary folders') || this.options.folder) {
		if (typeof this.options.folder === 'string') {
			folder = this.options.folder;
		} else {
			var folderList = keystone.get('cloudinary prefix') ? [keystone.get('cloudinary prefix')] : [];
			folderList.push(this.list.path);
			folderList.push(this.path);
			folder = folderList.join('/');
		}
	}
	return folder;
};

/**
 * Registers the field on the List's Mongoose Schema.
 */
cloudinaryimages.prototype.addToSchema = function (schema) {

	var cloudinary = require('cloudinary');
	var mongoose = keystone.mongoose;
	var field = this;

	this.paths = {
		// virtuals
		folder: this.path + '.folder',
		// form paths
		upload: this.path + '_upload',
		uploads: this.path + '_uploads',
		action: this.path + '_action',
	};

	var ImageSchema = new mongoose.Schema({
		public_id: String,
		version: Number,
		signature: String,
		format: String,
		resource_type: String,
		url: String,
		width: Number,
		height: Number,
		secure_url: String,
		etag: String,
	});

	// The .folder virtual returns the cloudinary folder used to upload/select images
	schema.virtual(field.paths.folder).get(function () {
		return ImageSchema.folder.apply(this);
	});

	var src = function (img, options) {
		if (keystone.get('cloudinary secure')) {
			options = options || {};
			options.secure = true;
		}
		options.format = options.format || img.format;
		return img.public_id ? cloudinary.url(img.public_id, options) : '';
	};

	var addSize = function (options, width, height, other) {
		if (width) options.width = width;
		if (height) options.height = height;
		if (typeof other === 'object') {
			assign(options, other);
		}
		return options;
	};
	ImageSchema.method('folder', function (options) {
		return this.getFolder();
	});
	ImageSchema.method('src', function (options) {
		return src(this, options);
	});
	ImageSchema.method('scale', function (width, height, options) {
		return src(this, addSize({ crop: 'scale' }, width, height, options));
	});
	ImageSchema.method('fill', function (width, height, options) {
		return src(this, addSize({ crop: 'fill', gravity: 'faces' }, width, height, options));
	});
	ImageSchema.method('lfill', function (width, height, options) {
		return src(this, addSize({ crop: 'lfill', gravity: 'faces' }, width, height, options));
	});
	ImageSchema.method('fit', function (width, height, options) {
		return src(this, addSize({ crop: 'fit' }, width, height, options));
	});
	ImageSchema.method('limit', function (width, height, options) {
		return src(this, addSize({ crop: 'limit' }, width, height, options));
	});
	ImageSchema.method('pad', function (width, height, options) {
		return src(this, addSize({ crop: 'pad' }, width, height, options));
	});
	ImageSchema.method('lpad', function (width, height, options) {
		return src(this, addSize({ crop: 'lpad' }, width, height, options));
	});
	ImageSchema.method('crop', function (width, height, options) {
		return src(this, addSize({ crop: 'crop', gravity: 'faces' }, width, height, options));
	});
	ImageSchema.method('thumbnail', function (width, height, options) {
		return src(this, addSize({ crop: 'thumb', gravity: 'faces' }, width, height, options));
	});

	schema.add(this._path.addTo({}, [ImageSchema]));

	this.removeImage = function (item, id, method, callback) {
		var images = item.get(field.path);
		if (typeof id !== 'number') {
			for (var i = 0; i < images.length; i++) {
				if (images[i].public_id === id) {
					id = i;
					break;
				}
			}
		}
		var img = images[id];
		if (!img) return;
		if (method === 'delete') {
			cloudinary.uploader.destroy(img.public_id, function () {});
		}
		images.splice(id, 1);
		if (callback) {
			item.save((typeof callback !== 'function') ? callback : undefined);
		}
	};
	this.underscoreMethod('remove', function (id, callback) {
		field.removeImage(this, id, 'remove', callback);
	});
	this.underscoreMethod('delete', function (id, callback) {
		field.removeImage(this, id, 'delete', callback);
	});
	this.bindUnderscoreMethods();
};

/**
 * Formats the field value
 */
cloudinaryimages.prototype.format = function (item) {
	return _.map(item.get(this.path), function (img) {
		return img.src();
	}).join(', ');
};

/**
 * Gets the field's data from an Item, as used by the React components
 */
cloudinaryimages.prototype.getData = function (item) {
	var value = item.get(this.path);
	return Array.isArray(value) ? value : [];
};

/**
 * Validates that a value for this field has been provided in a data object
 *
 * Deprecated
 */
cloudinaryimages.prototype.inputIsValid = function (data) { // eslint-disable-line no-unused-vars
	// TODO - how should image field input be validated?
	return true;
};

/**
 * Updates the value for this field in the item from a data object
 */
cloudinaryimages.prototype.updateItem = function (item, data, files, callback) {
	if (typeof files === 'function') {
		callback = files;
		files = {};
	} else if (!files) {
		files = {};
	}

	var cloudinary = require('cloudinary');
	var field = this;
	var values = this.getValueFromData(data);

	// TODO: This logic needs to block uploading of files from the data argument,
	// see CloudinaryImage for a reference on how it should be implemented

	// Early exit path: reset value when falsy, or bail if no value was provided
	if (!values) {
		if (values !== undefined) {
			item.set(field.path, []);
		}
		return process.nextTick(callback);
	}

	// When the value exists, but isn't an array, turn it into one (this just
	// means a single field was submitted in the formdata)
	if (!Array.isArray(values)) {
		values = [values];
	}

	// We cache options to avoid recalculating them on each iteration in the map below
	var cachedUploadOptions;
	function getUploadOptions () {
		if (cachedUploadOptions) {
			return cachedUploadOptions;
		}
		var tagPrefix = keystone.get('cloudinary prefix') || '';
		var uploadOptions = {
			tags: [],
			resource_type: 'auto',
		};
		if (tagPrefix.length) {
			uploadOptions.tags.push(tagPrefix);
			tagPrefix += '_';
		}
		uploadOptions.tags.push(tagPrefix + field.list.path + '_' + field.path);
		if (keystone.get('env') !== 'production') {
			uploadOptions.tags.push(tagPrefix + 'dev');
		}
		var folder = field.getFolder();
		if (folder) {
			uploadOptions.folder = folder;
		}
		cachedUploadOptions = uploadOptions;
		return uploadOptions;
	}

	// Preprocess values to deserialise JSON, detect mappings to uploaded files
	// and flatten out arrays
	values = values.map(function (value) {
		// When the value is a string, it may be JSON serialised data.
		if (typeof value === 'string'
			&& value.charAt(0) === '{'
			&& value.charAt(value.length - 1) === '}'
		) {
			try {
				return JSON.parse(value);
			} catch (e) { /* value isn't JSON */ }
		}
		if (typeof value === 'string') {
			// detect file upload (field value must be a reference to a field in the
			// uploaded files object provided by multer)
			if (value.substr(0, 7) === 'upload:') {
				var uploadFieldPath = value.substr(7);
				return files[uploadFieldPath];
			}
			// detect a URL or Base64 Data
			else if (/^(data:[a-z\/]+;base64)|(https?\:\/\/)/.test(value)) {
				return { path: value };
			}
		}
		return value;
	});
	values = _.flatten(values);

	async.map(values, function (value, next) {
		if (typeof value === 'object' && 'public_id' in value) {
			// Setting "autoCleanup" the property "remove:true" removes the file and resets the field
			if (field.options.autoCleanup && value.public_id && value.remove) {
				cloudinary.uploader.destroy(value.public_id, function (result) {
					if (result.error || result === 'not found') {
						return next(result.error || 'not found');
					} else {
						// Remove value
						return next();
					}
				}, {
					resource_type: value.resource_type,
				});
			// Cloudinary Image data provided
			} else if (value.public_id) {
				// Default the object with empty values
				var v = assign(getEmptyValue(), value);
				return next(null, v);
			} else {
				// public_id is falsy, remove the value
				return next();
			}
		} else if (typeof value === 'object' && value.path) {
			// File provided - upload it
			var uploadOptions = getUploadOptions();
			// NOTE: field.options.publicID has been deprecated (tbc)
			if (field.options.filenameAsPublicID && value.originalname && typeof value.originalname === 'string') {
				uploadOptions = assign({}, uploadOptions, {
					public_id: value.originalname.substring(0, value.originalname.lastIndexOf('.')),
				});
			}
			// TODO: implement autoCleanup; should delete existing images before uploading
			cloudinary.uploader.upload(value.path, function (result) {
				if (result.error) {
					next(result.error);
				} else {
					next(null, result);
				}
			}, uploadOptions);
		} else {
			// Nothing to do
			// TODO: We should really also support deleting images from cloudinary,
			// see the CloudinaryImageType field for reference
			return next();
		}
	}, function (err, result) {
		if (err) return callback(err);
		result = result.filter(truthy);
		item.set(field.path, result);
		return callback();
	});
};

module.exports = cloudinaryimages;
<|endoftext|>


<commit_before>
"use strict"

var jsdates = (function() {
    var datenow = null;

    function JSDate(date, isday) {
        this.year = function () {
            return date.getFullYear();
        }

        this.month = function () {
            return date.getMonth() + 1;
        }

        this.day = function () {
            return date.getDate();
        }

        this.hours = function () {
            if (isday)
                return 0;

            return date.getHours();
        }

        this.minutes = function () {
            if (isday)
                return 0;

            return date.getMinutes();
        }

        this.seconds = function () {
            if (isday)
                return 0;

            return date.getSeconds();
        }

        this.addDays = function (days) {
            date.setDate(date.getDate() + days);
            return this;
        }

        this.addMonths = function (months) {
            date.setMonth(date.getMonth() + months);
            return this;
        }

        this.toDate = function () {
            if (isday)
                return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);

            return new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds());
        }
    }

    function today() {
        return new JSDate(datenow ? datenow : new Date(), true);
    }

    function now() {
        return new JSDate(datenow ? datenow : new Date(), false);
    }

    function date(year, month, day) {
        return new JSDate(new Date(year, month - 1, day, 0, 0, 0), true);
    }

    function datetime(year, month, day, hours, minutes, seconds) {
        return new JSDate(new Date(year, month - 1, day, hours, minutes, seconds), false);
    }

    function set(name, value) {
        if (name === 'now')
            datenow = value;
    }

    return {
        today: today,
        now: now,
        date: date,
        datetime: datetime,
        set: set
    }
})();

if (typeof module !== 'undefined' && typeof module.exports !== 'undefined')
    module.exports = jsdates;

<commit_msg>internal refactor, set value in config<commit_after>
"use strict"

var jsdates = (function() {
    var config = {};

    function JSDate(date, isday) {
        this.year = function () {
            return date.getFullYear();
        }

        this.month = function () {
            return date.getMonth() + 1;
        }

        this.day = function () {
            return date.getDate();
        }

        this.hours = function () {
            if (isday)
                return 0;

            return date.getHours();
        }

        this.minutes = function () {
            if (isday)
                return 0;

            return date.getMinutes();
        }

        this.seconds = function () {
            if (isday)
                return 0;

            return date.getSeconds();
        }

        this.addDays = function (days) {
            date.setDate(date.getDate() + days);
            return this;
        }

        this.addMonths = function (months) {
            date.setMonth(date.getMonth() + months);
            return this;
        }

        this.toDate = function () {
            if (isday)
                return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);

            return new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds());
        }
    }

    function today() {
        return new JSDate(config.now ? config.now : new Date(), true);
    }

    function now() {
        return new JSDate(config.now ? config.now : new Date(), false);
    }

    function date(year, month, day) {
        return new JSDate(new Date(year, month - 1, day, 0, 0, 0), true);
    }

    function datetime(year, month, day, hours, minutes, seconds) {
        return new JSDate(new Date(year, month - 1, day, hours, minutes, seconds), false);
    }

    function set(name, value) {
        config[name] = value;
    }

    return {
        today: today,
        now: now,
        date: date,
        datetime: datetime,
        set: set
    }
})();

if (typeof module !== 'undefined' && typeof module.exports !== 'undefined')
    module.exports = jsdates;

<|endoftext|>


<commit_before>'use strict';

const util = require('util');
const EventEmitter = require('events').EventEmitter;

const config = require('../config');
const constants = require('../constants');
const k8sClient = require('./clientFactory');

const debug = require('debug')('tilloo:k8sjob');

debug('config.jobEnvironmentVariables', config.jobEnvironmentVariables);

const jobEnvironmentVariables = [];
if (config.jobEnvironmentVariables) {
    // eslint-disable-next-line guard-for-in
    for (const key in config.jobEnvironmentVariables) {
        jobEnvironmentVariables.push({ name: key, value: config.jobEnvironmentVariables[key] });
    }
}
// expose host_ip into containers.  Useful for monitoring, etc
jobEnvironmentVariables.push({ name: 'HOST_IP', valueFrom: { fieldRef: { fieldPath: 'status.hostIP' } } });
debug('jobEnvironmentVariables', jobEnvironmentVariables);

class Job extends EventEmitter {
    constructor(jobId, runId, name, imageUri, path, args, nodeSelector, timeout) {
        super();
        const self = this;
        this.jobId = jobId;
        this.runId = runId;
        this.name = name;
        this.imageUri = imageUri;
        this.path = path;
        this.args = args;
        this.timeout = timeout;

        this.command = [this.path].concat(args);
        this.uniqueName = `${jobId}-${runId}`;

        this.jobDef = {
            apiVersion: 'batch/v1',
            kind: 'Job',
            metadata: {
                name: this.uniqueName,
                labels: {
                    jobId: this.jobId,
                    runId: this.runId
                }
            },
            spec: {
                template: {
                    metadata: {
                        labels: {
                            jobId: this.jobId,
                            runId: this.runId
                        }
                    },
                    spec: {
                        containers: [
                            {
                                env: jobEnvironmentVariables,
                                name: this.uniqueName,
                                image: this.imageUri,
                                imagePullPolicy: 'Always',
                                command: this.command
                            }
                        ],
                        restartPolicy: 'Never',
                        dnsPolicy: 'Default'
                    }
                },
                backoffLimit: 0,
                ttlSecondsAfterFinished: 3600
            }
        };

        if (this.timeout !== undefined && this.timeout !== 0) {
            this.jobDef.spec.activeDeadlineSeconds = this.timeout;
        }

        if (nodeSelector) {
            const nodeSelectors = nodeSelector.split(',');
            nodeSelectors.forEach(function (selector) {
                const selectorParts = selector.split('=');
                if (selectorParts.length === 2) {
                    if (!self.jobDef.spec.template.spec.nodeSelector) {
                        self.jobDef.spec.template.spec.nodeSelector = {};
                    }
                    self.jobDef.spec.template.spec.nodeSelector[selectorParts[0]] = selectorParts[1];
                }
            });
        }

        debug(`k8s/jobDef`, JSON.stringify(self.jobDef, null, 2));
    }

    start() {
        const self = this;

        debug(`Starting k8Job jobId: ${self.jobId}, runId: ${self.runId}`);

        function errorStatus(err) {
            console.error('script error jobId: %s, runId: %s, path: %s, err: %s', self.jobId, self.runId, self.path, self.args, err);
            self.logOutput(util.format('script error\njobId: %s\nrunId: %s\npath: %s\nerr: %s', self.jobId, self.runId, self.path, self.args, err));

            self.updateStatus({ status: constants.JOBSTATUS.FAIL });
            self.emit('complete');
        }

        try {
            k8sClient.apis.batch.v1.namespaces(constants.NAMESPACE).jobs.post({ body: this.jobDef }).then((job) => {
                debug(`job created`, job);
            }).catch((err) => {
                console.error('job creation err: ', err);
            });
        }
        catch (err) {
            errorStatus(err);
        }
    }

    static async remove(runId) {
        await k8sClient.loadSpec();
        await Promise.all([
            k8sClient.apis.batch.v1.namespaces(constants.NAMESPACE).jobs.delete({ qs: { labelSelector: `runId=${runId}` } }),
            k8sClient.apis.v1.namespaces(constants.NAMESPACE).pods.delete({ qs: { labelSelector: `runId=${runId}` } })
        ]);
    }

    updateStatus(message) {
        message.runId = this.runId;
        message.jobId = this.jobId;
        this.emit('status', message);
    }
}

module.exports = Job;<commit_msg>Fix api path<commit_after>'use strict';

const util = require('util');
const EventEmitter = require('events').EventEmitter;

const config = require('../config');
const constants = require('../constants');
const k8sClient = require('./clientFactory');

const debug = require('debug')('tilloo:k8sjob');

debug('config.jobEnvironmentVariables', config.jobEnvironmentVariables);

const jobEnvironmentVariables = [];
if (config.jobEnvironmentVariables) {
    // eslint-disable-next-line guard-for-in
    for (const key in config.jobEnvironmentVariables) {
        jobEnvironmentVariables.push({ name: key, value: config.jobEnvironmentVariables[key] });
    }
}
// expose host_ip into containers.  Useful for monitoring, etc
jobEnvironmentVariables.push({ name: 'HOST_IP', valueFrom: { fieldRef: { fieldPath: 'status.hostIP' } } });
debug('jobEnvironmentVariables', jobEnvironmentVariables);

class Job extends EventEmitter {
    constructor(jobId, runId, name, imageUri, path, args, nodeSelector, timeout) {
        super();
        const self = this;
        this.jobId = jobId;
        this.runId = runId;
        this.name = name;
        this.imageUri = imageUri;
        this.path = path;
        this.args = args;
        this.timeout = timeout;

        this.command = [this.path].concat(args);
        this.uniqueName = `${jobId}-${runId}`;

        this.jobDef = {
            apiVersion: 'batch/v1',
            kind: 'Job',
            metadata: {
                name: this.uniqueName,
                labels: {
                    jobId: this.jobId,
                    runId: this.runId
                }
            },
            spec: {
                template: {
                    metadata: {
                        labels: {
                            jobId: this.jobId,
                            runId: this.runId
                        }
                    },
                    spec: {
                        containers: [
                            {
                                env: jobEnvironmentVariables,
                                name: this.uniqueName,
                                image: this.imageUri,
                                imagePullPolicy: 'Always',
                                command: this.command
                            }
                        ],
                        restartPolicy: 'Never',
                        dnsPolicy: 'Default'
                    }
                },
                backoffLimit: 0,
                ttlSecondsAfterFinished: 3600
            }
        };

        if (this.timeout !== undefined && this.timeout !== 0) {
            this.jobDef.spec.activeDeadlineSeconds = this.timeout;
        }

        if (nodeSelector) {
            const nodeSelectors = nodeSelector.split(',');
            nodeSelectors.forEach(function (selector) {
                const selectorParts = selector.split('=');
                if (selectorParts.length === 2) {
                    if (!self.jobDef.spec.template.spec.nodeSelector) {
                        self.jobDef.spec.template.spec.nodeSelector = {};
                    }
                    self.jobDef.spec.template.spec.nodeSelector[selectorParts[0]] = selectorParts[1];
                }
            });
        }

        debug(`k8s/jobDef`, JSON.stringify(self.jobDef, null, 2));
    }

    start() {
        const self = this;

        debug(`Starting k8Job jobId: ${self.jobId}, runId: ${self.runId}`);

        function errorStatus(err) {
            console.error('script error jobId: %s, runId: %s, path: %s, err: %s', self.jobId, self.runId, self.path, self.args, err);
            self.logOutput(util.format('script error\njobId: %s\nrunId: %s\npath: %s\nerr: %s', self.jobId, self.runId, self.path, self.args, err));

            self.updateStatus({ status: constants.JOBSTATUS.FAIL });
            self.emit('complete');
        }

        try {
            k8sClient.apis.batch.v1.namespaces(constants.NAMESPACE).jobs.post({ body: this.jobDef }).then((job) => {
                debug(`job created`, job);
            }).catch((err) => {
                console.error('job creation err: ', err);
            });
        }
        catch (err) {
            errorStatus(err);
        }
    }

    static async remove(runId) {
        await k8sClient.loadSpec();
        await Promise.all([
            k8sClient.apis.batch.v1.namespaces(constants.NAMESPACE).jobs.delete({ qs: { labelSelector: `runId=${runId}` } }),
            k8sClient.api.v1.namespaces(constants.NAMESPACE).pods.delete({ qs: { labelSelector: `runId=${runId}` } })
        ]);
    }

    updateStatus(message) {
        message.runId = this.runId;
        message.jobId = this.jobId;
        this.emit('status', message);
    }
}

module.exports = Job;<|endoftext|>


<commit_before>/**
 * Pie chart extension for leaflet using Leaflet-semicircle.
 * Jan Pieter Waagmeester <jieter@jieter.nl>
 *
 * latlng
 *  Location to add the pie chart.
 *
 * data - The data for Leaflet Pie chart can be supplied in three ways:
 *
 *  = single number: display two parts, random colors.
 *  = array of numbers: display numbers in array normalized to 360 degrees, random colors.
 *  = array of objects:
 * [
 *   {
 *      num: <number>,
 *      color: "<color>",
 *      label: "label A"
 *   },
 *   {
 *      num: // etc...
 *   }
 * ]
 * If color is omitted, a random (predictable) color will be be choosen.
 *
 * options - for the pie charts.
 *  radius: <number>, in meters.
 *  pathOptions: <Leaflet Path options>
 *  labels: <boolean> Display
 *  colors: <null|array> if colors is an array, the colors will be used for the slices.
 *
 */

/*jshint browser:true, strict:false, globalstrict:false, indent:4, white:true, smarttabs:true*/
/*global L:true*/

(function (L) {
	L.Pie = L.Class.extend({
		options: {
			radius: 500,
			pathOptions: {
				weight: 1
			},
			labels: true,
			colors: null
		},
		initialize: function (latlng, data, options) {
			this._latlng = latlng;
			L.Util.setOptions(this, options);
			this._prepareData(data);
		},

		_prepareData: function (data) {
			this._count = 0;
			this._sum = 0;
			this._data = {};

			var part;
			for (var i = 0; i < data.length; i++) {
				if (typeof(data[i]) == 'number') {
					part = {
						num: data[i]
					};
				} else {
					part = data[i];
				}
				if (!part.color) {
					part.color = this.randomColor();
				}
				if (!part.label) {
					part.label = '';
				}

				this._count++;
				this._sum += part.num;
				this._data[i] = part;
			}
		},

		setData: function (data) {
			this._prepareData(data);
			// TODO: redraw
			return this;
		},

		redraw: function () {
			// TODO implement
			return this;
		},

		// return the sum of the input data.
		sum: function () {
			return this._sum;
		},
		count: function () {
			return this._count;
		},

		_normalize: function (num) {
			return num / this.sum();
		},
		_color: function (index) {
			return this._data[index].color;
		},

		// layer implementation.
		onAdd: function (map) {
			this._parts = [];
			var startAngle = 0;
			var stopAngle = 0;

			for (var i = 0; i < this.count(); i++) {
				var normalized = this._normalize(this._data[i].num);

				stopAngle = normalized * 360 + startAngle;

				// set start/stop Angle and color for semicircle
				var options = {
					startAngle: startAngle,
					stopAngle: stopAngle,

					fillColor: this._color(i),
					color: this._color(i)
				};

				this._data[i]._part =
					L.circle(
						this._latlng,
						this.options.radius,
						L.Util.extend({}, this.options.pathOptions, options)
					).addTo(map);

				var labelDir = (normalized * 360) / 2  + startAngle;
				var labelText = this._data[i].label;
				if (labelText != '') {
					labelText += ' ';
				}
				labelText += L.Util.formatNum(normalized * 100, 1) + '%';

				// add a label.
				if (this.options.labels) {
					this._data[i]._label =
						new L.PieLabel(
							this._latlng,
							this.options.radius,
							labelDir,
							labelText
						).addTo(map);
				}

				startAngle = stopAngle;
			}
			return this;
		},
		addTo: function (map) {
			map.addLayer(this);
			return this;
		},

		onRemove: function (map) {
			for (var i = 0; i < this.count(); i++) {
				this._data[i]._part.onRemove(map);
				if (this.options.labels) {
					this._data[i]._label.onRemove(map);
				}
			}
			return this;
		},
		_reset: function () {

		},
		randomColor: function () {
			if (this._counter === undefined) {
				this._counter = 0;
			}
			this._counter++;

			// if an array with colors is passed, use it.
			if (this.options.colors != null) {
				return this.options.colors[this._counter % this.options.colors.length];
			}

			//Based on http://krazydad.com/tutorials/makecolors.php
			var byte2Hex = function (n) {
				var nybHexString = "0123456789ABCDEF";
				return (
					String(nybHexString.substr((n >> 4) & 0x0F, 1)) +
					String(nybHexString.substr(n & 0x0F, 1))
				);
			};
			return '#' +
				byte2Hex(Math.sin(1.666 * this._counter) * 127 + 128) +
				byte2Hex(Math.sin(2.666 * this._counter) * 127 + 128) +
				byte2Hex(Math.sin(3.666 * this._counter) * 127 + 128);
		}
	});
})(L);

L.pie = function (latlng, param, options) {
	var data = [];
	if (typeof(param) == "number") {
		// for a single number, a percentage is assumed.
		param = param / 100;
		data.push(param);
		data.push(1 - param);
	} else {
		data = param;
	}

	if (!options) {
		options = {};
	}
	return new L.Pie(latlng, data, options);
};

/**
 * Draw a label for a pie chart.
 */
L.PieLabel = L.Circle.extend({
	options: {
		buffer: 2,
		length: 20,
		fill: false,
		weight: 1,
		color: '#000'
	},
	initialize: function(latlng, radius, dir, text, options) {
		L.Circle.prototype.initialize.call(this, latlng, radius, options)
		this._dir = dir;
		this._text = text;
	},

	onRemove: function (map) {
	this._container.removeChild(this._t);

		L.Circle.prototype.onRemove.call(this, map);

	},
	getPathString: function () {
		var center = this._point,
			    r = this._radius;

			var labelStart = this.rotated(
				this._fixAngle(this._dir),
				r + this.options.buffer
			),
			labelMid = this.rotated(
				this._fixAngle(this._dir),
				r + this.options.buffer + this.options.length
			);

			var dx = this.options.length;
			var textAnchor = 'start';
			if (this._dir > 190) {
				dx *= -1;
				textAnchor = 'end';
			}
			labelEnd = labelMid.add(L.point(dx, 0));

			this._t = this._createElement('text');

			this._t.setAttribute('x', labelEnd.x);
			this._t.setAttribute('y', labelEnd.y);
			this._t.setAttribute('dx', 2);
			this._t.setAttribute('dy', 5);
			this._t.setAttribute('text-anchor', textAnchor);
			this._t.setAttribute('style', 'font: 10px "Arial"');
			this._t.textContent = this._text;

			this._container.appendChild(this._t);

			if (L.Browser.svg) {

				//move to labelStart
				var ret = "M" + labelStart.x + "," + labelStart.y;

				ret += "L " + labelMid.x + "," + labelMid.y;
				// horizontal part.
				ret += "L " + labelEnd.x + ", " + labelEnd.y;

				return ret;
			}
	}
});<commit_msg>Fix jshint and correctly merge pathOptions.<commit_after>/**
 * Pie chart extension for leaflet using Leaflet-semicircle.
 * Jan Pieter Waagmeester <jieter@jieter.nl>
 *
 * latlng
 *  Location to add the pie chart.
 *
 * data - The data for Leaflet Pie chart can be supplied in three ways:
 *
 *  = single number: display two parts, random colors.
 *  = array of numbers: display numbers in array normalized to 360 degrees, random colors.
 *  = array of objects:
 * [
 *   {
 *      num: <number>,
 *      color: "<color>",
 *      label: "label A"
 *   },
 *   {
 *      num: // etc...
 *   }
 * ]
 * If color is omitted, a random (predictable) color will be be choosen.
 *
 * options - for the pie charts.
 *  radius: <number>, in meters.
 *  pathOptions: <Leaflet Path options>
 *  labels: <boolean> Display
 *  colors: <null|array> if colors is an array, the colors will be used for the slices.
 *
 */

/*jshint browser:true, strict:false, globalstrict:false, indent:4, white:true, smarttabs:true*/
/*global L:true*/

(function (L) {
	L.Pie = L.Class.extend({
		options: {
			radius: 500,
			labels: true,
			colors: null
		},
		pathOptions: {
			weight: 1
		},
		initialize: function (latlng, data, options) {
			this._latlng = latlng;
			L.Util.setOptions(this, options);

			this.options.pathOptions = L.Util.extend({}, this.pathOptions, options.pathOptions);
			this._prepareData(data);
		},

		_prepareData: function (data) {
			this._count = 0;
			this._sum = 0;
			this._data = {};

			var part;
			for (var i = 0; i < data.length; i++) {
				if (typeof(data[i]) == 'number') {
					part = {
						num: data[i]
					};
				} else {
					part = data[i];
				}
				if (!part.color) {
					part.color = this.randomColor();
				}
				if (!part.label) {
					part.label = '';
				}

				this._count++;
				this._sum += part.num;
				this._data[i] = part;
			}
		},

		setData: function (data) {
			this._prepareData(data);
			// TODO: redraw
			return this;
		},

		redraw: function () {
			// TODO implement
			return this;
		},

		// return the sum of the input data.
		sum: function () {
			return this._sum;
		},
		count: function () {
			return this._count;
		},

		_normalize: function (num) {
			return num / this.sum();
		},
		_color: function (index) {
			return this._data[index].color;
		},

		// layer implementation.
		onAdd: function (map) {
			this._parts = [];
			var startAngle = 0;
			var stopAngle = 0;

			for (var i = 0; i < this.count(); i++) {
				var normalized = this._normalize(this._data[i].num);

				stopAngle = normalized * 360 + startAngle;

				// set start/stop Angle and color for semicircle
				var options = {
					startAngle: startAngle,
					stopAngle: stopAngle,

					fillColor: this._color(i),
					color: this._color(i)
				};

				this._data[i]._part =
					L.circle(
						this._latlng,
						this.options.radius,
						L.Util.extend({}, options, this.options.pathOptions)
					).addTo(map);

				var labelDir = (normalized * 360) / 2  + startAngle;
				var labelText = this._data[i].label;
				if (labelText !== '') {
					labelText += ' ';
				}
				labelText += L.Util.formatNum(normalized * 100, 1) + '%';

				// add a label.
				if (this.options.labels) {
					this._data[i]._label =
						new L.PieLabel(
							this._latlng,
							this.options.radius,
							labelDir,
							labelText
						).addTo(map);
				}

				startAngle = stopAngle;
			}
			return this;
		},
		addTo: function (map) {
			map.addLayer(this);
			return this;
		},

		onRemove: function (map) {
			for (var i = 0; i < this.count(); i++) {
				this._data[i]._part.onRemove(map);
				if (this.options.labels) {
					this._data[i]._label.onRemove(map);
				}
			}
			return this;
		},
		_reset: function () {

		},
		randomColor: function () {
			if (this._counter === undefined) {
				this._counter = 0;
			}
			this._counter++;

			// if an array with colors is passed, use it.
			if (this.options.colors !== null) {
				return this.options.colors[this._counter % this.options.colors.length];
			}

			//Based on http://krazydad.com/tutorials/makecolors.php
			var byte2Hex = function (n) {
				var nybHexString = "0123456789ABCDEF";
				return (
					String(nybHexString.substr((n >> 4) & 0x0F, 1)) +
					String(nybHexString.substr(n & 0x0F, 1))
				);
			};
			return '#' +
				byte2Hex(Math.sin(1.666 * this._counter) * 127 + 128) +
				byte2Hex(Math.sin(2.666 * this._counter) * 127 + 128) +
				byte2Hex(Math.sin(3.666 * this._counter) * 127 + 128);
		}
	});
})(L);

L.pie = function (latlng, param, options) {
	var data = [];
	if (typeof(param) == "number") {
		// for a single number, a percentage is assumed.
		param = param / 100;
		data.push(param);
		data.push(1 - param);
	} else {
		data = param;
	}

	if (!options) {
		options = {};
	}
	return new L.Pie(latlng, data, options);
};

/**
 * Draw a label for a pie chart.
 */
L.PieLabel = L.Circle.extend({
	options: {
		buffer: 2,
		length: 20,
		fill: false,
		weight: 1,
		color: '#000'
	},
	initialize: function (latlng, radius, dir, text, options) {
		L.Circle.prototype.initialize.call(this, latlng, radius, options);
		this._dir = dir;
		this._text = text;
	},

	onRemove: function (map) {
		this._container.removeChild(this._t);

		L.Circle.prototype.onRemove.call(this, map);

	},
	getPathString: function () {
		var center = this._point,
			    r = this._radius;

		var labelStart = this.rotated(
			this._fixAngle(this._dir),
			r + this.options.buffer
		),
		labelMid = this.rotated(
			this._fixAngle(this._dir),
			r + this.options.buffer + this.options.length
		);

		var dx = this.options.length;
		var textAnchor = 'start';
		if (this._dir > 190) {
			dx *= -1;
			textAnchor = 'end';
		}
		labelEnd = labelMid.add(L.point(dx, 0));

		this._t = this._createElement('text');

		this._t.setAttribute('x', labelEnd.x);
		this._t.setAttribute('y', labelEnd.y);
		this._t.setAttribute('dx', 2);
		this._t.setAttribute('dy', 5);
		this._t.setAttribute('text-anchor', textAnchor);
		this._t.setAttribute('style', 'font: 10px "Arial"');
		this._t.textContent = this._text;

		this._container.appendChild(this._t);

		if (L.Browser.svg) {

			//move to labelStart
			var ret = "M" + labelStart.x + "," + labelStart.y;

			ret += "L " + labelMid.x + "," + labelMid.y;
			// horizontal part.
			ret += "L " + labelEnd.x + ", " + labelEnd.y;

			return ret;
		}
	}
});<|endoftext|>