<commit_before>import Email from '../models/email.model';
import mongoose from 'mongoose';
import User from '../models/user.model';
import striptags from 'striptags';
const ObjectId = mongoose.Types.ObjectId;

function getMonthlyPunchCardWithYear(userId) {
  return Email.aggregate([
    {$match: {user: ObjectId(userId)}},
    {$group: {_id: {year: {$year: "$date"}, month: {$month: "$date"}, day: {$dayOfMonth: "$date"}}, count: {$sum: 1}}},
    {$sort: {'_id.year':1, '_id.month': 1, '_id.day': 1}},
    {$project: {_id: 0, year: '$_id.year', month: '$_id.month', day: '$_id.day', count: 1}}
  ]);
}

function getMonthlyPunchCard(userId) {
  return Email.aggregate([
    {$match: {user: ObjectId(userId)}},
    {$group: {_id: {month: {$month: "$date"}, day: {$dayOfMonth: "$date"}}, count: {$sum: 1}}},
    {$sort: {'_id.month': 1, '_id.day': 1}},
    {$project: {_id: 0, month: '$_id.month', day: '$_id.day', count: 1}}
  ]);
}

function getDailyPunchCard(userId) {
  return Email.aggregate([
    {$match: {user: ObjectId(userId)}},
    {$group: {_id: {day: {$dayOfWeek: "$date"}, hour: {$hour: "$date"}}, count: {$sum: 1}}},
    {$sort: {'_id.day': 1, '_id.hour': 1}},
    {$project: {_id: 0, day: '$_id.day', hour: '$_id.hour', count: 1}}
  ]);
}

function getTopSender(userId) {
  return Email.aggregate([
    {$match: {user: ObjectId(userId)}},
    {$unwind: '$from'},
    {$group: {_id: { $toLower:'$from.address'}, count: {$sum: 1}}},
    {$sort: {count: -1}},
    {$project: {_id: 0, address: '$_id', count: 1}},
    {$limit : 15}
  ]);
}

function getTopReceiver(userId) {
  return Email.aggregate([
    {$match: {user: ObjectId(userId)}},
    {$unwind: '$to'},
    {$group: {_id: { $toLower:'$to.address'}, count: {$sum: 1}}},
    {$sort: {'count': -1}},
    {$project: {_id: 0, address: '$_id', count: 1}},
    {$limit : 15}
  ]);
}

function getNetworkGraph(userId){

  class Edge{

    constructor(from, to){
      if(from)
        this.from = from.toLowerCase();
      if(to)
        this.to = to.toLowerCase();
      this.count = 1;
    }

    increaseCount(){
      this.count++;
    }

    key(){
      return this.from+'_'+this.to;
    }

    toJson(){
      return {from: this.from, to: this.to, count: this.count};
    }
  }

  class Node{

    constructor(email, name){
      if(email)
        this.email = email.toLowerCase();
      this.name = name;
    }

    key(){
      return this.email;
    }

    toJson(){
      return {email: this.email, name: this.name};
    }
  }

  /** Not implemented as set due the fact that the
   *  compare for objects is not implemented in es6 */
  const edges = new Map();
  const nodes = new Map();

  return new Promise((resolve, reject) => {
    Email.find({user: ObjectId(userId)}, {from: 1, to: 1}).lean()
      .then((emails)=> {
        emails.forEach((email)=> {
          if(email.from != null)
            email.from.forEach((from)=> {
              if(email.to != null)
                email.to.forEach((to)=> {
                  let edge = new Edge(from.address, to.address);
                  if (edges.has(edge.key())) {
                    edge = edges.get(edge.key());
                    edge.increaseCount();
                  } else {
                    edges.set(edge.key(), edge);
                  }
                  let node = new Node(from.address, from.name);
                  if(!nodes.has(node.key()))
                    nodes.set(node.key(), node);
                  node = new Node(to.address, to.name);
                  if(!nodes.has(node.key()))
                    nodes.set(node.key(), node);
                });
            });
        });
        const g = {
          edges: [],
          nodes: []
        };
        edges.forEach((e)=> {
          g.edges.push(e.toJson());
        });
        nodes.forEach((n)=> {
          g.nodes.push(n.toJson());
        });
        resolve(g);
      }).catch((err)=>{
        reject(err);
      });
  });
}

function getActions(userId){

  return {
    all: undefined,
    needreply: undefined,
    noreply : undefined,
  }
}

function getLabels(userId){
  return Email.aggregate([
    {$match: {user: userId}},
    {$unwind: '$labels'},
    {$group: {_id: {label: '$labels'}, count: {$sum: 1}}},
    {$sort: {count: -1}},
    {$project: {_id: 0, label: '$_id.label', count: 1}}
  ]);
}

function getConversations(userId){
  return Email.aggregate([
    {$match: {user: userId}},
    {$group: {_id: {thrid: '$thrid'}, nrmsg: {$sum: 1}}},
    {$group: {_id: {nrmsg: '$nrmsg'}, nrthr: {$sum: 1}}},
    {$project: {_id: 0, nrmsg: '$_id.nrmsg', nrthr: 1}},
    {$sort: {nrmsg: -1}}
  ]);
}

//TODO remove
function testNer(){
  Email.find({}).then((emails)=>{
    emails.forEach((email)=>{
      if(email.text != undefined){
        email.plainText = email.text;
      }else if(email.html != undefined){
        email.plainText = striptags(email.html);
      }
      console.log(email.flags);
      console.log(email.labels);
      console.log('#############');

    });
    console.log(emails.length);
  });
}

function getTimeline(req, res){
  let userId = req.user._id;
  const s = {};
  console.log(userId);
  getMonthlyPunchCard(userId)
    .then((m) => {
      s.monthly = m;
      return getDailyPunchCard(userId);
    })
    .then((d) => {
      s.daily = d;
      res.status(200).send(s);
    });
}

function getNetwork(req, res){
  let userId = req.user._id;
  const s = {};
  getTopSender(userId)
    .then((ts) => {
      s.topsender = ts;
      return getTopReceiver(userId);
    })
    .then((tr) => {
      s.topreceiver = tr;
      return getNetworkGraph(userId);
    })
    .then((g) => {
      s.graph = g;
      res.status(200).send(s);
    });
}

function getStructure(req, res){
  let userId = req.user._id;
  const s = {};
  getConversations(userId)
    .then((c)=>{
      s.converstations = c;
      return getLabels(userId);
    })
    .then((l)=>{
      s.labels = l;
      res.status(200).send(s);
    });
}

function getSummary(req, res) {

  let userId = null;
  const s = {
    punchcard: {},
    network: {},
    structural: {}
  };

  //TODO differentiate between send, received and all mails
  //TODO use id of current user?? assuming that the dashboard is embedded in WebApp??
  User.findOne()
    .then((user) => {
      userId = user._id;
      return getMonthlyPunchCard(userId);
    })
    .then((monthlySummary) => {
      s.punchcard.monthly = monthlySummary;
      return getDailyPunchCard(userId);
    })
    .then((dailySummary) => {
      s.punchcard.daily = dailySummary;
      return getTopSender(userId)
    })
    .then((topSender) => {
      s.network.topsender = topSender;
      return getTopReceiver(userId)
    })
    .then((topReceiver) => {
      s.network.topreceiver = topReceiver;
      return getNetworkGraph(userId);
    })
    .then((graph) => {
      s.network.graph = graph;
      return getActions(userId);
    })
    .then((actions)=>{
      s.structural.actions = actions;
      return getConversations(userId)
    })
    .then((conversations)=>{
      s.structural.converstations = conversations;
      return getLabels(userId)
    })
    .then((labels)=>{
      s.structural.labels = labels;
      res.status(200).send(s);
    })
}

export default {
  getSummary,
  getTimeline,
  getNetwork,
  getStructure
};
<commit_msg>dashboard network fixes<commit_after>import Email from '../models/email.model';
import mongoose from 'mongoose';
import User from '../models/user.model';
import striptags from 'striptags';
const ObjectId = mongoose.Types.ObjectId;

function getMonthlyPunchCardWithYear(userId) {
  return Email.aggregate([
    {$match: {user: ObjectId(userId)}},
    {$group: {_id: {year: {$year: "$date"}, month: {$month: "$date"}, day: {$dayOfMonth: "$date"}}, count: {$sum: 1}}},
    {$sort: {'_id.year':1, '_id.month': 1, '_id.day': 1}},
    {$project: {_id: 0, year: '$_id.year', month: '$_id.month', day: '$_id.day', count: 1}}
  ]);
}

function getMonthlyPunchCard(userId) {
  return Email.aggregate([
    {$match: {user: ObjectId(userId)}},
    {$group: {_id: {month: {$month: "$date"}, day: {$dayOfMonth: "$date"}}, count: {$sum: 1}}},
    {$sort: {'_id.month': 1, '_id.day': 1}},
    {$project: {_id: 0, month: '$_id.month', day: '$_id.day', count: 1}}
  ]);
}

function getDailyPunchCard(userId) {
  return Email.aggregate([
    {$match: {user: ObjectId(userId)}},
    {$group: {_id: {day: {$dayOfWeek: "$date"}, hour: {$hour: "$date"}}, count: {$sum: 1}}},
    {$sort: {'_id.day': 1, '_id.hour': 1}},
    {$project: {_id: 0, day: '$_id.day', hour: '$_id.hour', count: 1}}
  ]);
}

function getTopFrom(userId) {
  return Email.aggregate([
    {$match: {user: ObjectId(userId)}},
    {$unwind: '$from'},
    {$group: {_id: { $toLower:'$from.address'}, count: {$sum: 1}}},
    {$sort: {count: -1}},
    {$project: {_id: 0, address: '$_id', count: 1}},
    {$limit : 15}
  ]);
}

function getTopTo(userId) {
  return Email.aggregate([
    {$match: {user: ObjectId(userId)}},
    {$unwind: '$to'},
    {$group: {_id: { $toLower:'$to.address'}, count: {$sum: 1}}},
    {$sort: {'count': -1}},
    {$project: {_id: 0, address: '$_id', count: 1}},
    {$limit : 15}
  ]);
}

function getTopCC(userId) {
  return Email.aggregate([
    {$match: {user: ObjectId(userId)}},
    {$unwind: '$cc'},
    {$group: {_id: { $toLower:'$cc.address'}, count: {$sum: 1}}},
    {$sort: {'count': -1}},
    {$project: {_id: 0, address: '$_id', count: 1}},
    {$limit : 15}
  ]);
}

function getTopBCC(userId) {
  return Email.aggregate([
    {$match: {user: ObjectId(userId)}},
    {$unwind: '$bcc'},
    {$group: {_id: { $toLower:'$bcc.address'}, count: {$sum: 1}}},
    {$sort: {'count': -1}},
    {$project: {_id: 0, address: '$_id', count: 1}},
    {$limit : 15}
  ]);
}

function getNetworkGraph(userId){

  class Edge{

    constructor(from, to){
      if(from)
        this.from = from.toLowerCase();
      if(to)
        this.to = to.toLowerCase();
      this.count = 1;
    }

    increaseCount(){
      this.count++;
    }

    key(){
      return this.from+'_'+this.to;
    }

    toJson(){
      return {from: this.from, to: this.to, count: this.count};
    }
  }

  class Node{

    constructor(email, name){
      if(email)
        this.email = email.toLowerCase();
      this.name = name;
    }

    key(){
      return this.email;
    }

    toJson(){
      return {email: this.email, name: this.name};
    }
  }

  /** Not implemented as set due the fact that the
   *  compare for objects is not implemented in es6 */
  const edges = new Map();
  const nodes = new Map();

  return new Promise((resolve, reject) => {
    Email.find({user: ObjectId(userId)}, {from: 1, to: 1}).lean()
      .then((emails)=> {
        emails.forEach((email)=> {
          if(email.from != null)
            email.from.forEach((from)=> {
              if(email.to != null)
                email.to.forEach((to)=> {
                  let edge = new Edge(from.address, to.address);
                  if (edges.has(edge.key())) {
                    edge = edges.get(edge.key());
                    edge.increaseCount();
                  } else {
                    edges.set(edge.key(), edge);
                  }
                  let node = new Node(from.address, from.name);
                  if(!nodes.has(node.key()))
                    nodes.set(node.key(), node);
                  node = new Node(to.address, to.name);
                  if(!nodes.has(node.key()))
                    nodes.set(node.key(), node);
                });
            });
        });
        const g = {
          edges: [],
          nodes: []
        };
        edges.forEach((e)=> {
          g.edges.push(e.toJson());
        });
        nodes.forEach((n)=> {
          g.nodes.push(n.toJson());
        });
        resolve(g);
      }).catch((err)=>{
        reject(err);
      });
  });
}

function getActions(userId){

  return {
    all: undefined,
    needreply: undefined,
    noreply : undefined,
  }
}

function getLabels(userId){
  return Email.aggregate([
    {$match: {user: userId}},
    {$unwind: '$labels'},
    {$group: {_id: {label: '$labels'}, count: {$sum: 1}}},
    {$sort: {count: -1}},
    {$project: {_id: 0, label: '$_id.label', count: 1}}
  ]);
}

function getConversations(userId){
  return Email.aggregate([
    {$match: {user: userId}},
    {$group: {_id: {thrid: '$thrid'}, nrmsg: {$sum: 1}}},
    {$group: {_id: {nrmsg: '$nrmsg'}, nrthr: {$sum: 1}}},
    {$project: {_id: 0, nrmsg: '$_id.nrmsg', nrthr: 1}},
    {$sort: {nrmsg: -1}}
  ]);
}

//TODO remove
function testNer(){
  Email.find({}).then((emails)=>{
    emails.forEach((email)=>{
      if(email.text != undefined){
        email.plainText = email.text;
      }else if(email.html != undefined){
        email.plainText = striptags(email.html);
      }
      console.log(email.flags);
      console.log(email.labels);
      console.log('#############');

    });
    console.log(emails.length);
  });
}

function getTimeline(req, res){
  let userId = req.user._id;
  const s = {};
  console.log(userId);
  getMonthlyPunchCard(userId)
    .then((m) => {
      s.monthly = m;
      return getDailyPunchCard(userId);
    })
    .then((d) => {
      s.daily = d;
      res.status(200).send(s);
    });
}

function getNetwork(req, res){
  let userId = req.user._id;
  const s = {};
  getTopFrom(userId)
    .then(from => {
      s.topfrom = from;
      return getTopTo(userId);
    })
    .then(to => {
      s.topto = to;
      return getTopCC(userId);
    })
    .then(cc => {
      s.topcc = cc;
      return getTopBCC(userId);
    })
    .then(bcc =>{
      s.topbcc = bcc;
      return getNetworkGraph(userId);
    })
    .then((g) => {
      s.graph = g;
      res.status(200).send(s);
    });
}

function getStructure(req, res){
  let userId = req.user._id;
  const s = {};
  getConversations(userId)
    .then((c)=>{
      s.converstations = c;
      return getLabels(userId);
    })
    .then((l)=>{
      s.labels = l;
      res.status(200).send(s);
    });
}

function getSummary(req, res) {

  let userId = null;
  const s = {
    punchcard: {},
    network: {},
    structural: {}
  };

  //TODO differentiate between send, received and all mails
  //TODO use id of current user?? assuming that the dashboard is embedded in WebApp??
  User.findOne()
    .then((user) => {
      userId = user._id;
      return getMonthlyPunchCard(userId);
    })
    .then((monthlySummary) => {
      s.punchcard.monthly = monthlySummary;
      return getDailyPunchCard(userId);
    })
    .then((dailySummary) => {
      s.punchcard.daily = dailySummary;
      return getTopFrom(userId)
    })
    .then((topSender) => {
      s.network.topsender = topSender;
      return getTopTo(userId)
    })
    .then((topReceiver) => {
      s.network.topreceiver = topReceiver;
      return getNetworkGraph(userId);
    })
    .then((graph) => {
      s.network.graph = graph;
      return getActions(userId);
    })
    .then((actions)=>{
      s.structural.actions = actions;
      return getConversations(userId)
    })
    .then((conversations)=>{
      s.structural.converstations = conversations;
      return getLabels(userId)
    })
    .then((labels)=>{
      s.structural.labels = labels;
      res.status(200).send(s);
    })
}

export default {
  getSummary,
  getTimeline,
  getNetwork,
  getStructure
};
<|endoftext|>


<commit_before>var mapnik = require('../');
var assert = require('assert');
var fs = require('fs');
var path = require('path');

describe('mapnik.Image ', function() {
    it('should throw with invalid usage', function() {
        // no 'new' keyword
        assert.throws(function() { mapnik.Image(1, 1); });

        // invalid args
        assert.throws(function() { new mapnik.Image(); });
        assert.throws(function() { new mapnik.Image(1); });
        assert.throws(function() { new mapnik.Image('foo'); });
        assert.throws(function() { new mapnik.Image('a', 'b', 'c'); });
    });

    it('should throw with filename lacking an extension', function() {
        var im = new mapnik.Image(256, 256);
        assert.throws(function() { im.save('foo'); });
    });

    it('should throw with invalid encoding format 1', function() {
        var im = new mapnik.Image(256, 256);
        assert.throws(function() { im.encodeSync('foo'); });
    });

    it('should throw with invalid encoding format 2', function() {
        var im = new mapnik.Image(256, 256);
        assert.throws(function() { im.save('foo','foo'); });
    });

    it('should throw with invalid binary read from buffer', function() {
        assert.throws(function() { new mapnik.Image.fromBytesSync(new Buffer(0)); });
        assert.throws(function() { new mapnik.Image.fromBytesSync(new Buffer(1024)); });
        var buffer = new Buffer('\x89\x50\x4E\x47\x0D\x0A\x1A\x0A' + Array(48).join('\0'), 'binary');
        assert.throws(function() { new mapnik.Image.fromBytesSync(buffer); });
        buffer = new Buffer('\x89\x50\x4E\x47\x0D\x0A\x1A\x0A', 'binary');
        assert.throws(function() { new mapnik.Image.fromBytesSync(buffer); });
    });

    it('should throw with invalid encoding format 3', function(done) {
        var im = new mapnik.Image(256, 256);
        im.encode('foo',function(err) {
            assert.ok(err);
            done();
        })
    });

    it('should be initialized properly', function() {
        var im = new mapnik.Image(256, 256);
        assert.ok(im instanceof mapnik.Image);

        assert.equal(im.width(), 256);
        assert.equal(im.height(), 256);
        var v = im.view(0, 0, 256, 256);
        assert.ok(v instanceof mapnik.ImageView);
        assert.equal(v.width(), 256);
        assert.equal(v.height(), 256);
        assert.equal(im.encodeSync().length, v.encodeSync().length);

        im.save('./test/tmp/image.png');

        var im2 = new mapnik.Image.open('./test/tmp/image.png');
        assert.ok(im2 instanceof mapnik.Image);

        assert.equal(im2.width(), 256);
        assert.equal(im2.height(), 256);

        assert.equal(im.encodeSync().length, im2.encodeSync().length);
    });

    it('should be able to open via byte stream', function(done) {
        var im = new mapnik.Image(256, 256);
        // png
        var filename = './test/tmp/image2.png'
        im.save(filename);
        var buffer = fs.readFileSync(filename);
        var im2 = new mapnik.Image.fromBytesSync(buffer);
        assert.ok(im2 instanceof mapnik.Image);
        assert.equal(im2.width(), 256);
        assert.equal(im2.height(), 256);
        assert.equal(im.encodeSync().length, im2.encodeSync().length);
        // jpeg
        var filename2 = './test/tmp/image2.jpeg'
        im.save(filename2);
        var buffer = fs.readFileSync(filename);
        var im3 = new mapnik.Image.fromBytesSync(buffer);
        assert.ok(im3 instanceof mapnik.Image);
        assert.equal(im3.width(), 256);
        assert.equal(im3.height(), 256);
        assert.equal(im.encodeSync().length, im3.encodeSync().length);
        done();
    });

    it('should be initialized properly via async constructors', function(done) {
        var im = new mapnik.Image(256, 256);
        im.save('./test/tmp/image3.png');

        mapnik.Image.open('./test/tmp/image3.png',function(err,im2) {
            if (err) throw err;
            assert.ok(im2 instanceof mapnik.Image);
            assert.equal(im2.width(), 256);
            assert.equal(im2.height(), 256);
            assert.equal(im.encodeSync().length, im2.encodeSync().length);
            mapnik.Image.fromBytes(im.encodeSync(),function(err,im3) {
                if (err) throw err;
                assert.ok(im3 instanceof mapnik.Image);
                assert.equal(im3.width(), 256);
                assert.equal(im3.height(), 256);
                assert.equal(im.encodeSync().length, im3.encodeSync().length);
                done();
            });
        });
    });

    it('should not be painted after rendering', function(done) {
        var im_blank = new mapnik.Image(4, 4);
        assert.equal(im_blank.painted(), false);
        assert.equal(im_blank.background, undefined);

        var m = new mapnik.Map(4, 4);

        m.render(im_blank, {},function(err,im_blank) {
            assert.equal(im_blank.painted(), false);
            assert.equal(im_blank.background, undefined);
            done();
        });
    });

    it('should have background set after rendering', function(done) {
        var im_blank2 = new mapnik.Image(4, 4);
        assert.equal(im_blank2.painted(), false);
        assert.equal(im_blank2.background, undefined);

        var m2 = new mapnik.Map(4, 4);

        m2.background = new mapnik.Color('green');
        m2.render(im_blank2, {},function(err,im_blank2) {
            assert.equal(im_blank2.painted(), false);
            assert.ok(im_blank2.background);
            done();
        });
    });

    it('should be painted after rendering', function(done) {

        var im_blank3 = new mapnik.Image(4, 4);
        assert.equal(im_blank3.painted(), false);
        assert.equal(im_blank3.background, undefined);

        var m3 = new mapnik.Map(4, 4);
        var s = '<Map>';
        s += '<Style name="points">';
        s += ' <Rule>';
        s += '  <PointSymbolizer />';
        s += ' </Rule>';
        s += '</Style>';
        s += '</Map>';
        m3.fromStringSync(s);

        var mem_datasource = new mapnik.MemoryDatasource({'extent': '-180,-90,180,90'});
        mem_datasource.add({ 'x': 0, 'y': 0 });
        mem_datasource.add({ 'x': 1, 'y': 1 });
        mem_datasource.add({ 'x': 2, 'y': 2 });
        mem_datasource.add({ 'x': 3, 'y': 3 });
        var l = new mapnik.Layer('test');
        l.srs = m3.srs;
        l.styles = ['points'];
        l.datasource = mem_datasource;
        m3.add_layer(l);
        m3.zoomAll();
        m3.render(im_blank3, {},function(err,im_blank3) {
            assert.equal(im_blank3.painted(), true);
            assert.equal(im_blank3.background, undefined);
            done();
        });
    });

    it('should support setting the alpha channel based on the amount of gray', function() {
        var gray = new mapnik.Image(256, 256);
        gray.background = new mapnik.Color('white');
        gray.setGrayScaleToAlpha();
        var gray_view = gray.view(0, 0, gray.width(), gray.height());
        assert.equal(gray_view.isSolidSync(), true);
        var pixel = gray.getPixel(0, 0);
        assert.equal(pixel.r, 255);
        assert.equal(pixel.g, 255);
        assert.equal(pixel.b, 255);
        assert.equal(pixel.a, 255);

        gray.background = new mapnik.Color('black');
        gray.setGrayScaleToAlpha();
        var pixel2 = gray.getPixel(0, 0);
        assert.equal(pixel2.r, 255);
        assert.equal(pixel2.g, 255);
        assert.equal(pixel2.b, 255);
        assert.equal(pixel2.a, 0);

        gray.setGrayScaleToAlpha(new mapnik.Color('green'));
        var pixel3 = gray.getPixel(0, 0);
        assert.equal(pixel3.r, 0);
        assert.equal(pixel3.g, 128);
        assert.equal(pixel3.b, 0);
        assert.equal(pixel3.a, 255);
    });

    it('should support setting an individual pixel', function() {
        var gray = new mapnik.Image(256, 256);
        gray.setPixel(0,0,new mapnik.Color('white'));
        var pixel = gray.getPixel(0,0);
        assert.equal(pixel.r, 255);
        assert.equal(pixel.g, 255);
        assert.equal(pixel.b, 255);
        assert.equal(pixel.a, 255);
    });

    it('should support comparing images', function() {
        // if width/height don't match should throw
        assert.throws(function() { new mapnik.Image(256, 256).compare(new mapnik.Image(256, 255)) });
        var one = new mapnik.Image(256, 256);
        // two blank images should exactly match
        assert.equal(one.compare(new mapnik.Image(256, 256)),0);
        // here we set one pixel different
        one.setPixel(0,0,new mapnik.Color('white'));
        assert.equal(one.compare(new mapnik.Image(256, 256)),1);
        // here we set all pixels to be different
        one.background = new mapnik.Color('white');
        assert.equal(one.compare(new mapnik.Image(256, 256)),one.width()*one.height());
        // now lets test comparing just rgb and not alpha
        var two = new mapnik.Image(256, 256);
        // white image but fully alpha
        two.background = new mapnik.Color('rgba(255,255,255,0)');
        // if we consider alpha all pixels should be different
        assert.equal(one.compare(two),one.width()*one.height());
        // but ignoring alpha all pixels should pass as the same
        assert.equal(one.compare(two,{alpha:false}),0);
        // now lets test the threshold option
        // a minorly different color should trigger differences
        var blank = new mapnik.Image(256, 256);
        var blank2 = new mapnik.Image(256, 256);
        blank2.setPixel(0,0,new mapnik.Color('rgba(16,16,16,0)'));
        // should pass because threshold is 16 by default
        assert.equal(blank.compare(blank2),0);
        // with 15 or below threshold should fail
        assert.equal(blank.compare(blank2,{threshold:15}),1);
    });

    it('should be able to open and save jpeg', function(done) {
        var im = new mapnik.Image(10,10);
        im.background = new mapnik.Color('green');
        var filename = './test/data/images/10x10.png';
        // sync open
        assert.equal(0,im.compare(new mapnik.Image.open(filename)));
        // sync fromBytes
        assert.equal(0,im.compare(new mapnik.Image.fromBytesSync(im.encodeSync("jpeg"))));
        // async open
        mapnik.Image.open(filename,function(err,im2) {
            if (err) throw err;
            assert.equal(0,im.compare(im2));
            // async fromBytes
            mapnik.Image.fromBytes(im.encodeSync(),function(err,im3) {
                if (err) throw err;
                assert.equal(0,im.compare(im3));
                done();
            });
        });
    });

    it('should be able to open and save tiff', function(done) {
        var im = new mapnik.Image(10,10);
        im.background = new mapnik.Color('green');
        var filename = './test/data/images/10x10.tiff';
        // sync open
        assert.equal(0,im.compare(new mapnik.Image.open(filename)));
        // sync fromBytes
        assert.equal(0,im.compare(new mapnik.Image.fromBytesSync(im.encodeSync("tiff"))));
        // async open
        mapnik.Image.open(filename,function(err,im2) {
            if (err) throw err;
            assert.equal(0,im.compare(im2));
            // async fromBytes
            mapnik.Image.fromBytes(im.encodeSync(),function(err,im3) {
                if (err) throw err;
                assert.equal(0,im.compare(im3));
                done();
            });
        });
    });

    if (mapnik.versions.mapnik_number >= 200300) {
        it('should be able to open and save webp', function(done) {
            var im = new mapnik.Image(10,10);
            im.background = new mapnik.Color('green');
            var filename = './test/data/images/10x10.webp';
            // sync open
            assert.equal(0,im.compare(new mapnik.Image.open(filename)));
            // sync fromBytes
            assert.equal(0,im.compare(new mapnik.Image.fromBytesSync(im.encodeSync("webp"))));
            // async open
            mapnik.Image.open(filename,function(err,im2) {
                if (err) throw err;
                assert.equal(0,im.compare(im2));
                // async fromBytes
                mapnik.Image.fromBytes(im.encodeSync(),function(err,im3) {
                    if (err) throw err;
                    assert.equal(0,im.compare(im3));
                    done();
                });
            });
        });
    }

});
<commit_msg>actually use jpeg in jpeg test<commit_after>var mapnik = require('../');
var assert = require('assert');
var fs = require('fs');
var path = require('path');

describe('mapnik.Image ', function() {
    it('should throw with invalid usage', function() {
        // no 'new' keyword
        assert.throws(function() { mapnik.Image(1, 1); });

        // invalid args
        assert.throws(function() { new mapnik.Image(); });
        assert.throws(function() { new mapnik.Image(1); });
        assert.throws(function() { new mapnik.Image('foo'); });
        assert.throws(function() { new mapnik.Image('a', 'b', 'c'); });
    });

    it('should throw with filename lacking an extension', function() {
        var im = new mapnik.Image(256, 256);
        assert.throws(function() { im.save('foo'); });
    });

    it('should throw with invalid encoding format 1', function() {
        var im = new mapnik.Image(256, 256);
        assert.throws(function() { im.encodeSync('foo'); });
    });

    it('should throw with invalid encoding format 2', function() {
        var im = new mapnik.Image(256, 256);
        assert.throws(function() { im.save('foo','foo'); });
    });

    it('should throw with invalid binary read from buffer', function() {
        assert.throws(function() { new mapnik.Image.fromBytesSync(new Buffer(0)); });
        assert.throws(function() { new mapnik.Image.fromBytesSync(new Buffer(1024)); });
        var buffer = new Buffer('\x89\x50\x4E\x47\x0D\x0A\x1A\x0A' + Array(48).join('\0'), 'binary');
        assert.throws(function() { new mapnik.Image.fromBytesSync(buffer); });
        buffer = new Buffer('\x89\x50\x4E\x47\x0D\x0A\x1A\x0A', 'binary');
        assert.throws(function() { new mapnik.Image.fromBytesSync(buffer); });
    });

    it('should throw with invalid encoding format 3', function(done) {
        var im = new mapnik.Image(256, 256);
        im.encode('foo',function(err) {
            assert.ok(err);
            done();
        })
    });

    it('should be initialized properly', function() {
        var im = new mapnik.Image(256, 256);
        assert.ok(im instanceof mapnik.Image);

        assert.equal(im.width(), 256);
        assert.equal(im.height(), 256);
        var v = im.view(0, 0, 256, 256);
        assert.ok(v instanceof mapnik.ImageView);
        assert.equal(v.width(), 256);
        assert.equal(v.height(), 256);
        assert.equal(im.encodeSync().length, v.encodeSync().length);

        im.save('./test/tmp/image.png');

        var im2 = new mapnik.Image.open('./test/tmp/image.png');
        assert.ok(im2 instanceof mapnik.Image);

        assert.equal(im2.width(), 256);
        assert.equal(im2.height(), 256);

        assert.equal(im.encodeSync().length, im2.encodeSync().length);
    });

    it('should be able to open via byte stream', function(done) {
        var im = new mapnik.Image(256, 256);
        // png
        var filename = './test/tmp/image2.png'
        im.save(filename);
        var buffer = fs.readFileSync(filename);
        var im2 = new mapnik.Image.fromBytesSync(buffer);
        assert.ok(im2 instanceof mapnik.Image);
        assert.equal(im2.width(), 256);
        assert.equal(im2.height(), 256);
        assert.equal(im.encodeSync().length, im2.encodeSync().length);
        // jpeg
        var filename2 = './test/tmp/image2.jpeg'
        im.save(filename2);
        var buffer = fs.readFileSync(filename);
        var im3 = new mapnik.Image.fromBytesSync(buffer);
        assert.ok(im3 instanceof mapnik.Image);
        assert.equal(im3.width(), 256);
        assert.equal(im3.height(), 256);
        assert.equal(im.encodeSync().length, im3.encodeSync().length);
        done();
    });

    it('should be initialized properly via async constructors', function(done) {
        var im = new mapnik.Image(256, 256);
        im.save('./test/tmp/image3.png');

        mapnik.Image.open('./test/tmp/image3.png',function(err,im2) {
            if (err) throw err;
            assert.ok(im2 instanceof mapnik.Image);
            assert.equal(im2.width(), 256);
            assert.equal(im2.height(), 256);
            assert.equal(im.encodeSync().length, im2.encodeSync().length);
            mapnik.Image.fromBytes(im.encodeSync(),function(err,im3) {
                if (err) throw err;
                assert.ok(im3 instanceof mapnik.Image);
                assert.equal(im3.width(), 256);
                assert.equal(im3.height(), 256);
                assert.equal(im.encodeSync().length, im3.encodeSync().length);
                done();
            });
        });
    });

    it('should not be painted after rendering', function(done) {
        var im_blank = new mapnik.Image(4, 4);
        assert.equal(im_blank.painted(), false);
        assert.equal(im_blank.background, undefined);

        var m = new mapnik.Map(4, 4);

        m.render(im_blank, {},function(err,im_blank) {
            assert.equal(im_blank.painted(), false);
            assert.equal(im_blank.background, undefined);
            done();
        });
    });

    it('should have background set after rendering', function(done) {
        var im_blank2 = new mapnik.Image(4, 4);
        assert.equal(im_blank2.painted(), false);
        assert.equal(im_blank2.background, undefined);

        var m2 = new mapnik.Map(4, 4);

        m2.background = new mapnik.Color('green');
        m2.render(im_blank2, {},function(err,im_blank2) {
            assert.equal(im_blank2.painted(), false);
            assert.ok(im_blank2.background);
            done();
        });
    });

    it('should be painted after rendering', function(done) {

        var im_blank3 = new mapnik.Image(4, 4);
        assert.equal(im_blank3.painted(), false);
        assert.equal(im_blank3.background, undefined);

        var m3 = new mapnik.Map(4, 4);
        var s = '<Map>';
        s += '<Style name="points">';
        s += ' <Rule>';
        s += '  <PointSymbolizer />';
        s += ' </Rule>';
        s += '</Style>';
        s += '</Map>';
        m3.fromStringSync(s);

        var mem_datasource = new mapnik.MemoryDatasource({'extent': '-180,-90,180,90'});
        mem_datasource.add({ 'x': 0, 'y': 0 });
        mem_datasource.add({ 'x': 1, 'y': 1 });
        mem_datasource.add({ 'x': 2, 'y': 2 });
        mem_datasource.add({ 'x': 3, 'y': 3 });
        var l = new mapnik.Layer('test');
        l.srs = m3.srs;
        l.styles = ['points'];
        l.datasource = mem_datasource;
        m3.add_layer(l);
        m3.zoomAll();
        m3.render(im_blank3, {},function(err,im_blank3) {
            assert.equal(im_blank3.painted(), true);
            assert.equal(im_blank3.background, undefined);
            done();
        });
    });

    it('should support setting the alpha channel based on the amount of gray', function() {
        var gray = new mapnik.Image(256, 256);
        gray.background = new mapnik.Color('white');
        gray.setGrayScaleToAlpha();
        var gray_view = gray.view(0, 0, gray.width(), gray.height());
        assert.equal(gray_view.isSolidSync(), true);
        var pixel = gray.getPixel(0, 0);
        assert.equal(pixel.r, 255);
        assert.equal(pixel.g, 255);
        assert.equal(pixel.b, 255);
        assert.equal(pixel.a, 255);

        gray.background = new mapnik.Color('black');
        gray.setGrayScaleToAlpha();
        var pixel2 = gray.getPixel(0, 0);
        assert.equal(pixel2.r, 255);
        assert.equal(pixel2.g, 255);
        assert.equal(pixel2.b, 255);
        assert.equal(pixel2.a, 0);

        gray.setGrayScaleToAlpha(new mapnik.Color('green'));
        var pixel3 = gray.getPixel(0, 0);
        assert.equal(pixel3.r, 0);
        assert.equal(pixel3.g, 128);
        assert.equal(pixel3.b, 0);
        assert.equal(pixel3.a, 255);
    });

    it('should support setting an individual pixel', function() {
        var gray = new mapnik.Image(256, 256);
        gray.setPixel(0,0,new mapnik.Color('white'));
        var pixel = gray.getPixel(0,0);
        assert.equal(pixel.r, 255);
        assert.equal(pixel.g, 255);
        assert.equal(pixel.b, 255);
        assert.equal(pixel.a, 255);
    });

    it('should support comparing images', function() {
        // if width/height don't match should throw
        assert.throws(function() { new mapnik.Image(256, 256).compare(new mapnik.Image(256, 255)) });
        var one = new mapnik.Image(256, 256);
        // two blank images should exactly match
        assert.equal(one.compare(new mapnik.Image(256, 256)),0);
        // here we set one pixel different
        one.setPixel(0,0,new mapnik.Color('white'));
        assert.equal(one.compare(new mapnik.Image(256, 256)),1);
        // here we set all pixels to be different
        one.background = new mapnik.Color('white');
        assert.equal(one.compare(new mapnik.Image(256, 256)),one.width()*one.height());
        // now lets test comparing just rgb and not alpha
        var two = new mapnik.Image(256, 256);
        // white image but fully alpha
        two.background = new mapnik.Color('rgba(255,255,255,0)');
        // if we consider alpha all pixels should be different
        assert.equal(one.compare(two),one.width()*one.height());
        // but ignoring alpha all pixels should pass as the same
        assert.equal(one.compare(two,{alpha:false}),0);
        // now lets test the threshold option
        // a minorly different color should trigger differences
        var blank = new mapnik.Image(256, 256);
        var blank2 = new mapnik.Image(256, 256);
        blank2.setPixel(0,0,new mapnik.Color('rgba(16,16,16,0)'));
        // should pass because threshold is 16 by default
        assert.equal(blank.compare(blank2),0);
        // with 15 or below threshold should fail
        assert.equal(blank.compare(blank2,{threshold:15}),1);
    });

    it('should be able to open and save jpeg', function(done) {
        var im = new mapnik.Image(10,10);
        im.background = new mapnik.Color('green');
        var filename = './test/data/images/10x10.jpeg';
        // sync open
        assert.equal(0,im.compare(new mapnik.Image.open(filename)));
        // sync fromBytes
        assert.equal(0,im.compare(new mapnik.Image.fromBytesSync(im.encodeSync("jpeg"))));
        // async open
        mapnik.Image.open(filename,function(err,im2) {
            if (err) throw err;
            assert.equal(0,im.compare(im2));
            // async fromBytes
            mapnik.Image.fromBytes(im.encodeSync(),function(err,im3) {
                if (err) throw err;
                assert.equal(0,im.compare(im3));
                done();
            });
        });
    });

    it('should be able to open and save tiff', function(done) {
        var im = new mapnik.Image(10,10);
        im.background = new mapnik.Color('green');
        var filename = './test/data/images/10x10.tiff';
        // sync open
        assert.equal(0,im.compare(new mapnik.Image.open(filename)));
        // sync fromBytes
        assert.equal(0,im.compare(new mapnik.Image.fromBytesSync(im.encodeSync("tiff"))));
        // async open
        mapnik.Image.open(filename,function(err,im2) {
            if (err) throw err;
            assert.equal(0,im.compare(im2));
            // async fromBytes
            mapnik.Image.fromBytes(im.encodeSync(),function(err,im3) {
                if (err) throw err;
                assert.equal(0,im.compare(im3));
                done();
            });
        });
    });

    if (mapnik.versions.mapnik_number >= 200300) {
        it('should be able to open and save webp', function(done) {
            var im = new mapnik.Image(10,10);
            im.background = new mapnik.Color('green');
            var filename = './test/data/images/10x10.webp';
            // sync open
            assert.equal(0,im.compare(new mapnik.Image.open(filename)));
            // sync fromBytes
            assert.equal(0,im.compare(new mapnik.Image.fromBytesSync(im.encodeSync("webp"))));
            // async open
            mapnik.Image.open(filename,function(err,im2) {
                if (err) throw err;
                assert.equal(0,im.compare(im2));
                // async fromBytes
                mapnik.Image.fromBytes(im.encodeSync(),function(err,im3) {
                    if (err) throw err;
                    assert.equal(0,im.compare(im3));
                    done();
                });
            });
        });
    }

});
<|endoftext|>


<commit_before>// Copyright 2019, University of Colorado Boulder

/**
 * A PhET-iO class that encapsulates a PhetioObject that is not created during sim startup to provide PhET-iO API
 * validation, API communication (like to view in studio before creation), and to support PhET-iO state if applicable.
 *
 * Constructing a PhetioSingleton effectively creates the singleton where the wrapped instance can be of any type.
 *
 * Clients should use mySingleton.getInstance() instead of storing the instance value itself.
 *
 * @author Michael Kauzmann (PhET Interactive Simulations)
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Chris Klusendorf (PhET Interactive Simulations)
 */
define( require => {
  'use strict';

  // modules
  const merge = require( 'PHET_CORE/merge' );
  const PhetioDynamicUtil = require( 'TANDEM/PhetioDynamicUtil' );
  const PhetioObject = require( 'TANDEM/PhetioObject' );
  const Tandem = require( 'TANDEM/Tandem' );
  const tandemNamespace = require( 'TANDEM/tandemNamespace' );

  class PhetioSingleton extends PhetioObject {

    /**
     * @param {function(tandem, ...):PhetioObject} createInstance - function that creates a group member
     * @param {Array.<*>|function.<[],Array.<*>>} defaultArguments arguments passed to create during API harvest
     * @param {Object} [options] - describe the Singleton itself
     */
    constructor( createInstance, defaultArguments, options ) {

      assert && assert( typeof createInstance === 'function', 'createInstance should be a function' );
      assert && assert( Array.isArray( defaultArguments ) || typeof defaultArguments === 'function', 'defaultArguments should be an array or a function' );
      if ( Array.isArray( defaultArguments ) ) {
        assert && assert( createInstance.length === defaultArguments.length + 1, 'mismatched number of arguments' ); // createInstance also takes tandem
      }

      options = merge( {
        phetioState: false,
        tandem: Tandem.required
      }, options );

      assert && assert( !!options.phetioType, 'phetioType must be supplied' );
      assert && assert( !!options.phetioType.parameterTypes, 'PhetioSingletonIO must supply its parameter types' );
      assert && assert( options.phetioType.parameterTypes.length === 1, 'PhetioSingletonIO must have exactly one parameter type' );
      assert && assert( !!options.phetioType.parameterTypes[ 0 ], 'PhetioSingletonIO parameterType must be truthy' );
      assert && assert( options.tandem.name.endsWith( 'Singleton' ), 'PhetioSingleton tandems should end with Singleton suffix' );

      super( options );

      // @private
      this.createInstance = createInstance;

      // @public (read-only)
      this.instance = null;

      // @public (read-only) {PhetioObject|null} Can be used as an argument to create other prototypes
      this.instancePrototype = PhetioDynamicUtil.createPrototype( this.tandem, createInstance, defaultArguments );
    }

    /**
     * Dispose the underlying instance.  Called by the PhetioStateEngine so the singleton can be recreated with the
     * correct state.
     * @public (phet-io)
     */
    disposeInstance() {
      this.instance.dispose();
      this.instance = null;
    }

    /**
     * Creates the instance if it has not been created yet, and returns it.
     * @param {Array.<*>} [argsForCreateFunction]
     * @returns {Object}
     * @public
     */
    getInstance( ...argsForCreateFunction ) {
      if ( !this.instance ) {
        this.create( ...argsForCreateFunction );
      }
      return this.instance;
    }

    /**
     * Primarily for internal use, clients should usually use getInstance.
     * @param {Array.<*>} [argsForCreateFunction]
     * @returns {Object}
     * @public (phet-io)
     */
    create( ...argsForCreateFunction ) {

      // create with default state and substructure, details will need to be set by setter methods.
      this.instance = PhetioDynamicUtil.createDynamicPhetioObject(
        this.tandem,
        'instance',
        this.createInstance,
        argsForCreateFunction,
        this.phetioType.parameterTypes[ 0 ].validator
      );

      return this.instance;
    }
  }

  return tandemNamespace.register( 'PhetioSingleton', PhetioSingleton );
} );<commit_msg>improve doc for defaultArguments #130<commit_after>// Copyright 2019, University of Colorado Boulder

/**
 * A PhET-iO class that encapsulates a PhetioObject that is not created during sim startup to provide PhET-iO API
 * validation, API communication (like to view in studio before creation), and to support PhET-iO state if applicable.
 *
 * Constructing a PhetioSingleton effectively creates the singleton where the wrapped instance can be of any type.
 *
 * Clients should use mySingleton.getInstance() instead of storing the instance value itself.
 *
 * @author Michael Kauzmann (PhET Interactive Simulations)
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Chris Klusendorf (PhET Interactive Simulations)
 */
define( require => {
  'use strict';

  // modules
  const merge = require( 'PHET_CORE/merge' );
  const PhetioDynamicUtil = require( 'TANDEM/PhetioDynamicUtil' );
  const PhetioObject = require( 'TANDEM/PhetioObject' );
  const Tandem = require( 'TANDEM/Tandem' );
  const tandemNamespace = require( 'TANDEM/tandemNamespace' );

  class PhetioSingleton extends PhetioObject {

    /**
     * @param {function(tandem, ...):PhetioObject} createInstance - function that creates a group member
     * @param {Array.<*>|function.<[],Array.<*>>} defaultArguments - arguments passed to createInstance during API baseline generation
     * @param {Object} [options] - describe the Singleton itself
     */
    constructor( createInstance, defaultArguments, options ) {

      assert && assert( typeof createInstance === 'function', 'createInstance should be a function' );
      assert && assert( Array.isArray( defaultArguments ) || typeof defaultArguments === 'function', 'defaultArguments should be an array or a function' );
      if ( Array.isArray( defaultArguments ) ) {
        assert && assert( createInstance.length === defaultArguments.length + 1, 'mismatched number of arguments' ); // createInstance also takes tandem
      }

      options = merge( {
        phetioState: false,
        tandem: Tandem.required
      }, options );

      assert && assert( !!options.phetioType, 'phetioType must be supplied' );
      assert && assert( !!options.phetioType.parameterTypes, 'PhetioSingletonIO must supply its parameter types' );
      assert && assert( options.phetioType.parameterTypes.length === 1, 'PhetioSingletonIO must have exactly one parameter type' );
      assert && assert( !!options.phetioType.parameterTypes[ 0 ], 'PhetioSingletonIO parameterType must be truthy' );
      assert && assert( options.tandem.name.endsWith( 'Singleton' ), 'PhetioSingleton tandems should end with Singleton suffix' );

      super( options );

      // @private
      this.createInstance = createInstance;

      // @public (read-only)
      this.instance = null;

      // @public (read-only) {PhetioObject|null} Can be used as an argument to create other prototypes
      this.instancePrototype = PhetioDynamicUtil.createPrototype( this.tandem, createInstance, defaultArguments );
    }

    /**
     * Dispose the underlying instance.  Called by the PhetioStateEngine so the singleton can be recreated with the
     * correct state.
     * @public (phet-io)
     */
    disposeInstance() {
      this.instance.dispose();
      this.instance = null;
    }

    /**
     * Creates the instance if it has not been created yet, and returns it.
     * @param {Array.<*>} [argsForCreateFunction]
     * @returns {Object}
     * @public
     */
    getInstance( ...argsForCreateFunction ) {
      if ( !this.instance ) {
        this.create( ...argsForCreateFunction );
      }
      return this.instance;
    }

    /**
     * Primarily for internal use, clients should usually use getInstance.
     * @param {Array.<*>} [argsForCreateFunction]
     * @returns {Object}
     * @public (phet-io)
     */
    create( ...argsForCreateFunction ) {

      // create with default state and substructure, details will need to be set by setter methods.
      this.instance = PhetioDynamicUtil.createDynamicPhetioObject(
        this.tandem,
        'instance',
        this.createInstance,
        argsForCreateFunction,
        this.phetioType.parameterTypes[ 0 ].validator
      );

      return this.instance;
    }
  }

  return tandemNamespace.register( 'PhetioSingleton', PhetioSingleton );
} );<|endoftext|>


<commit_before>import {
    readFileSync
} from 'fs';
import loader from '../src'

describe('enhanced-properties-loader', () => {
    const makeRequest = (resourcePath, callback, options = {}, query = null) => {
        loader.call({
            async: () => callback,
            cacheable: () => {},
            resourcePath,
            options,
            query: query ? `?${JSON.stringify(query)}` : ''
        }, readFileSync(resourcePath, { encoding: 'utf8' }));
    };

    it('should load `*.properties` with `namespaces`', done => {
        makeRequest('./test/fixtures/index.properties', (err, properties) => {
            expect(err).toBe(null);
            expect(properties).toEqual({
                foo: 1,
                bar: {
                    bar1: true
                }
            });

            done();
        });
    });

    it('should load `*.properties` without `namespaces`', done => {
        makeRequest('./test/fixtures/index.properties', (err, properties) => {
            expect(err).toBe(null);
            expect(properties).toEqual({
                foo: 1,
                'bar.bar1': true
            });

            done();
        }, {}, {
            namespaces: false
        });
    });
});
<commit_msg>tests: fix tests<commit_after>import {
    readFileSync
} from 'fs';
import loader from '../src'

describe('enhanced-properties-loader', () => {
    const makeRequest = (resourcePath, callback, options = {}, query = null) => {
        loader.call({
            async: () => callback,
            cacheable: () => {},
            options,
            query: query ? `?${JSON.stringify(query)}` : ''
        }, readFileSync(resourcePath, { encoding: 'utf8' }));
    };

    it('should load `*.properties` with `namespaces`', done => {
        makeRequest('./test/fixtures/index.properties', (err, properties) => {
            expect(err).toBe(null);
            expect(properties).toEqual({
                foo: 1,
                bar: {
                    bar1: true
                }
            });

            done();
        });
    });

    it('should load `*.properties` without `namespaces`', done => {
        makeRequest('./test/fixtures/index.properties', (err, properties) => {
            expect(err).toBe(null);
            expect(properties).toEqual({
                foo: 1,
                'bar.bar1': true
            });

            done();
        }, {}, {
            namespaces: false
        });
    });
});
<|endoftext|>


<commit_before>define(["dojo/Evented", "dojo/_base/declare", "dojo/_base/lang", "dojo/has", "esri/kernel",
    "dijit/_WidgetBase", "dijit/_TemplatedMixin", "dojo/on",
    "dojo/text!application/dijit/templates/TableOfContents.html",
    "dojo/dom-class", "dojo/dom-attr", "dojo/dom-style", "dojo/dom-construct", "dojo/_base/event",
    "dojo/_base/array",
    "esri/symbols/TextSymbol", "esri/renderers/SimpleRenderer", "esri/layers/LabelLayer"
    ], function (
        Evented, declare, lang, has, esriNS,
        _WidgetBase, _TemplatedMixin, on,
        dijitTemplate,
        domClass, domAttr, domStyle, domConstruct, event,
        array,
        TextSymbol, SimpleRenderer, LabelLayer
    ) {
    var Widget = declare("esri.dijit.TableOfContents", [_WidgetBase, _TemplatedMixin, Evented], {
        templateString: dijitTemplate,
        // defaults
        options: {
            theme: "TableOfContents",
            map: null,
            layers: null,
            visible: true
        },

        // lifecycle: 1
        constructor: function (options, srcRefNode) {
            // mix in settings and defaults
            var defaults = lang.mixin({}, this.options, options);
            // widget node
            this.domNode = srcRefNode;
            // properties
            this.set("map", defaults.map);
            this.set("layers", defaults.layers);
            this.set("theme", defaults.theme);
            this.set("visible", defaults.visible);
            // listeners
            this.watch("theme", this._updateThemeWatch);
            this.watch("visible", this._visible);
            this.watch("layers", this._refreshLayers);
            this.watch("map", this.refresh);
            // classes
            this.css = {
                container: "toc-container",
                layer: "toc-layer",
                firstLayer: "toc-first-layer",
                title: "toc-title",
                titleContainer: "toc-title-container",
                content: "toc-content",
                titleCheckbox: "checkbox",
                checkboxCheck: "icon-check-1",
                titleText: "checkbox",
                accountText: "toc-account",
                visible: "toc-visible",
                settingsIcon: "icon-cog",
                settings: "toc-settings",
                actions: "toc-actions",
                account: "toc-account",
                clear: "clear"
            };
        },

        // start widget. called by user
        startup: function () {
            // map not defined
            if (!this.map) {
                this.destroy();
                console.log("TableOfContents::map required");
            }
            // when map is loaded
            if (this.map.loaded) {
                this._init();
            } else {
                on.once(this.map, "load", lang.hitch(this, function () {
                    this._init();
                }));
            }
        },

        // connections/subscriptions will be cleaned up during the destroy() lifecycle phase
        destroy: function () {
            this._removeEvents();
            this.inherited(arguments);
        },
        /* ---------------- */
        /* Public Events */
        /* ---------------- */
        // load
        // toggle
        // expand
        // collapse

        /* ---------------- */
        /* Public Functions */
        /* ---------------- */

        show: function () {
            this.set("visible", true);
        },

        hide: function () {
            this.set("visible", false);
        },

        refresh: function () {
            this._createList();
        },

        /* ----------------- */
        /* Private Functions */
        /* ----------------- */

        _createList: function () {
            var layers = this.get("layers");
            this._nodes = [];
            // kill events
            this._removeEvents();
            // clear node
            this._layersNode.innerHTML = "";
            domAttr.set(this._layersNode, "role", "list");
            // if we got layers
            if (layers && layers.length) {

                for (var i = 0; i < layers.length; i++) {
                    var layer = layers[i];

                    // ceckbox class
                    var titleCheckBoxClass = this.css.titleCheckbox;
                    // layer class
                    var layerClass = this.css.layer;
                    // first layer
                    if (i === (layers.length - 1)) {
                        layerClass += " ";
                        layerClass += this.css.firstLayer;
                    }
                    if (layer.visibility) {
                        layerClass += " ";
                        layerClass += this.css.visible;
                        titleCheckBoxClass += " ";
                        titleCheckBoxClass += this.css.checkboxCheck;
                    }

                    // layer node
                    var layerDiv = domConstruct.create("div", {
                        className: layerClass,
                        role: "listitem",
                    });
                    domConstruct.place(layerDiv, this._layersNode, "first");

                    // title of layer
                    var titleDiv = domConstruct.create("div", {
                        className: this.css.title,
                    }, layerDiv);

                    // title container
                    var titleContainerDiv = domConstruct.create("div", {
                        className: this.css.titleContainer,
                        tabindex: -1,
                    }, titleDiv);

                    titleCheckbox = domConstruct.create("input",
                    {
                        id: "layer_ck_"+i,
                        className: titleCheckBoxClass, //this.css.titleCheckbox,
                        type: "checkbox",
                        tabindex: 0,
                        checked: layer.visibility,
                    }, titleContainerDiv);

                    var titleText = domConstruct.create("label", {
                        "for": "layer_ck_"+i,
                        "className": this.css.titleText,
                        "innerHTML": layer.title,
                        role: "presentation",
                        //"title" : layer.title
                    }, titleContainerDiv);

                    this._atachSpaceKey(titleContainerDiv, titleCheckbox);

                    var accountText = '';
                    if (layer.account) {
                        accountText = domConstruct.create("a", {
                            className: this.css.accountText,
                            id: layer.account
                        }, titleText);
                    }

                    // settings
                    var settingsDiv, settingsIcon;
                    if (layer.layerObject &&
                        dojo.exists("settings", layer) &&
                        layer.layerObject.isEditable())
                    {
                        settingsDiv = domConstruct.create("div", {
                            className: this.css.settings,
                            id: layer.settings
                        }, titleContainerDiv);

                        settingsIcon = domConstruct.create("img", {
                            'src' : 'images/icon-cog.png',
                            alt:'Configuration',
                            role: "button,",
                            tabindex:0,
                        }, settingsDiv);
                    }

                    // clear css
                    var clearCSS = domConstruct.create("div", {
                        className: this.css.clear
                    }, titleContainerDiv);

                    // lets save all the nodes for events
                    var nodesObj = {
                        checkbox: titleCheckbox,
                        title: titleDiv,
                        titleContainer: titleContainerDiv,
                        titleText: titleText,
                        accountText: accountText,
                        settingsIcon: settingsIcon,
                        settingsDiv: settingsDiv,
                        layer: layerDiv
                    };
                    this._nodes.push(nodesObj);
                    // create click event
                    this._checkboxEvent(i);
                }
                this._setLayerEvents();
            }
        },

        _atachSpaceKey: function(onButton, clickButton) {
            on(onButton, 'keyup', lang.hitch(clickButton, function(event){
                if(event.keyCode=='32')
                    this.click();
            }));
        },

        _refreshLayers: function () {
            this.refresh();
        },

        _removeEvents: function () {
            var i;
            // checkbox click events
            if (this._checkEvents && this._checkEvents.length) {
                for (i = 0; i < this._checkEvents.length; i++) {
                    this._checkEvents[i].remove();
                }
            }
            // layer visibility events
            if (this._layerEvents && this._layerEvents.length) {
                for (i = 0; i < this._layerEvents.length; i++) {
                    this._layerEvents[i].remove();
                }
            }
            this._checkEvents = [];
            this._layerEvents = [];
        },

        _toggleVisible: function (index, visible) {
            // update checkbox and layer visibility classes
            domClass.toggle(this._nodes[index].layer, this.css.visible, visible);
            domClass.toggle(this._nodes[index].checkbox, this.css.checkboxCheck, visible);

            this.emit("toggle", {
                index: index,
                visible: visible
            });

            if(visible) {
                domAttr.set(this._nodes[index].checkbox, "checked", "checked");
            }
            else {
                domAttr.set(this._nodes[index].checkbox, "checked", "");
            }
        },

        _layerEvent: function (layer, index) {
            // layer visibility changes
            var visChange = on(layer, "visibility-change", lang.hitch(this, function (evt) {
                // update checkbox and layer visibility classes
                this._toggleVisible(index, evt.visible);
            }));
            this._layerEvents.push(visChange);
        },

        _featureCollectionVisible: function (layer, index, visible) {
            // all layers either visible or not
            var equal;
            // feature collection layers turned on by default
            var visibleLayers = layer.visibleLayers;
            // feature collection layers
            var layers = layer.featureCollection.layers;
            // if we have layers set
            if (visibleLayers && visibleLayers.length) {
                // check if all layers have same visibility
                equal = array.every(visibleLayers, function (item) {
                    // check if current layer has same as first layer
                    return layers[item].layerObject.visible === visible;
                });
            }
            else {
                // check if all layers have same visibility
                equal = array.every(layers, function (item) {
                    // check if current layer has same as first layer
                    return item.layerObject.visible === visible;
                });
            }
            // all are the same
            if (equal) {
                this._toggleVisible(index, visible);
            }
        },

        _createFeatureLayerEvent: function (layer, index, i) {
            var layers = layer.featureCollection.layers;
            // layer visibility changes
            var visChange = on(layers[i].layerObject, "visibility-change", lang.hitch(this, function (evt) {
                var visible = evt.visible;
                this._featureCollectionVisible(layer, index, visible);
            }));
            this._layerEvents.push(visChange);
        },

        _featureLayerEvent: function (layer, index) {
            // feature collection layers
            var layers = layer.featureCollection.layers;
            if (layers && layers.length) {
                // make event for each layer
                for (var i = 0; i < layers.length; i++) {
                    this._createFeatureLayerEvent(layer, index, i);
                }
            }
        },

        _setLayerEvents: function () {
            // this function sets up all the events for layers
            var layers = this.get("layers");
            var layerObject;
            if (layers && layers.length) {
                // get all layers
                for (var i = 0; i < layers.length; i++) {
                    var layer = layers[i];
                    // if it is a feature collection with layers
                    if (layer.featureCollection && layer.featureCollection.layers && layer.featureCollection.layers.length) {
                        this._featureLayerEvent(layer, i);
                    } else {
                        // 1 layer object
                        layerObject = layer.layerObject;
                        this._layerEvent(layerObject, i);
                    }
                }
            }
        },

        _toggleLayer: function (layerIndex) {
            // all layers
            if (this.layers && this.layers.length) {
                var newVis;
                var layer = this.layers[layerIndex];
                var layerObject = layer.layerObject;
                var featureCollection = layer.featureCollection;
                var visibleLayers;
                var i;
                if (featureCollection) {
                    // visible feature layers
                    visibleLayers = layer.visibleLayers;
                    // new visibility
                    newVis = !layer.visibility;
                    // set visibility for layer reference
                    layer.visibility = newVis;
                    // toggle all feature collection layers
                    if (visibleLayers && visibleLayers.length) {
                        // toggle visible sub layers
                        for (i = 0; i < visibleLayers.length; i++) {
                            layerObject = featureCollection.layers[visibleLayers[i]].layerObject;
                            // toggle to new visibility
                            layerObject.setVisibility(newVis);
                        }
                    }
                    else {
                        // toggle all sub layers
                        for (i = 0; i < featureCollection.layers.length; i++) {
                            layerObject = featureCollection.layers[i].layerObject;
                            // toggle to new visibility
                            layerObject.setVisibility(newVis);
                        }
                    }
                } else if (layerObject) {
                    newVis = !layer.layerObject.visible;
                    layer.visibility = newVis;
                    layerObject.setVisibility(newVis);
                }
            }
        },

        _checkboxEvent: function (index) {
            // when checkbox is clicked
            var checkEvent = on(this._nodes[index].checkbox, "click", lang.hitch(this,
                function (evt) {
                // toggle layer visibility
                this._toggleLayer(index);
                //event.stop(evt);
            }));
            this._checkEvents.push(checkEvent);
        },

        _init: function () {
            this._visible();
            this._createList();
            this.set("loaded", true);
            this.emit("load", {});
        },

        _updateThemeWatch: function () {
            var oldVal = arguments[1];
            var newVal = arguments[2];
            domClass.remove(this.domNode, oldVal);
            domClass.add(this.domNode, newVal);
        },

        _visible: function () {
            if (this.get("visible")) {
                domStyle.set(this.domNode, "display", "block");
            } else {
                domStyle.set(this.domNode, "display", "none");
            }
        }
    });
    if (has("extend-esri")) {
        lang.setObject("dijit.TableOfContents", Widget, esriNS);
    }
    return Widget;
});<commit_msg>removed space behavior on layer title box<commit_after>define(["dojo/Evented", "dojo/_base/declare", "dojo/_base/lang", "dojo/has", "esri/kernel",
    "dijit/_WidgetBase", "dijit/_TemplatedMixin", "dojo/on",
    "dojo/text!application/dijit/templates/TableOfContents.html",
    "dojo/dom-class", "dojo/dom-attr", "dojo/dom-style", "dojo/dom-construct", "dojo/_base/event",
    "dojo/_base/array",
    "esri/symbols/TextSymbol", "esri/renderers/SimpleRenderer", "esri/layers/LabelLayer"
    ], function (
        Evented, declare, lang, has, esriNS,
        _WidgetBase, _TemplatedMixin, on,
        dijitTemplate,
        domClass, domAttr, domStyle, domConstruct, event,
        array,
        TextSymbol, SimpleRenderer, LabelLayer
    ) {
    var Widget = declare("esri.dijit.TableOfContents", [_WidgetBase, _TemplatedMixin, Evented], {
        templateString: dijitTemplate,
        // defaults
        options: {
            theme: "TableOfContents",
            map: null,
            layers: null,
            visible: true
        },

        // lifecycle: 1
        constructor: function (options, srcRefNode) {
            // mix in settings and defaults
            var defaults = lang.mixin({}, this.options, options);
            // widget node
            this.domNode = srcRefNode;
            // properties
            this.set("map", defaults.map);
            this.set("layers", defaults.layers);
            this.set("theme", defaults.theme);
            this.set("visible", defaults.visible);
            // listeners
            this.watch("theme", this._updateThemeWatch);
            this.watch("visible", this._visible);
            this.watch("layers", this._refreshLayers);
            this.watch("map", this.refresh);
            // classes
            this.css = {
                container: "toc-container",
                layer: "toc-layer",
                firstLayer: "toc-first-layer",
                title: "toc-title",
                titleContainer: "toc-title-container",
                content: "toc-content",
                titleCheckbox: "checkbox",
                checkboxCheck: "icon-check-1",
                titleText: "checkbox",
                accountText: "toc-account",
                visible: "toc-visible",
                settingsIcon: "icon-cog",
                settings: "toc-settings",
                actions: "toc-actions",
                account: "toc-account",
                clear: "clear"
            };
        },

        // start widget. called by user
        startup: function () {
            // map not defined
            if (!this.map) {
                this.destroy();
                console.log("TableOfContents::map required");
            }
            // when map is loaded
            if (this.map.loaded) {
                this._init();
            } else {
                on.once(this.map, "load", lang.hitch(this, function () {
                    this._init();
                }));
            }
        },

        // connections/subscriptions will be cleaned up during the destroy() lifecycle phase
        destroy: function () {
            this._removeEvents();
            this.inherited(arguments);
        },
        /* ---------------- */
        /* Public Events */
        /* ---------------- */
        // load
        // toggle
        // expand
        // collapse

        /* ---------------- */
        /* Public Functions */
        /* ---------------- */

        show: function () {
            this.set("visible", true);
        },

        hide: function () {
            this.set("visible", false);
        },

        refresh: function () {
            this._createList();
        },

        /* ----------------- */
        /* Private Functions */
        /* ----------------- */

        _createList: function () {
            var layers = this.get("layers");
            this._nodes = [];
            // kill events
            this._removeEvents();
            // clear node
            this._layersNode.innerHTML = "";
            domAttr.set(this._layersNode, "role", "list");
            // if we got layers
            if (layers && layers.length) {

                for (var i = 0; i < layers.length; i++) {
                    var layer = layers[i];

                    // ceckbox class
                    var titleCheckBoxClass = this.css.titleCheckbox;
                    // layer class
                    var layerClass = this.css.layer;
                    // first layer
                    if (i === (layers.length - 1)) {
                        layerClass += " ";
                        layerClass += this.css.firstLayer;
                    }
                    if (layer.visibility) {
                        layerClass += " ";
                        layerClass += this.css.visible;
                        titleCheckBoxClass += " ";
                        titleCheckBoxClass += this.css.checkboxCheck;
                    }

                    // layer node
                    var layerDiv = domConstruct.create("div", {
                        className: layerClass,
                        role: "listitem",
                    });
                    domConstruct.place(layerDiv, this._layersNode, "first");

                    // title of layer
                    var titleDiv = domConstruct.create("div", {
                        className: this.css.title,
                    }, layerDiv);

                    // title container
                    var titleContainerDiv = domConstruct.create("div", {
                        className: this.css.titleContainer,
                        tabindex: -1,
                    }, titleDiv);

                    titleCheckbox = domConstruct.create("input",
                    {
                        id: "layer_ck_"+i,
                        className: titleCheckBoxClass, //this.css.titleCheckbox,
                        type: "checkbox",
                        tabindex: 0,
                        checked: layer.visibility,
                    }, titleContainerDiv);

                    var titleText = domConstruct.create("label", {
                        "for": "layer_ck_"+i,
                        "className": this.css.titleText,
                        "innerHTML": layer.title,
                        role: "presentation",
                        //"title" : layer.title
                    }, titleContainerDiv);

                    // this._atachSpaceKey(titleContainerDiv, titleCheckbox);

                    var accountText = '';
                    if (layer.account) {
                        accountText = domConstruct.create("a", {
                            className: this.css.accountText,
                            id: layer.account
                        }, titleText);
                    }

                    // settings
                    var settingsDiv, settingsIcon;
                    if (layer.layerObject &&
                        dojo.exists("settings", layer) &&
                        layer.layerObject.isEditable())
                    {
                        settingsDiv = domConstruct.create("div", {
                            className: this.css.settings,
                            id: layer.settings
                        }, titleContainerDiv);

                        settingsIcon = domConstruct.create("img", {
                            'src' : 'images/icon-cog.png',
                            alt:'Configuration',
                            role: "button,",
                            tabindex:0,
                        }, settingsDiv);
                    }

                    // clear css
                    var clearCSS = domConstruct.create("div", {
                        className: this.css.clear
                    }, titleContainerDiv);

                    // lets save all the nodes for events
                    var nodesObj = {
                        checkbox: titleCheckbox,
                        title: titleDiv,
                        titleContainer: titleContainerDiv,
                        titleText: titleText,
                        accountText: accountText,
                        settingsIcon: settingsIcon,
                        settingsDiv: settingsDiv,
                        layer: layerDiv
                    };
                    this._nodes.push(nodesObj);
                    // create click event
                    this._checkboxEvent(i);
                }
                this._setLayerEvents();
            }
        },

        // _atachSpaceKey: function(onButton, clickButton) {
        //     on(onButton, 'keyup', lang.hitch(clickButton, function(event){
        //         if(event.keyCode===32) {
        //             clickButton.click();
        //             event.stopPropagation();
        //         }
        //     }));
        // },

        _refreshLayers: function () {
            this.refresh();
        },

        _removeEvents: function () {
            var i;
            // checkbox click events
            if (this._checkEvents && this._checkEvents.length) {
                for (i = 0; i < this._checkEvents.length; i++) {
                    this._checkEvents[i].remove();
                }
            }
            // layer visibility events
            if (this._layerEvents && this._layerEvents.length) {
                for (i = 0; i < this._layerEvents.length; i++) {
                    this._layerEvents[i].remove();
                }
            }
            this._checkEvents = [];
            this._layerEvents = [];
        },

        _toggleVisible: function (index, visible) {
            // update checkbox and layer visibility classes
            domClass.toggle(this._nodes[index].layer, this.css.visible, visible);
            domClass.toggle(this._nodes[index].checkbox, this.css.checkboxCheck, visible);

            this.emit("toggle", {
                index: index,
                visible: visible
            });

            if(visible) {
                domAttr.set(this._nodes[index].checkbox, "checked", "checked");
            }
            else {
                domAttr.set(this._nodes[index].checkbox, "checked", "");
            }
        },

        _layerEvent: function (layer, index) {
            // layer visibility changes
            var visChange = on(layer, "visibility-change", lang.hitch(this, function (evt) {
                // update checkbox and layer visibility classes
                this._toggleVisible(index, evt.visible);
            }));
            this._layerEvents.push(visChange);
        },

        _featureCollectionVisible: function (layer, index, visible) {
            // all layers either visible or not
            var equal;
            // feature collection layers turned on by default
            var visibleLayers = layer.visibleLayers;
            // feature collection layers
            var layers = layer.featureCollection.layers;
            // if we have layers set
            if (visibleLayers && visibleLayers.length) {
                // check if all layers have same visibility
                equal = array.every(visibleLayers, function (item) {
                    // check if current layer has same as first layer
                    return layers[item].layerObject.visible === visible;
                });
            }
            else {
                // check if all layers have same visibility
                equal = array.every(layers, function (item) {
                    // check if current layer has same as first layer
                    return item.layerObject.visible === visible;
                });
            }
            // all are the same
            if (equal) {
                this._toggleVisible(index, visible);
            }
        },

        _createFeatureLayerEvent: function (layer, index, i) {
            var layers = layer.featureCollection.layers;
            // layer visibility changes
            var visChange = on(layers[i].layerObject, "visibility-change", lang.hitch(this, function (evt) {
                var visible = evt.visible;
                this._featureCollectionVisible(layer, index, visible);
            }));
            this._layerEvents.push(visChange);
        },

        _featureLayerEvent: function (layer, index) {
            // feature collection layers
            var layers = layer.featureCollection.layers;
            if (layers && layers.length) {
                // make event for each layer
                for (var i = 0; i < layers.length; i++) {
                    this._createFeatureLayerEvent(layer, index, i);
                }
            }
        },

        _setLayerEvents: function () {
            // this function sets up all the events for layers
            var layers = this.get("layers");
            var layerObject;
            if (layers && layers.length) {
                // get all layers
                for (var i = 0; i < layers.length; i++) {
                    var layer = layers[i];
                    // if it is a feature collection with layers
                    if (layer.featureCollection && layer.featureCollection.layers && layer.featureCollection.layers.length) {
                        this._featureLayerEvent(layer, i);
                    } else {
                        // 1 layer object
                        layerObject = layer.layerObject;
                        this._layerEvent(layerObject, i);
                    }
                }
            }
        },

        _toggleLayer: function (layerIndex) {
            // all layers
            if (this.layers && this.layers.length) {
                var newVis;
                var layer = this.layers[layerIndex];
                var layerObject = layer.layerObject;
                var featureCollection = layer.featureCollection;
                var visibleLayers;
                var i;
                if (featureCollection) {
                    // visible feature layers
                    visibleLayers = layer.visibleLayers;
                    // new visibility
                    newVis = !layer.visibility;
                    // set visibility for layer reference
                    layer.visibility = newVis;
                    // toggle all feature collection layers
                    if (visibleLayers && visibleLayers.length) {
                        // toggle visible sub layers
                        for (i = 0; i < visibleLayers.length; i++) {
                            layerObject = featureCollection.layers[visibleLayers[i]].layerObject;
                            // toggle to new visibility
                            layerObject.setVisibility(newVis);
                        }
                    }
                    else {
                        // toggle all sub layers
                        for (i = 0; i < featureCollection.layers.length; i++) {
                            layerObject = featureCollection.layers[i].layerObject;
                            // toggle to new visibility
                            layerObject.setVisibility(newVis);
                        }
                    }
                } else if (layerObject) {
                    newVis = !layer.layerObject.visible;
                    layer.visibility = newVis;
                    layerObject.setVisibility(newVis);
                }
            }
        },

        _checkboxEvent: function (index) {
            // when checkbox is clicked
            var checkEvent = on(this._nodes[index].checkbox, "click", lang.hitch(this,
                function (evt) {
                // toggle layer visibility
                this._toggleLayer(index);
                //event.stop(evt);
            }));
            this._checkEvents.push(checkEvent);
        },

        _init: function () {
            this._visible();
            this._createList();
            this.set("loaded", true);
            this.emit("load", {});
        },

        _updateThemeWatch: function () {
            var oldVal = arguments[1];
            var newVal = arguments[2];
            domClass.remove(this.domNode, oldVal);
            domClass.add(this.domNode, newVal);
        },

        _visible: function () {
            if (this.get("visible")) {
                domStyle.set(this.domNode, "display", "block");
            } else {
                domStyle.set(this.domNode, "display", "none");
            }
        }
    });
    if (has("extend-esri")) {
        lang.setObject("dijit.TableOfContents", Widget, esriNS);
    }
    return Widget;
});<|endoftext|>


<commit_before>/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var isNumeric = require('fast-isnumeric');

var Lib = require('../../lib');

module.exports = function handlePositionDefaults(containerIn, containerOut, coerce, options) {
    var counterAxes = options.counterAxes || [];
    var overlayableAxes = options.overlayableAxes || [];
    var letter = options.letter;
    var grid = options.grid;

    var dfltAnchor, dfltDomain, dfltSide, dfltPosition;

    if(grid) {
        dfltDomain = grid._domains[letter][grid._axisMap[containerOut._id]];
        dfltAnchor = grid._anchors[containerOut._id];
        if(dfltDomain) {
            dfltSide = grid[letter + 'side'].split(' ')[0];
            dfltPosition = grid.domain[letter][dfltSide === 'right' || dfltSide === 'top' ? 1 : 0];
        }
    }

    // Even if there's a grid, this axis may not be in it - fall back on non-grid defaults
    dfltDomain = dfltDomain || [0, 1];
    dfltAnchor = dfltAnchor || (isNumeric(containerIn.position) ? 'free' : (counterAxes[0] || 'free'));
    dfltSide = dfltSide || (letter === 'x' ? 'bottom' : 'left');
    dfltPosition = dfltPosition || 0;

    var anchor = Lib.coerce(containerIn, containerOut, {
        anchor: {
            valType: 'enumerated',
            values: ['free'].concat(counterAxes),
            dflt: dfltAnchor
        }
    }, 'anchor');

    if(anchor === 'free') coerce('position', dfltPosition);

    Lib.coerce(containerIn, containerOut, {
        side: {
            valType: 'enumerated',
            values: letter === 'x' ? ['bottom', 'top'] : ['left', 'right'],
            dflt: dfltSide
        }
    }, 'side');

    var overlaying = false;
    if(overlayableAxes.length) {
        overlaying = Lib.coerce(containerIn, containerOut, {
            overlaying: {
                valType: 'enumerated',
                values: [false].concat(overlayableAxes),
                dflt: false
            }
        }, 'overlaying');
    }

    if(!overlaying) {
        // TODO: right now I'm copying this domain over to overlaying axes
        // in ax.setscale()... but this means we still need (imperfect) logic
        // in the axes popover to hide domain for the overlaying axis.
        // perhaps I should make a private version _domain that all axes get???
        var domain = coerce('domain', dfltDomain);
        if(domain[0] > domain[1] - 0.001) containerOut.domain = dfltDomain;
        Lib.noneOrAll(containerIn.domain, containerOut.domain, dfltDomain);
    }

    coerce('layer');

    return containerOut;
};
<commit_msg>apply a smaller const<commit_after>/**
* Copyright 2012-2019, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var isNumeric = require('fast-isnumeric');

var Lib = require('../../lib');

module.exports = function handlePositionDefaults(containerIn, containerOut, coerce, options) {
    var counterAxes = options.counterAxes || [];
    var overlayableAxes = options.overlayableAxes || [];
    var letter = options.letter;
    var grid = options.grid;

    var dfltAnchor, dfltDomain, dfltSide, dfltPosition;

    if(grid) {
        dfltDomain = grid._domains[letter][grid._axisMap[containerOut._id]];
        dfltAnchor = grid._anchors[containerOut._id];
        if(dfltDomain) {
            dfltSide = grid[letter + 'side'].split(' ')[0];
            dfltPosition = grid.domain[letter][dfltSide === 'right' || dfltSide === 'top' ? 1 : 0];
        }
    }

    // Even if there's a grid, this axis may not be in it - fall back on non-grid defaults
    dfltDomain = dfltDomain || [0, 1];
    dfltAnchor = dfltAnchor || (isNumeric(containerIn.position) ? 'free' : (counterAxes[0] || 'free'));
    dfltSide = dfltSide || (letter === 'x' ? 'bottom' : 'left');
    dfltPosition = dfltPosition || 0;

    var anchor = Lib.coerce(containerIn, containerOut, {
        anchor: {
            valType: 'enumerated',
            values: ['free'].concat(counterAxes),
            dflt: dfltAnchor
        }
    }, 'anchor');

    if(anchor === 'free') coerce('position', dfltPosition);

    Lib.coerce(containerIn, containerOut, {
        side: {
            valType: 'enumerated',
            values: letter === 'x' ? ['bottom', 'top'] : ['left', 'right'],
            dflt: dfltSide
        }
    }, 'side');

    var overlaying = false;
    if(overlayableAxes.length) {
        overlaying = Lib.coerce(containerIn, containerOut, {
            overlaying: {
                valType: 'enumerated',
                values: [false].concat(overlayableAxes),
                dflt: false
            }
        }, 'overlaying');
    }

    if(!overlaying) {
        // TODO: right now I'm copying this domain over to overlaying axes
        // in ax.setscale()... but this means we still need (imperfect) logic
        // in the axes popover to hide domain for the overlaying axis.
        // perhaps I should make a private version _domain that all axes get???
        var domain = coerce('domain', dfltDomain);
        if(domain[0] > domain[1] - (1 / 32768.0)) containerOut.domain = dfltDomain;
        Lib.noneOrAll(containerIn.domain, containerOut.domain, dfltDomain);
    }

    coerce('layer');

    return containerOut;
};
<|endoftext|>