<commit_before>var assert = require('assert');
var deeq = require('../');

describe('deeq', () => {
  context('Set', () => {
    it('equals', () => {
      assert(deeq(new Set(), new Set()));
      assert(deeq(new Set([1]), new Set([1])));
      assert(deeq(new Set([1, 2]), new Set([1, 2])));
    });
    it('different size', () => {
      assert(!deeq(new Set([1]), new Set()));
    });
    it('different value', () => {
      assert(!deeq(new Set([1]), new Set([2])));
    });
    it('not strict', () => {
      assert(deeq(new Set([1]), new Set(['1'])));
    });
    it('strict', () => {
      assert(!deeq(new Set([1]), new Set(['1']), true));
    });
  });

  context('Map', () => {
    it('equals', () => {
      assert(deeq(new Map(), new Map()));
      assert(deeq(new Map([['a', 1]]), new Map([['a', 1]])));
      assert(deeq(new Map([['a', 1], ['b', 2]]), new Map([['a', 1], ['b', 2]])));
    });
    it('different size', () => {
      assert(!deeq(new Map([['a', 1]]), new Map()));
    });
    it('different value', () => {
      assert(!deeq(new Map([['a', 1]]), new Map([['a', 2]])));
    });
    it('different key', () => {
      assert(!deeq(new Map([['a', 1]]), new Map([['b', 1]])));
    });
    it('not strict', () => {
      assert(deeq(new Map([['a', 1]]), new Map([['a', '1']])));
    });
    it('strict', () => {
      assert(!deeq(new Map([['a', 1]]), new Map([['a', '1']]), true));
    });
  });

  context('Primitives', () => {
    it('same', () => {
      assert(deeq(1, 1));
      assert(deeq('a', 'a'));
      assert(deeq(null, null));
      assert(deeq(undefined, undefined));
      var s = Symbol();
      assert(deeq(s, s));
    });
    it('different', () => {
      assert(!deeq(1, 2));
      assert(!deeq('a', 'b'));
      assert(!deeq(null, 0));
      assert(!deeq(Symbol(), Symbol()));
    });
    it('not strict', () => {
      assert(deeq(4, '4'));
      assert(deeq(true, 1));
      assert(!deeq(4, '5'));
    });
    it('strict', () => {
      assert(deeq(4, 4, true));
      assert(!deeq(4, '4', true));
    });
  });

  context('Date', () => {
    it('same', () => {
      assert(deeq(new Date(2000, 3, 14), new Date(2000, 3, 14)));
    });
    it('different', () => {
      assert(!deeq(new Date(2000, 3, 14), new Date(2000, 3, 15)));
    });
  });

  context('RegExp', () => {
    it('same', () => {
      assert(deeq(/a/, /a/));
      assert(deeq(/a/g, /a/g));
      assert(deeq(/a/i, /a/i));
      assert(deeq(/a/m, /a/m));
      assert(deeq(/a/igm, /a/igm));
      assert(deeq(/a/mgi, /a/igm));
    });
    it('different pattern', () => {
      assert(!deeq(/ab/, /a/));
    });
    it('different flag: g', () => {
      assert(!deeq(/a/g, /a/));
    });
    it('different flag: i', () => {
      assert(!deeq(/a/i, /a/));
    });
    it('different flag: m', () => {
      assert(!deeq(/a/m, /a/));
    });
    it('different flag order', () => {
      assert(!deeq(/a/igm, /a/im));
    });
    it('different last index', () => {
      var re = /a/;
      re.lastIndex = 3;
      assert(!deeq(re, /a/));
    });
  });

  context('Object', () => {
    it('having the same number of owned properties && the same set of keys', () => {
      assert(deeq({a: 4}, {a: 4}));
      assert(deeq({a: 4, b: '2'}, {a: 4, b: '2'}));
    });
    it('array', () => {
      assert(deeq([4], ['4']));
    });
    it('does not allow extra property', () => {
      assert(!deeq({a: 4}, {a: 4, b: true}));
    });
    it('array and object (number index)', () => {
      assert(deeq(['a'], {0: 'a'}));
    });
    it('although not necessarily the same order', () => {
      assert(deeq({a: 4, b: '1'}, {b: '1', a: 4}));
    });
    it('array that has properties', () => {
      var a1 = [1, 2, 3];
      var a2 = [1, 2, 3];
      a1.a = 'test';
      a1.b = true;
      a2.b = true;
      a2.a = 'test';
      assert(!deeq(Object.keys(a1), Object.keys(a2))); // depends on implementation
      assert(deeq(a1, a2));
    });
    it('having an identical prototype property', () => {
      var nbRoot = {
        toString: function() { return this.first + ' ' + this.last; }
      };

      function nameBuilder(first, last) {
        this.first = first;
        this.last = last;
        return this;
      }
      nameBuilder.prototype = nbRoot;

      function nameBuilder2(first, last) {
        this.first = first;
        this.last = last;
        return this;
      }
      nameBuilder2.prototype = nbRoot;

      var nb1 = new nameBuilder('Ryan', 'Dahl');
      var nb2 = new nameBuilder2('Ryan', 'Dahl');

      assert(deeq(nb1, nb2));

      nameBuilder2.prototype = Object;
      nb2 = new nameBuilder2('Ryan', 'Dahl');
      assert(deeq(nb1, nb2));
    });
    it('primitives and object', () => {
      assert(!deeq(null, {}));
      assert(!deeq(undefined, {}));
      assert(!deeq('a', ['a']));
      assert(!deeq('a', {0: 'a'}));
      assert(!deeq(1, {}));
      assert(!deeq(true, {}));
      assert(!deeq(Symbol(), {}));
    });
    it('primitive wrappers and object', () => {
      assert(deeq(new String('a'), ['a']));
      assert(deeq(new String('a'), {0: 'a'}));
      assert(deeq(new Number(1), {}));
      assert(deeq(new Boolean(true), {}));
    });
  });
});
<commit_msg>test(deeq): add tests for different order<commit_after>var assert = require('assert');
var deeq = require('../');

describe('deeq', () => {
  context('Set', () => {
    it('equals', () => {
      assert(deeq(new Set(), new Set()));
      assert(deeq(new Set([1]), new Set([1])));
      assert(deeq(new Set([1, 2]), new Set([1, 2])));
    });
    it('different size', () => {
      assert(!deeq(new Set([1]), new Set()));
    });
    it('different value', () => {
      assert(!deeq(new Set([1]), new Set([2])));
    });
    it('different order', () => {
      assert(!deeq(new Set([1, 2]), new Set([2, 1])));
    });
    it('not strict', () => {
      assert(deeq(new Set([1]), new Set(['1'])));
    });
    it('strict', () => {
      assert(!deeq(new Set([1]), new Set(['1']), true));
    });
  });

  context('Map', () => {
    it('equals', () => {
      assert(deeq(new Map(), new Map()));
      assert(deeq(new Map([['a', 1]]), new Map([['a', 1]])));
      assert(deeq(new Map([['a', 1], ['b', 2]]), new Map([['a', 1], ['b', 2]])));
    });
    it('different size', () => {
      assert(!deeq(new Map([['a', 1]]), new Map()));
    });
    it('different value', () => {
      assert(!deeq(new Map([['a', 1]]), new Map([['a', 2]])));
    });
    it('different key', () => {
      assert(!deeq(new Map([['a', 1]]), new Map([['b', 1]])));
    });
    it('different order', () => {
      assert(!deeq(new Map([['a', 1], ['b', 2]]), new Map([['b', 2], ['a', 1]])));
    });
    it('not strict', () => {
      assert(deeq(new Map([['a', 1]]), new Map([['a', '1']])));
    });
    it('strict', () => {
      assert(!deeq(new Map([['a', 1]]), new Map([['a', '1']]), true));
    });
  });

  context('Primitives', () => {
    it('same', () => {
      assert(deeq(1, 1));
      assert(deeq('a', 'a'));
      assert(deeq(null, null));
      assert(deeq(undefined, undefined));
      var s = Symbol();
      assert(deeq(s, s));
    });
    it('different', () => {
      assert(!deeq(1, 2));
      assert(!deeq('a', 'b'));
      assert(!deeq(null, 0));
      assert(!deeq(Symbol(), Symbol()));
    });
    it('not strict', () => {
      assert(deeq(4, '4'));
      assert(deeq(true, 1));
      assert(!deeq(4, '5'));
    });
    it('strict', () => {
      assert(deeq(4, 4, true));
      assert(!deeq(4, '4', true));
    });
  });

  context('Date', () => {
    it('same', () => {
      assert(deeq(new Date(2000, 3, 14), new Date(2000, 3, 14)));
    });
    it('different', () => {
      assert(!deeq(new Date(2000, 3, 14), new Date(2000, 3, 15)));
    });
  });

  context('RegExp', () => {
    it('same', () => {
      assert(deeq(/a/, /a/));
      assert(deeq(/a/g, /a/g));
      assert(deeq(/a/i, /a/i));
      assert(deeq(/a/m, /a/m));
      assert(deeq(/a/igm, /a/igm));
      assert(deeq(/a/mgi, /a/igm));
    });
    it('different pattern', () => {
      assert(!deeq(/ab/, /a/));
    });
    it('different flag: g', () => {
      assert(!deeq(/a/g, /a/));
    });
    it('different flag: i', () => {
      assert(!deeq(/a/i, /a/));
    });
    it('different flag: m', () => {
      assert(!deeq(/a/m, /a/));
    });
    it('different flag order', () => {
      assert(!deeq(/a/igm, /a/im));
    });
    it('different last index', () => {
      var re = /a/;
      re.lastIndex = 3;
      assert(!deeq(re, /a/));
    });
  });

  context('Object', () => {
    it('having the same number of owned properties && the same set of keys', () => {
      assert(deeq({a: 4}, {a: 4}));
      assert(deeq({a: 4, b: '2'}, {a: 4, b: '2'}));
    });
    it('array', () => {
      assert(deeq([4], ['4']));
    });
    it('does not allow extra property', () => {
      assert(!deeq({a: 4}, {a: 4, b: true}));
    });
    it('array and object (number index)', () => {
      assert(deeq(['a'], {0: 'a'}));
    });
    it('although not necessarily the same order', () => {
      assert(deeq({a: 4, b: '1'}, {b: '1', a: 4}));
    });
    it('array that has properties', () => {
      var a1 = [1, 2, 3];
      var a2 = [1, 2, 3];
      a1.a = 'test';
      a1.b = true;
      a2.b = true;
      a2.a = 'test';
      assert(!deeq(Object.keys(a1), Object.keys(a2))); // depends on implementation
      assert(deeq(a1, a2));
    });
    it('having an identical prototype property', () => {
      var nbRoot = {
        toString: function() { return this.first + ' ' + this.last; }
      };

      function nameBuilder(first, last) {
        this.first = first;
        this.last = last;
        return this;
      }
      nameBuilder.prototype = nbRoot;

      function nameBuilder2(first, last) {
        this.first = first;
        this.last = last;
        return this;
      }
      nameBuilder2.prototype = nbRoot;

      var nb1 = new nameBuilder('Ryan', 'Dahl');
      var nb2 = new nameBuilder2('Ryan', 'Dahl');

      assert(deeq(nb1, nb2));

      nameBuilder2.prototype = Object;
      nb2 = new nameBuilder2('Ryan', 'Dahl');
      assert(deeq(nb1, nb2));
    });
    it('primitives and object', () => {
      assert(!deeq(null, {}));
      assert(!deeq(undefined, {}));
      assert(!deeq('a', ['a']));
      assert(!deeq('a', {0: 'a'}));
      assert(!deeq(1, {}));
      assert(!deeq(true, {}));
      assert(!deeq(Symbol(), {}));
    });
    it('primitive wrappers and object', () => {
      assert(deeq(new String('a'), ['a']));
      assert(deeq(new String('a'), {0: 'a'}));
      assert(deeq(new Number(1), {}));
      assert(deeq(new Boolean(true), {}));
    });
  });
});
<|endoftext|>


<commit_before>var http = require('http');
var fs = require('fs');
var host = '172.17.42.1';
host = 'localhost';
var port = 4001;

function getJson(page, callback) {
    return http.get({
        host: host,
        port: port,
        path: page,
    }, function(response) {
        // Continuously update stream with data
        var body = '';
        response.on('data', function(d) {
            body += d;
        });
        response.on('end', function() {
            // Data reception is done, do whatever with it!
            var parsed = JSON.parse(body);
            callback( parsed );
        });
    });
};

function getDocs ( callback ) {
  getJson('/api-docs', function(jsonDoc) {
    callback(jsonDoc.apis);
  });
};

function mkdirSync (path) {
  try {
    fs.mkdirSync(path);
  } catch(e) {
    if ( e.code != 'EEXIST' ) throw e;
  }
}

var createApiData = function(apis) {
  var resourceUrl = "";
  var newArray = [];
  for (i in apis) {
    basename = apis[i].path.split(/^\/v\d+\//)[1];
    resourceUrl = "http://" + host + ":" + port + "/api-docs" + apis[i].path;
    newArray.push({'baseName': basename, 'resourceUrl': resourceUrl});
  }
};

getDocs(getApiEndpoints);
getDocs(writeConverterScript);

console.log("Now run:\ncd output\nnpm install swagger-converter\nsh convert.sh");
<commit_msg>convert our 1.2 swagger docs to 2.0<commit_after>var http = require('http');
var fs = require('fs');
var swaggerConverter = require('swagger-converter');
var host = '172.17.42.1';
host = 'localhost';
var port = 4001;
var apiVersion = "0.3.5";

function getJson(page, callback) {
    return http.get({
        host: host,
        port: port,
        path: page,
    }, function(response) {
        // Continuously update stream with data
        var body = '';
        response.on('data', function(d) {
            body += d;
        });
        response.on('end', function() {
            // Data reception is done, do whatever with it!
            var parsed = JSON.parse(body);
            callback( parsed );
        });
    });
};

function mkdirSync (path) {
  try {
    fs.mkdirSync(path);
  } catch(e) {
    if ( e.code != 'EEXIST' ) throw e;
  }
}

// getApiEndpoints THEN createApiData THEN downloadEndPointAPIS THEN localTransformFixes THEN convertToVersion2

var fetchData = function() {
  return new Promise(function(resolve, reject) {
    getJson('/api-docs', function(jsonDoc) {
      resolve({"root": jsonDoc, "apis": jsonDoc.apis});
    });
  });
};

var parseApiEndpoints = function(data) {
  return new Promise(function(resolve, reject) {
    var resourceUrl = "";
    var newArray = [];
    var apis = data.apis;
    for (i in apis) {
      var baseName = apis[i].path.split(/^\/v\d+\//)[1];
      resourceUrl = "http://" + host + ":" + port + "/api-docs" + apis[i].path;
      newArray.push({'baseName': baseName, 'resourceUrl': resourceUrl});
    }
    data.apis = newArray;
    resolve(data);
  });
};

var readApiEndpoints = function(data) {
  var apis = data.apis;
  var promiseChain = [];
  for (var i in apis) {
    var tempPromise = new Promise(function(resolve, reject) {
      var baseName = apis[i].baseName;
      var resourceUrl = apis[i].resourceUrl;
      getJson('/api-docs/v0/' + baseName, function(jsonDoc) {
        resolve({"baseName": baseName, "api": jsonDoc});
      });
    });
    promiseChain.push(tempPromise);
  }
  return Promise.all(promiseChain)
    .then(function(chainData) {
      return new Promise(function(resolve, reject) {
        data.apis = chainData;
        resolve(data);
      });
    });
};

var flattenApis = function(data) {
  return new Promise(function(resolve, reject) {
    var flatArray = [];
    for(var i in data['apis']) {
      flatArray.push(data['apis'][i]['api']);
    }
    data['apis'] = flatArray;
    resolve(data);
  });
};

var writeVersion1 = function(data) {
  return new Promise(function(resolve, reject) {
    for (var i in data['apis']) {
      var base = data['apis'][i]['baseName'];
      var contents = data['apis'][i]['api'];
      fs.writeFileSync('./output/swaggerv1.2/' + base + '.json', JSON.stringify(contents));
    }
    resolve(data);
  });
};

var writeVersion2 = function(data) {
  return new Promise(function(resolve, reject) {
      fs.writeFileSync('./output/swaggerv2/api.json', JSON.stringify(data));
      resolve(data);
  });
};

var logData = function(data) {
  return new Promise(function(resolve, reject) {
    console.log(data);
    resolve(data);
  });
};

var transformJson = function(jsonDoc) {
  /* //for outer document
  data.info.title = "CoralAPIServer";
  data.info.version = apiVersion;
  */
  return new Promise(function(resolve, reject) {
    var dataArray = jsonDoc.apis;
    for (var h in dataArray) {
      var data = dataArray[h];
      data.basePath = "http://coralapiserver.local:4001";
      for (var i in data.apis) {
        data.apis[i].path = data.apis[i].path.substring(3) ;
        for (var j in data.apis[i].operations) {
          var requiresAuth = false;
          for (var k in data.apis[i].operations[j].parameters) {
            if (data.apis[i].operations[j].parameters[k].items ) {
              delete data.apis[i].operations[j].parameters[k].items;
              data.apis[i].operations[j].parameters[k].type = 'string';
            }
            if (data.apis[i].operations[j].parameters[k].type == 'User') {
              data.apis[i].operations[j].parameters.splice(k, 1);
              requiresAuth = true;
            }
          }
          if (requiresAuth) {
            data.apis[i].operations[j].security = { "basicAuth": [] };
          }
        }
      }
      dataArray[h] = data;
    }
    jsonDoc.apis = dataArray;
    resolve(jsonDoc);
  });
};

var convertToVersion2 = function(data) {
  return new Promise(function(resolve, reject) {
    var resourceListing = data.root;
    var apiDeclarations = data.apis
    var swagger2Document = swaggerConverter(resourceListing, apiDeclarations);
    resolve(swagger2Document);
  });
};

var updateVersion2 = function(data) {
  return new Promise(function(resolve, reject) {
    data.info.version = apiVersion;
    data.info.title = "Coral API Server";
    resolve(data);
  });
};

mkdirSync('./output');
mkdirSync('./output/swaggerv1.2');
mkdirSync('./output/swaggerv2');

fetchData().then(function(data) {
  return parseApiEndpoints(data);
}).then(function(data) {
  console.log("----STEP 1------");
  return readApiEndpoints(data);
}).then(function(data) {
  console.log("----STEP 2.5------");
  console.log(data);
  return writeVersion1(data);
}).then(function(data) {
  console.log("----STEP 2------");
  console.log(data);
  return flattenApis(data);
}).then(function(data) {
  console.log("----STEP 3------");
  console.log(data);
  return transformJson(data);
}).then(function(data) {
  console.log("----STEP 4------");
  console.log(data);
  return convertToVersion2(data);
}).then(function(data) {
  console.log("----STEP 4.2------");
  console.log(data);
  return updateVersion2(data);
}).then(function(data) {
  console.log("----STEP 4.5------");
  console.log(data);
  return writeVersion2(data);
}).then(function(data) {
  console.log("----STEP 5------");
  console.log(data);
  //return logData(data);
});
<|endoftext|>


<commit_before>const test = require('ava');
const random = require('./helpers/random');
const all = require('./products');

test('all()', t => {
  t.true(all.length > 0);
});

test('random()', t => {
  t.truthy(random(all));
  t.not(random(all), random(all));
});
<commit_msg>🤖(break): 2017-7-3 08:37:46<commit_after>const test = require('ava');
const random = require('./helpers/random');
const all = require('./products');

test('all()', t => {
  t.true(all.length < 0);
});

test('random()', t => {
  t.truthy(random(all));
  t.not(random(all), random(all));
});
<|endoftext|>


<commit_before>let msec = 0, prevInitMsec = 0, prevNow = 0;
let plotMode = -1, plotLabels = ["position(y)", "velocity(y)", "acceralation(y)"], plotStartMsec = 0, plotData = [];
let gravity = 9.8 * 2; // 2px ~= 1m
let apple;

function setup() {
    canvas = createCanvas(windowWidth, windowHeight);
    apple = new Body(1);
}

function draw() {
  clear();
  background(247, 227, 218);

  ellapseTime();

  let minWH = min(width, height);
  push();
  translate(min((width - minWH) / 2 + 32, width / 4) , 32);
  fill(250, 170, 165); stroke(0);
  ellipse(0, apple.position.y, 24, 24);
  line(0, apple.position.y - 8, 0, apple.position.y - 16);
  pop();

  let graphW = minWH - 64;
  plotGraph(plotData, (width - graphW) / 2 + 32, 32, graphW, height - 64, 0, 8000, -(height - 64), 0, "time", plotLabels[plotMode]);
}

function ellapseTime() {
  let ellapsedMsec = min(100, window.performance.now() - prevNow);
  msec += ellapsedMsec;
  let secondsRemaining = ellapsedMsec / 1000;
  let maxStepSize = 1 / 60;
  while (secondsRemaining > 0) {
    let stepSize = secondsRemaining > maxStepSize ? maxStepSize : secondsRemaining;
    updateSimulation(stepSize);
    secondsRemaining -= maxStepSize;
  }

  if (msec > prevInitMsec + 8000) {
    apple = new Body(1);
    plotData = [];
    prevInitMsec += 8000;
  }

  if (plotData.length == 0) {
    plotStartMsec = msec;
    plotMode = (plotMode + 1) % 3;
  }

  let protMsec = msec - plotStartMsec;
  switch(plotMode) {
    case 0: plotData.push({x:protMsec, y: -apple.position.y}); break;
    case 1: plotData.push({x:protMsec, y: -apple.velocity.y}); break;
    case 2: plotData.push({x:protMsec, y: -getForce(apple).y}); break;
  }
}

function updateSimulation(t) {
  apple.applyForce(getForce(apple), t);
  apple.update(t);
}

function getForce(o) {
  return createVector(0, gravity).mult(o.mass)
}

/** plotGraph **/

/** Body **/

/** drawCircleMarker **/

/** drawLabel **/
<commit_msg>Spelling change<commit_after>let msec = 0, prevInitMsec = 0, prevNow = 0;
let plotMode = -1, plotLabels = ["position(y)", "velocity(y)", "acceleration(y)"], plotStartMsec = 0, plotData = [];
let gravity = 9.8 * 2; // 2px ~= 1m
let apple;

function setup() {
    canvas = createCanvas(windowWidth, windowHeight);
    apple = new Body(1);
}

function draw() {
  clear();
  background(247, 227, 218);

  ellapseTime();

  let minWH = min(width, height);
  push();
  translate(min((width - minWH) / 2 + 32, width / 4) , 32);
  fill(250, 170, 165); stroke(0);
  ellipse(0, apple.position.y, 24, 24);
  line(0, apple.position.y - 8, 0, apple.position.y - 16);
  pop();

  let graphW = minWH - 64;
  plotGraph(plotData, (width - graphW) / 2 + 32, 32, graphW, height - 64, 0, 8000, -(height - 64), 0, "time", plotLabels[plotMode]);
}

function ellapseTime() {
  let ellapsedMsec = min(100, window.performance.now() - prevNow);
  msec += ellapsedMsec;
  let secondsRemaining = ellapsedMsec / 1000;
  let maxStepSize = 1 / 60;
  while (secondsRemaining > 0) {
    let stepSize = secondsRemaining > maxStepSize ? maxStepSize : secondsRemaining;
    updateSimulation(stepSize);
    secondsRemaining -= maxStepSize;
  }

  if (msec > prevInitMsec + 8000) {
    apple = new Body(1);
    plotData = [];
    prevInitMsec += 8000;
  }

  if (plotData.length == 0) {
    plotStartMsec = msec;
    plotMode = (plotMode + 1) % 3;
  }

  let protMsec = msec - plotStartMsec;
  switch(plotMode) {
    case 0: plotData.push({x:protMsec, y: -apple.position.y}); break;
    case 1: plotData.push({x:protMsec, y: -apple.velocity.y}); break;
    case 2: plotData.push({x:protMsec, y: -getForce(apple).y}); break;
  }
}

function updateSimulation(t) {
  apple.applyForce(getForce(apple), t);
  apple.update(t);
}

function getForce(o) {
  return createVector(0, gravity).mult(o.mass)
}

/** plotGraph **/

/** Body **/

/** drawCircleMarker **/

/** drawLabel **/
<|endoftext|>


<commit_before>var osx_version = require('./main.js').get();
if (process.platform === 'darwin') {
  console.log('\nOSX version: %s\n', osx_version);
} else {
  if (osx_version !== 'no OSX system') {
    console.log('ERROR');
    process.exit(1);
  } else {
    console.log('\nOSX version: %s\n', osx_version);
  }
}
<commit_msg>better test script<commit_after>var osx_version = require('./main.js').get(); /* istanbul ignore next */
if (process.platform !== 'darwin') {
  if (osx_version !== 'no OSX system') {
    console.log('ERROR');
    process.exit(1);
  }
}
console.log('\nOSX version: %s\n', osx_version);
<|endoftext|>


<commit_before>(function($, undefined) {

  $(document).ready(function () {

    module('Objectify.convert');

    var personForm = $('#person-fixture').get(0),
        personObj = Objectify.convert(personForm);

    test('Object definitions', function() {
      ok(personObj.person, 'Person object exists');
      ok(personObj.person.name, 'Person has a name');
      ok(personObj.person.email, 'Person has an email');
      ok(personObj.person.address, 'Person has an Address');
      ok(personObj.person.address.street_address, 'Address has a street_address');
      ok(personObj.person.address.city, 'Address has a city');
      ok(personObj.person.address.state, 'Address has a state');
      ok(personObj.person.address.zip, 'Address has a zip');
      ok(personObj.person.authorizations, 'Authorizations object exists');
      ok(Object.isArray(personObj.person.authorizations), 'Authorizations is an array');
    });

    test('_method parameter is ignored', function () {
      equal(personObj['_method'], undefined, "_method parameter is not added to object");
    });

    var personFixture = {
      "person": {
        "id": "1",
        "name": "Joe Blow",
        "email": "joe.blow@test.com",
        "address": {
          "street_address": "123 Somewhere St",
          "city": "Omaha",
          "state": "NE",
          "zip": "68144"
        },
        "authorizations": ["1", "2", "3"]
      }
    };

    test('Object structure', function() {
      same(
        personObj,
        personFixture,
        "Object structure is generated as expected"
      );
    });

    module('Objectify.fields');

    test('Objectify.fields() with no args returns the current filters', function () {

      Objectify.fields({
        id: Number,
        "something[id]": String
      });

      same(
        Objectify.fields(),
        { id: Number, "something[id]": String },
        "The filters passed into Objectify.fields have been stored correctly"
      );
    });

    test('field filters are persistent and additive', function () {

      function zipConverter (zip) {
        return zip + "-1234";
      }

      Objectify.fields({
        zip: zipConverter,
        "be_integers": Number,
        "be_floats": Number,
        date: String, // should not match
        good: Date, // should match
        bad: Date, // should be string
        "parseInt": Number
      });

      same(
        Objectify.fields(),
        {
          id: Number,
          "something[id]": String,
          zip: zipConverter,
          "be_integers": Number,
          "be_floats": Number,
          date: String,
          good: Date,
          bad: Date,
          "parseInt": Number
        },
        "The two Objectify.fields() objects have been combined together"
      );
    });

    var filtersObj;

    test('User-provided field filters are applied', function () {
      filtersObj = Objectify.convert($('form#filters-fixture').get(0));
      equal(filtersObj.something.zip, "68144-1234", "user-defined functions are used correctly");
    });

    test('Exact field matches take precedence over general matches', function () {
      ok(filtersObj.id === 1, "id was converted to Number");
      ok(filtersObj.something.id === "2", "something[id] filter overrode general id filter");
    });

    test('parseInt is used for Numbers with no decimal point', function () {
      same(filtersObj.these_should.be_strings, ["1", "2", "3"], "these_should[be_strings][] were combined into an array but left untouched");
      same(filtersObj.these_should.be_integers, [4, 5, 6], "these_should[be_integers][] were parsed into an array of integers");
      same(filtersObj.these_should.be_floats, [10.1, 10.2, 10.3], "these_should[be_floats][] were parsed into an array of floats");
    });

    test('Number data types correctly avoid the parseInt octal bug', function () {
      ok(filtersObj.testing.parseInt === 9, "testing[parseInt] was parsed into a base-10 integer");
    });

    test('Date parsing', function () {
      ok(filtersObj.date.good instanceof Date, "date was correctly converted to Date instance");
      ok(filtersObj.date.good === new Date("Wed Aug 25 2010 21:14:47 GMT-0500 (CST)"), "date was parsed to correct Date");
      equal(filtersObj.date.bad, "2010-8-25 9pm", "non-parsable date should be left as String");
    });

    test('Objectify.fields.clear() removes filters', function () {
      Objectify.fields.clear();
      same(Objectify.fields(), {}, "Fields filters are now empty");
    });

  });

})(jQuery);<commit_msg>fixing date test<commit_after>(function($, undefined) {

  $(document).ready(function () {

    module('Objectify.convert');

    var personForm = $('#person-fixture').get(0),
        personObj = Objectify.convert(personForm);

    test('Object definitions', function() {
      ok(personObj.person, 'Person object exists');
      ok(personObj.person.name, 'Person has a name');
      ok(personObj.person.email, 'Person has an email');
      ok(personObj.person.address, 'Person has an Address');
      ok(personObj.person.address.street_address, 'Address has a street_address');
      ok(personObj.person.address.city, 'Address has a city');
      ok(personObj.person.address.state, 'Address has a state');
      ok(personObj.person.address.zip, 'Address has a zip');
      ok(personObj.person.authorizations, 'Authorizations object exists');
      ok(Object.isArray(personObj.person.authorizations), 'Authorizations is an array');
    });

    test('_method parameter is ignored', function () {
      equal(personObj['_method'], undefined, "_method parameter is not added to object");
    });

    var personFixture = {
      "person": {
        "id": "1",
        "name": "Joe Blow",
        "email": "joe.blow@test.com",
        "address": {
          "street_address": "123 Somewhere St",
          "city": "Omaha",
          "state": "NE",
          "zip": "68144"
        },
        "authorizations": ["1", "2", "3"]
      }
    };

    test('Object structure', function() {
      same(
        personObj,
        personFixture,
        "Object structure is generated as expected"
      );
    });

    module('Objectify.fields');

    test('Objectify.fields() with no args returns the current filters', function () {

      Objectify.fields({
        id: Number,
        "something[id]": String
      });

      same(
        Objectify.fields(),
        { id: Number, "something[id]": String },
        "The filters passed into Objectify.fields have been stored correctly"
      );
    });

    test('field filters are persistent and additive', function () {

      function zipConverter (zip) {
        return zip + "-1234";
      }

      Objectify.fields({
        zip: zipConverter,
        "be_integers": Number,
        "be_floats": Number,
        date: String, // should not match
        good: Date, // should match
        bad: Date, // should be string
        "parseInt": Number
      });

      same(
        Objectify.fields(),
        {
          id: Number,
          "something[id]": String,
          zip: zipConverter,
          "be_integers": Number,
          "be_floats": Number,
          date: String,
          good: Date,
          bad: Date,
          "parseInt": Number
        },
        "The two Objectify.fields() objects have been combined together"
      );
    });

    var filtersObj;

    test('User-provided field filters are applied', function () {
      filtersObj = Objectify.convert($('form#filters-fixture').get(0));
      equal(filtersObj.something.zip, "68144-1234", "user-defined functions are used correctly");
    });

    test('Exact field matches take precedence over general matches', function () {
      ok(filtersObj.id === 1, "id was converted to Number");
      ok(filtersObj.something.id === "2", "something[id] filter overrode general id filter");
    });

    test('parseInt is used for Numbers with no decimal point', function () {
      same(filtersObj.these_should.be_strings, ["1", "2", "3"], "these_should[be_strings][] were combined into an array but left untouched");
      same(filtersObj.these_should.be_integers, [4, 5, 6], "these_should[be_integers][] were parsed into an array of integers");
      same(filtersObj.these_should.be_floats, [10.1, 10.2, 10.3], "these_should[be_floats][] were parsed into an array of floats");
    });

    test('Number data types correctly avoid the parseInt octal bug', function () {
      ok(filtersObj.testing.parseInt === 9, "testing[parseInt] was parsed into a base-10 integer");
    });

    test('Date parsing', function () {
      var testDate = new Date("Wed Aug 25 2010 21:14:47 GMT-0500 (CST)");
      ok(filtersObj.date.good instanceof Date, "date was correctly converted to Date instance");
      same(filtersObj.date.good, testDate, "Date matches");
      equal(filtersObj.date.bad, "2010-8-25 9pm", "non-parsable date should be left as String");
    });

    test('Objectify.fields.clear() removes filters', function () {
      Objectify.fields.clear();
      same(Objectify.fields(), {}, "Fields filters are now empty");
    });

  });

})(jQuery);<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

CLASS({
  package: 'foam.ui',
  name: 'BasePropertyView',
  extendsModel: 'foam.ui.BaseView',

  documentation: function() {/*
    Apply this trait to a $$DOC{ref:'BaseView'} (such as $$DOC{ref:'HTMLView'}).

Used by $$DOC{ref:'foam.ui.DetailView'} to generate a sub-$$DOC{ref:'foam.ui.View'} for one
    $$DOC{ref:'Property'}. The $$DOC{ref:'foam.ui.View'} chosen can be based off the
    $$DOC{ref:'Property.view',text:'Property.view'} value, the $$DOC{ref:'.innerView'} value, or
    $$DOC{ref:'.args'}.model_.
  */},

  properties: [
    {
      name: 'prop',
      type: 'Property',
      documentation: function() {/*
          The $$DOC{ref:'Property'} for which to generate a $$DOC{ref:'foam.ui.View'}.
      */},
      postSet: function(old, nu) {
        if ( old && this.bound_ ) this.unbindData(this.data);
        if ( nu && ! this.bound_ ) this.bindData(this.data);
      }
    },
    {
      name: 'data',
      documentation: function() {/*
          The $$DOC{ref:'.data'} for which to generate a $$DOC{ref:'foam.ui.View'}.
      */},
      postSet: function(old, nu) {
        if ( old && this.bound_ ) this.unbindData(old);
        if ( nu ) this.bindData(nu);
      }
    },
    {
      name: 'childData'
    },
    {
      name: 'parent',
      type: 'foam.ui.View',
      postSet: function(_, p) {
        if ( ! p ) return; // TODO(jacksonic): We shouldn't pretend we aren't part of the tree
        p[this.prop.name + 'View'] = this.view;
        if ( this.view ) this.view.parent = p;
      },
      documentation: function() {/*
        The $$DOC{ref:'foam.ui.View'} to use as the parent container for the new
        sub-$$DOC{ref:'foam.ui.View'}.
      */}
    },
    {
      name: 'innerView',
      help: 'Override for prop.view',
      documentation: function() {/*
        The optional name of the desired sub-$$DOC{ref:'foam.ui.View'}. If not specified,
        prop.$$DOC{ref:'Property.view'} is used.
      */}
    },
    {
      name: 'view',
      type: 'foam.ui.View',
      adapt: function(_, v) { return v && v.toView_ ? v.toView_() : v; },
      documentation: function() {/*
        The new sub-$$DOC{ref:'foam.ui.View'} generated for the given $$DOC{ref:'Property'}.
      */}
    },
    {
      name: 'args',
      documentation: function() {/*
        Optional arguments to be used for sub-$$DOC{ref:'foam.ui.View'} creation. args.model_
        in particular specifies the exact $$DOC{ref:'foam.ui.View'} to use.
      */}
    },
    {
      name: 'bound_',
      model_: 'BooleanProperty',
      defaultValue: false
    }
  ],

  methods: {
    init: function() {
      this.SUPER();
      this.construct();
    },

    fromElement: function(e) {
      this.view.fromElement(e);
      return this;
    },

    createViewFromProperty: function(prop, ret) {
      /* Helper to determine the $$DOC{ref:'foam.ui.View'} to use. */
      var viewName = this.innerView || prop.view || 'foam.ui.TextFieldView';
      if ( typeof viewName === 'string' ) {
//        var m = this.Y.lookup(viewName);
//        if ( m ) ret(m.create(prop, this.Y));
//        else
          arequire(viewName, this.X)(function(m) {
            ret(m.create({__proto__: prop, view: undefined}, this.Y).toView_());
          }.bind(this));
      }
      else if ( viewName.model_ && typeof viewName.model_ === 'string' ) {
        var m = FOAM(prop.view);
        m.arequire()(ret);
      }
      else if ( viewName.model_ ) {
        var v = viewName.model_.create(viewName, this.X);
        var vId = v.id;
        v.copyFrom(prop);
        v.id = vId;
        ret(v);
      }
      else if ( viewName.factory_ ) {
        var v = this.X.lookup(viewName.factory_).create(viewName, this.X).toView_();
        var vId = v.id;
        v.copyFrom({__proto__: prop, view: undefined});
        v.id = vId;
        ret(v);
      }
      else if ( typeof viewName === 'function' ) ret(viewName(prop, this));

      else ret(viewName.create(prop));
    },

    unbindData: function(oldData) {
      if ( ! this.bound_ || ! oldData || ! this.prop ) return;
      var pValue = oldData.propertyValue(this.prop.name);
      Events.unlink(pValue, this.childData$);
      this.bound_ = false;
    },

    bindData: function(data) {
      if ( this.bound_ || ! data || ! this.prop) return;
      var pValue = data.propertyValue(this.prop.name);
      Events.link(pValue, this.childData$);
      this.bound_ = true;
    },

    toString: function() { /* Name info. */ return 'PropertyView(' + this.prop.name + ', ' + this.view + ')'; },

    destroy: function( isParentDestroyed ) { /* Passthrough to $$DOC{ref:'.view'} */
      // always unbind, since if our parent was the top level destroy we need
      // to unhook if we were created as an addSelfDataChild
      this.unbindData(this.data);
      this.SUPER( isParentDestroyed );
    },

    finishPropertyRender: function() { /* Implement to render your property. */ },

    construct: function() {
      // if not bound yet and we do have data set, bind it
      this.bindData(this.data);

      if ( this.args && this.args.model_ ) {
        var model = this.Y.lookup(this.args.model_);
        console.assert( model, 'Unknown View: ' + this.args.model_);
        // HACK to make sure model specification makes it into the create
        if ( this.args.model ) this.prop.model = this.args.model;
        var view = model.create(this.prop, this.Y);
        delete this.args.model_;
        // syncronous case
        this.finishConstruct(view, this.finishPropertyRender.bind(this));
      } else {
        view = this.createViewFromProperty(this.prop,
                 function(v) {
                   this.finishConstruct(v, this.finishPropertyRender.bind(this));
                 }.bind(this));
      }
    },

    finishConstruct: function(view, ret) {
      view.copyFrom(this.args);
      view.parent = this.parent;
      view.prop = this.prop;

      // TODO(kgr): re-enable when improved
      // if ( this.prop.description || this.prop.help ) view.tooltip = this.prop.description || this.prop.help;

      this.view = view;
      this.addDataChild(view);

      ret && ret();
    },

    addDataChild: function(child) {
      Events.link(this.childData$, child.data$);
      this.addChild(child);
    }
  },

});
<commit_msg>Fixed PropertyView factory case when model not yet required. Async!<commit_after>/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

CLASS({
  package: 'foam.ui',
  name: 'BasePropertyView',
  extendsModel: 'foam.ui.BaseView',

  documentation: function() {/*
    Apply this trait to a $$DOC{ref:'BaseView'} (such as $$DOC{ref:'HTMLView'}).

Used by $$DOC{ref:'foam.ui.DetailView'} to generate a sub-$$DOC{ref:'foam.ui.View'} for one
    $$DOC{ref:'Property'}. The $$DOC{ref:'foam.ui.View'} chosen can be based off the
    $$DOC{ref:'Property.view',text:'Property.view'} value, the $$DOC{ref:'.innerView'} value, or
    $$DOC{ref:'.args'}.model_.
  */},

  properties: [
    {
      name: 'prop',
      type: 'Property',
      documentation: function() {/*
          The $$DOC{ref:'Property'} for which to generate a $$DOC{ref:'foam.ui.View'}.
      */},
      postSet: function(old, nu) {
        if ( old && this.bound_ ) this.unbindData(this.data);
        if ( nu && ! this.bound_ ) this.bindData(this.data);
      }
    },
    {
      name: 'data',
      documentation: function() {/*
          The $$DOC{ref:'.data'} for which to generate a $$DOC{ref:'foam.ui.View'}.
      */},
      postSet: function(old, nu) {
        if ( old && this.bound_ ) this.unbindData(old);
        if ( nu ) this.bindData(nu);
      }
    },
    {
      name: 'childData'
    },
    {
      name: 'parent',
      type: 'foam.ui.View',
      postSet: function(_, p) {
        if ( ! p ) return; // TODO(jacksonic): We shouldn't pretend we aren't part of the tree
        p[this.prop.name + 'View'] = this.view;
        if ( this.view ) this.view.parent = p;
      },
      documentation: function() {/*
        The $$DOC{ref:'foam.ui.View'} to use as the parent container for the new
        sub-$$DOC{ref:'foam.ui.View'}.
      */}
    },
    {
      name: 'innerView',
      help: 'Override for prop.view',
      documentation: function() {/*
        The optional name of the desired sub-$$DOC{ref:'foam.ui.View'}. If not specified,
        prop.$$DOC{ref:'Property.view'} is used.
      */}
    },
    {
      name: 'view',
      type: 'foam.ui.View',
      adapt: function(_, v) { return v && v.toView_ ? v.toView_() : v; },
      documentation: function() {/*
        The new sub-$$DOC{ref:'foam.ui.View'} generated for the given $$DOC{ref:'Property'}.
      */}
    },
    {
      name: 'args',
      documentation: function() {/*
        Optional arguments to be used for sub-$$DOC{ref:'foam.ui.View'} creation. args.model_
        in particular specifies the exact $$DOC{ref:'foam.ui.View'} to use.
      */}
    },
    {
      name: 'bound_',
      model_: 'BooleanProperty',
      defaultValue: false
    }
  ],

  methods: {
    init: function() {
      this.SUPER();
      this.construct();
    },

    fromElement: function(e) {
      this.view.fromElement(e);
      return this;
    },

    createViewFromProperty: function(prop, ret) {
      /* Helper to determine the $$DOC{ref:'foam.ui.View'} to use. */
      var viewName = this.innerView || prop.view || 'foam.ui.TextFieldView';
      if ( typeof viewName === 'string' ) {
//        var m = this.Y.lookup(viewName);
//        if ( m ) ret(m.create(prop, this.Y));
//        else
          arequire(viewName, this.X)(function(m) {
            ret(m.create({__proto__: prop, view: undefined}, this.Y).toView_());
          }.bind(this));
      }
      else if ( viewName.model_ && typeof viewName.model_ === 'string' ) {
        var m = FOAM(prop.view);
        m.arequire()(ret);
      }
      else if ( viewName.model_ ) {
        var v = viewName.model_.create(viewName, this.X);
        var vId = v.id;
        v.copyFrom(prop);
        v.id = vId;
        ret(v);
      }
      else if ( viewName.factory_ ) {
        arequire(viewName.factory_, this.X)(function(m) {
          var v = m.create(viewName, this.X).toView_();
          var vId = v.id;
          v.copyFrom({__proto__: prop, view: undefined});
          v.id = vId;
          ret(v);
        }.bind(this));
      }
      else if ( typeof viewName === 'function' ) ret(viewName(prop, this));

      else ret(viewName.create(prop));
    },

    unbindData: function(oldData) {
      if ( ! this.bound_ || ! oldData || ! this.prop ) return;
      var pValue = oldData.propertyValue(this.prop.name);
      Events.unlink(pValue, this.childData$);
      this.bound_ = false;
    },

    bindData: function(data) {
      if ( this.bound_ || ! data || ! this.prop) return;
      var pValue = data.propertyValue(this.prop.name);
      Events.link(pValue, this.childData$);
      this.bound_ = true;
    },

    toString: function() { /* Name info. */ return 'PropertyView(' + this.prop.name + ', ' + this.view + ')'; },

    destroy: function( isParentDestroyed ) { /* Passthrough to $$DOC{ref:'.view'} */
      // always unbind, since if our parent was the top level destroy we need
      // to unhook if we were created as an addSelfDataChild
      this.unbindData(this.data);
      this.SUPER( isParentDestroyed );
    },

    finishPropertyRender: function() { /* Implement to render your property. */ },

    construct: function() {
      // if not bound yet and we do have data set, bind it
      this.bindData(this.data);

      if ( this.args && this.args.model_ ) {
        var model = this.Y.lookup(this.args.model_);
        console.assert( model, 'Unknown View: ' + this.args.model_);
        // HACK to make sure model specification makes it into the create
        if ( this.args.model ) this.prop.model = this.args.model;
        var view = model.create(this.prop, this.Y);
        delete this.args.model_;
        // syncronous case
        this.finishConstruct(view, this.finishPropertyRender.bind(this));
      } else {
        view = this.createViewFromProperty(this.prop,
                 function(v) {
                   this.finishConstruct(v, this.finishPropertyRender.bind(this));
                 }.bind(this));
      }
    },

    finishConstruct: function(view, ret) {
      view.copyFrom(this.args);
      view.parent = this.parent;
      view.prop = this.prop;

      // TODO(kgr): re-enable when improved
      // if ( this.prop.description || this.prop.help ) view.tooltip = this.prop.description || this.prop.help;

      this.view = view;
      this.addDataChild(view);

      ret && ret();
    },

    addDataChild: function(child) {
      Events.link(this.childData$, child.data$);
      this.addChild(child);
    }
  },

});
<|endoftext|>


<commit_before>/**
 *    Copyright (C) 2015 Deco Software Inc.
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

'use strict'

import fs from 'fs'
import path from 'path'
import child_process from 'child_process'
import mv from 'mv'
import mkdirp from 'mkdirp'

import fs_plus from 'fs-plus'
import _ from 'lodash'

import bridge from '../bridge'
import {
  onError,
  onSuccess,
} from '../actions/genericActions'
import {
  setProject,
} from '../actions/projectActions'
import ProjectConstants from 'shared/constants/ipc/ProjectConstants'
const {
  CREATE_NEW_PROJECT,
  OPEN_PROJECT,
  SHARE_SAVE_STATUS,
} = ProjectConstants

import {
  TEMP_PROJECT_FOLDER,
  TEMP_PROJECT_FOLDER_TEMPLATE,
  LIB_PROJECT_FOLDER,
} from '../constants/DecoPaths'

import SimulatorController from '../process/simulatorController'
import PackagerController from '../process/packagerController'

import Logger from '../log/logger'

let unsavedMap = {}

const PROJECT_SETTINGS_TEMPLATE = (projectName) => `{

  // relative path from project root to the .app binary that is generated after building iOS
  "iosTarget": "ios/build/Build/Products/Debug-iphonesimulator/${projectName}.app",

  // relative path from project root to the xcode project or workspace file for iOS build
  "iosProject": "ios/${projectName}.xcodeproj",

  // scheme name to use when building in Deco
  "iosBuildScheme": "${projectName}",

  // relative path from project to the AndroidManifest.xml file for your application
  "androidManifest": "android/app/src/main/AndroidManifest.xml",

  // port for the packager to run on
  "packagerPort": 8081
}`

class ProjectHandler {

  hasUnsavedProgress() {
    return _.keys(unsavedMap).length != 0
  }

  register() {
    bridge.on(CREATE_NEW_PROJECT, this.createNewProject.bind(this))
    bridge.on(OPEN_PROJECT, this.openProject.bind(this))
    bridge.on(SHARE_SAVE_STATUS, this.updateSaveStatus.bind(this))
  }

  updateSaveStatus(payload, respond) {
    try {
      if (payload.status) {
        unsavedMap[payload.id] = payload.status
      } else {
        delete unsavedMap[payload.id]
      }
    } catch(e) {
      Logger.error(e)
    }
    respond(onSuccess(SHARE_SAVE_STATUS))
  }

  _deleteProject(root) {
    const deletePath = root + '.delete'
    try {
      fs.statSync(root)
    } catch(e) {
      // Trying to delete a project that does not exist eh?
      Logger.error(e)
      return
    }
    try {
      fs_plus.moveSync(root, deletePath)
      child_process.spawn('rm', ['-rf', deletePath, ])
    } catch(e) {
      Logger.error(e)
    }
  }

  cleanBuildDir(root) {
    try {
      const pathsToClean = [
        path.join(root, 'ios/build/ModuleCache'),
        path.join(root, 'ios/build/info.plist'),
        path.join(root, 'ios/build/Build/Intermediates'),
      ]
      _.each(pathsToClean, (filename) => {
        child_process.spawn('rm', ['-rf', filename, ])
      })
    } catch (e) {
      Logger.error(e)
    }
  }

  _createTemplateFolder() {
    return new Promise((resolve, reject) => {
      try {
        child_process.spawn('cp', ['-rf', path.join(LIB_PROJECT_FOLDER), TEMP_PROJECT_FOLDER_TEMPLATE])
        .on('close', (code) => {
          if (code != 0) {
            Logger.error(`Project template creation exited with code: ${code}`)
            reject()
          } else {
            resolve()
          }
        })
      } catch (e) {
        Logger.error(e)
        return
      }
    })
  }

  _resetProcessState() {
    try {
      SimulatorController.clearLastSimulator()
      PackagerController.killPackager()
    } catch (e) {
      Logger.error(e)
    }
  }

  createNewProject(payload, respond) {
    this._resetProcessState()
    try {
      payload.path = TEMP_PROJECT_FOLDER
      this._deleteProject(payload.path)
      const createProj = () => {
        fs.rename(TEMP_PROJECT_FOLDER_TEMPLATE, TEMP_PROJECT_FOLDER, (err) => {
          if (err) {
            Logger.error(err)
            respond(onError(err))
            return
          }
          respond(onSuccess(CREATE_NEW_PROJECT))
          bridge.send(setProject(payload.path, payload.tmp))
          this._createTemplateFolder()
          this.createProjectSettingsTemplate(payload.path)
        })
        unsavedMap = {}
      }

      try {
        fs.statSync(TEMP_PROJECT_FOLDER_TEMPLATE)
      } catch (e) {
        this._createTemplateFolder().then(() => {
          createProj()
        })
        return
      }
      createProj()

    } catch (e) {
      Logger.error(e)
    }
  }

  createProjectSettingsTemplate(rootPath) {
    return new Promise((resolve, reject) => {
      const metadataPath = path.join(rootPath, '.deco')
      const settingsFilePath = path.join(metadataPath, '.settings')
      const assumedProjectName = path.basename(rootPath)
      try {
        fs.statSync(settingsFilePath)
        resolve(settingsFilePath)
      } catch (e) {
        if (e && e.code == 'ENOENT') {
          mkdirp(metadataPath, () => {
            try {
              fs.writeFileSync(settingsFilePath, PROJECT_SETTINGS_TEMPLATE(assumedProjectName), {
                mode: '755'
              })
              resolve(settingsFilePath)
            } catch (e) {
              //could not write out the file
              Logger.error('Failed to write settings file template', e)
              reject()
            }
          })
        } else {
          Logger.error(e)
          reject()
        }
      }
    })
  }

  /**
   * Backwards compatability!
   */
  updateOldProjectStructure(rootPath) {
    const oldMetadata = path.join(rootPath, '.deco')
    const list = fs.readdirSync(oldMetadata)
    _.each(list, (sub) => {
      const oldPath = path.join(oldMetadata, sub)
      const newPath = path.join(oldMetadata, 'metadata', sub)
      mv(oldPath, newPath, {mkdirp: true}, (err) => {
        if (err) {
          Logger.error(err)
        }
      })
    })
    // add .settings file
    this.createProjectSettingsTemplate(rootPath)
  }

  /**
   * Backwards compatability!
   */
  checkOldProjectStructure(rootPath) {
    const oldMetadataPath = path.join(rootPath, '.deco')
    const newMetadataPath = path.join(oldMetadataPath, 'metadata')
    fs.stat(oldMetadataPath, (err, stats) => {
      if (err) {
        //project is clean
        return
      }

      fs.stat(newMetadataPath, (err, stats) => {
        if (!err) {
          return //project is current
        }
        if (err.code == 'ENOENT') {
          //this is an old project structure
          this.updateOldProjectStructure(rootPath)
        } else {
          Logger.error(err)
          return //something went wrong
        }
      })
    })
  }

  openProject(payload, respond) {
    if (!payload.resumeState) {
      this._resetProcessState()
    }
    unsavedMap = {}
    bridge.send(setProject(payload.path, false))
    this.checkOldProjectStructure(payload.path)
    respond(onSuccess(OPEN_PROJECT))
  }
}

const handler = new ProjectHandler()
export default handler
<commit_msg>do not create settings template on new project creation<commit_after>/**
 *    Copyright (C) 2015 Deco Software Inc.
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

'use strict'

import fs from 'fs'
import path from 'path'
import child_process from 'child_process'
import mv from 'mv'
import mkdirp from 'mkdirp'

import fs_plus from 'fs-plus'
import _ from 'lodash'

import bridge from '../bridge'
import {
  onError,
  onSuccess,
} from '../actions/genericActions'
import {
  setProject,
} from '../actions/projectActions'
import ProjectConstants from 'shared/constants/ipc/ProjectConstants'
const {
  CREATE_NEW_PROJECT,
  OPEN_PROJECT,
  SHARE_SAVE_STATUS,
} = ProjectConstants

import {
  TEMP_PROJECT_FOLDER,
  TEMP_PROJECT_FOLDER_TEMPLATE,
  LIB_PROJECT_FOLDER,
} from '../constants/DecoPaths'

import SimulatorController from '../process/simulatorController'
import PackagerController from '../process/packagerController'

import Logger from '../log/logger'

let unsavedMap = {}

const PROJECT_SETTINGS_TEMPLATE = (projectName) => `{

  // relative path from project root to the .app binary that is generated after building iOS
  "iosTarget": "ios/build/Build/Products/Debug-iphonesimulator/${projectName}.app",

  // relative path from project root to the xcode project or workspace file for iOS build
  "iosProject": "ios/${projectName}.xcodeproj",

  // scheme name to use when building in Deco
  "iosBuildScheme": "${projectName}",

  // relative path from project to the AndroidManifest.xml file for your application
  "androidManifest": "android/app/src/main/AndroidManifest.xml",

  // port for the packager to run on
  "packagerPort": 8081
}`

class ProjectHandler {

  hasUnsavedProgress() {
    return _.keys(unsavedMap).length != 0
  }

  register() {
    bridge.on(CREATE_NEW_PROJECT, this.createNewProject.bind(this))
    bridge.on(OPEN_PROJECT, this.openProject.bind(this))
    bridge.on(SHARE_SAVE_STATUS, this.updateSaveStatus.bind(this))
  }

  updateSaveStatus(payload, respond) {
    try {
      if (payload.status) {
        unsavedMap[payload.id] = payload.status
      } else {
        delete unsavedMap[payload.id]
      }
    } catch(e) {
      Logger.error(e)
    }
    respond(onSuccess(SHARE_SAVE_STATUS))
  }

  _deleteProject(root) {
    const deletePath = root + '.delete'
    try {
      fs.statSync(root)
    } catch(e) {
      // Trying to delete a project that does not exist eh?
      Logger.error(e)
      return
    }
    try {
      fs_plus.moveSync(root, deletePath)
      child_process.spawn('rm', ['-rf', deletePath, ])
    } catch(e) {
      Logger.error(e)
    }
  }

  cleanBuildDir(root) {
    try {
      const pathsToClean = [
        path.join(root, 'ios/build/ModuleCache'),
        path.join(root, 'ios/build/info.plist'),
        path.join(root, 'ios/build/Build/Intermediates'),
      ]
      _.each(pathsToClean, (filename) => {
        child_process.spawn('rm', ['-rf', filename, ])
      })
    } catch (e) {
      Logger.error(e)
    }
  }

  _createTemplateFolder() {
    return new Promise((resolve, reject) => {
      try {
        child_process.spawn('cp', ['-rf', path.join(LIB_PROJECT_FOLDER), TEMP_PROJECT_FOLDER_TEMPLATE])
        .on('close', (code) => {
          if (code != 0) {
            Logger.error(`Project template creation exited with code: ${code}`)
            reject()
          } else {
            resolve()
          }
        })
      } catch (e) {
        Logger.error(e)
        return
      }
    })
  }

  _resetProcessState() {
    try {
      SimulatorController.clearLastSimulator()
      PackagerController.killPackager()
    } catch (e) {
      Logger.error(e)
    }
  }

  createNewProject(payload, respond) {
    this._resetProcessState()
    try {
      payload.path = TEMP_PROJECT_FOLDER
      this._deleteProject(payload.path)
      const createProj = () => {
        fs.rename(TEMP_PROJECT_FOLDER_TEMPLATE, TEMP_PROJECT_FOLDER, (err) => {
          if (err) {
            Logger.error(err)
            respond(onError(err))
            return
          }
          respond(onSuccess(CREATE_NEW_PROJECT))
          bridge.send(setProject(payload.path, payload.tmp))
          this._createTemplateFolder()
        })
        unsavedMap = {}
      }

      try {
        fs.statSync(TEMP_PROJECT_FOLDER_TEMPLATE)
      } catch (e) {
        this._createTemplateFolder().then(() => {
          createProj()
        })
        return
      }
      createProj()

    } catch (e) {
      Logger.error(e)
    }
  }

  createProjectSettingsTemplate(rootPath) {
    return new Promise((resolve, reject) => {
      const metadataPath = path.join(rootPath, '.deco')
      const settingsFilePath = path.join(metadataPath, '.settings')
      const assumedProjectName = path.basename(rootPath)
      try {
        fs.statSync(settingsFilePath)
        resolve(settingsFilePath)
      } catch (e) {
        if (e && e.code == 'ENOENT') {
          mkdirp(metadataPath, () => {
            try {
              fs.writeFileSync(settingsFilePath, PROJECT_SETTINGS_TEMPLATE(assumedProjectName), {
                mode: '755'
              })
              resolve(settingsFilePath)
            } catch (e) {
              //could not write out the file
              Logger.error('Failed to write settings file template', e)
              reject()
            }
          })
        } else {
          Logger.error(e)
          reject()
        }
      }
    })
  }

  /**
   * Backwards compatability!
   */
  updateOldProjectStructure(rootPath) {
    const oldMetadata = path.join(rootPath, '.deco')
    const list = fs.readdirSync(oldMetadata)
    _.each(list, (sub) => {
      const oldPath = path.join(oldMetadata, sub)
      const newPath = path.join(oldMetadata, 'metadata', sub)
      mv(oldPath, newPath, {mkdirp: true}, (err) => {
        if (err) {
          Logger.error(err)
        }
      })
    })
    // add .settings file
    this.createProjectSettingsTemplate(rootPath)
  }

  /**
   * Backwards compatability!
   */
  checkOldProjectStructure(rootPath) {
    const oldMetadataPath = path.join(rootPath, '.deco')
    const newMetadataPath = path.join(oldMetadataPath, 'metadata')
    fs.stat(oldMetadataPath, (err, stats) => {
      if (err) {
        //project is clean
        return
      }

      fs.stat(newMetadataPath, (err, stats) => {
        if (!err) {
          return //project is current
        }
        if (err.code == 'ENOENT') {
          //this is an old project structure
          this.updateOldProjectStructure(rootPath)
        } else {
          Logger.error(err)
          return //something went wrong
        }
      })
    })
  }

  openProject(payload, respond) {
    if (!payload.resumeState) {
      this._resetProcessState()
    }
    unsavedMap = {}
    bridge.send(setProject(payload.path, false))
    this.checkOldProjectStructure(payload.path)
    respond(onSuccess(OPEN_PROJECT))
  }
}

const handler = new ProjectHandler()
export default handler
<|endoftext|>


<commit_before>//////////////////
// sample tests //
//////////////////
/**

run:
node test.js

*/

var lme = require('./index');

function testAllLogFunctions() {
	var args = Array.prototype.slice.call(arguments);
	lme.d.apply(lme, args);
	lme.s.apply(lme, args);
	lme.w.apply(lme, args);
	lme.e.apply(lme, args);
	lme.h.apply(lme, args);
	lme.i.apply(lme, args);
	lme.t.apply(lme, args);
	lme.d('\n');
}

function testAllLineFunctions() {
	var args = Array.prototype.slice.call(arguments);
	lme.line.apply(lme, args);
	lme.dline.apply(lme, args);
	lme.sline.apply(lme, args);
	lme.wline.apply(lme, args);
	lme.eline.apply(lme, args);
	lme.hline.apply(lme, args);
}

// objects
testAllLogFunctions({ kity: 'is pinky', fluffy: 'is funny!' });

// strings
testAllLogFunctions('mango is sweet!');

//Multiple Params
testAllLogFunctions('mango is sweet!', { mango: 'sweet' });
testAllLogFunctions('mango is sweet!', '!!!');
testAllLogFunctions({ 'mango is': 'sweet' }, { 'mango is': 'sweet' });

// lines
testAllLineFunctions();
testAllLineFunctions('*', 10);
testAllLineFunctions('*', 110);

// error-ed outputs for lines
lme.i('\nerror-ed outputs');

testAllLineFunctions({ yu: 1 });

lme.i('test finished');
<commit_msg>adding couple lines of test.<commit_after>//////////////////
// sample tests //
//////////////////
/**

run:
node test.js

*/

var lme = require('./index');

function testAllLogFunctions() {
	var args = Array.prototype.slice.call(arguments);
	lme.d.apply(lme, args);
	lme.s.apply(lme, args);
	lme.w.apply(lme, args);
	lme.e.apply(lme, args);
	lme.h.apply(lme, args);
	lme.i.apply(lme, args);
	lme.t.apply(lme, args);
	lme.d('\n');
}

function testAllLineFunctions() {
	var args = Array.prototype.slice.call(arguments);
	lme.line.apply(lme, args);
	lme.dline.apply(lme, args);
	lme.sline.apply(lme, args);
	lme.wline.apply(lme, args);
	lme.eline.apply(lme, args);
	lme.hline.apply(lme, args);
	lme.iline.apply(lme, args);
	lme.tline.apply(lme, args);
}

// objects
testAllLogFunctions({ kity: 'is pinky', fluffy: 'is funny!' });

// strings
testAllLogFunctions('mango is sweet!');

//Multiple Params
testAllLogFunctions('mango is sweet!', { mango: 'sweet' });
testAllLogFunctions('mango is sweet!', '!!!');
testAllLogFunctions({ 'mango is': 'sweet' }, { 'mango is': 'sweet' });

// lines
testAllLineFunctions();
testAllLineFunctions('*', 10);
testAllLineFunctions('*', 110);

// error-ed outputs for lines
lme.i('\nerror-ed outputs');

testAllLineFunctions({ yu: 1 });

lme.i('test finished');
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

CLASS({
  name: 'TextFieldView',
  package: 'foam.ui.md',
  extendsModel: 'View',

  properties: [
    {
      name: 'className',
      defaultValueFn: function() {
        return 'md-text-field-container' + (this.floatingLabel ?
            '' : ' md-text-field-no-label');
      }
    },
    { name: 'data' },
    { name: 'softData' },
    { name: 'inputId' },
    { name: '$input', getter: function() { return this.X.$(this.inputId); } },
    { name: 'labelId' },
    { name: '$label', getter: function() { return this.X.$(this.labelId); } },
    { model_: 'BooleanProperty', name: 'focused', defaultValue: false },
    'prop',
    { name: 'label', defaultValueFn: function() { return this.prop.label; } },
    { model_: 'BooleanProperty', name: 'onKeyMode', defautlValue: false },
    { model_: 'IntProperty', name: 'displayHeight' },
    { model_: 'IntProperty', name: 'displayWidth' },
    {
      model_: 'BooleanProperty',
      name: 'floatingLabel',
      documentation: 'Set true for the floating label (see MD spec) by ' +
          'default, but can be disabled where the label is redundant.',
      defaultValue: true
    },
    {
      name: 'clearAction',
      documentation: 'When true, will show an X for clearing the text box.',
      defaultValue: false
    }
  ],
  methods: {
    initHTML: function() {
      this.SUPER();
      this.softValue = DomValue.create(this.$input, 'input');
      this.softValue.set(this.data);
      Events.link(this.softValue, this.softData$);

      if ( this.onKeyMode ) {
        Events.link(this.data$, this.softData$);
      } else {
        Events.follow(this.data$, this.softData$);
      }
    },
    focus: function() {
      this.$input.focus();
    }
  },
  templates: [
    function CSS() {/*
      .md-text-field-container {
        align-items: center;
        width: 100%;
        display: flex;
        position: relative;
      }
      .md-text-field-label {
        position: absolute;
        top: 40px;
        font-size: 14px;
        font-weight: 500;
        color: #999;
        transition: font-size 0.5s, top 0.5s;
        flex-grow: 1;
        margin-left: 16px;
        z-index: 0;
      }
      .md-text-field-input {
        background: transparent;
        border-bottom: 1px solid #e0e0e0 !important;
        border: none;
        color: #444;
        flex-grow: 1;
        font-family: Roboto;
        font-size: 14px;
        margin: 40px 16px 8px;
        padding: 0 0 7px 0;
        resize: none;
        z-index: 1;
      }
      .md-text-field-container.md-text-field-no-label .md-text-field-input {
        font-size: 16px;
        margin: 8px 0;
        padding: 8px 2px;
      }

      .md-text-field-input:focus {
        border-bottom: 2px solid #0288D1;
        padding: 0 0 6px 0;
        outline: none;
      }
      .md-text-field-label-offset {
        font-size: 12px;
        top: 16px;
      }
    */},
    function toHTML() {/*
      <%
        var input = this.inputId = this.nextID();
        var label = this.labelId = this.nextID();

        this.on('focus',   this.onFocus,   input);
        this.on('blur',    this.onBlur,    input);
        this.on('input',   this.onInput,   input);
        this.on('change',  this.onChange,  input);
        this.on('click',   this.onClick,   input);
        this.on('keydown', this.onKeyDown, input);

        if ( this.floatingLabel ) {
          this.setClass('md-text-field-label-offset',
            function() {
              var focused = self.focused;
              var data    = self.data;
              return focused || ('' + data).length > 0;
            }, label);
        }
      %>

        <% if (this.floatingLabel) { %>
          %%label
        <% } %>
        <% if ( this.displayHeight > 1 ) { %>
          <textarea id="{{{input}}}" type="text" class="md-text-field-input" rows="{{{this.displayHeight}}}"></textarea>
        <% } else { %>
          <input id="{{{input}}}" type="text" class="md-text-field-input"
              <%= this.floatingLabel ? '' : 'placeholder="' + this.label + '"' %> />
          <% if ( this.clearAction ) { %>
            $$clear
          <% } %>
        <% } %>

    */}
  ],

  actions: [
    {
      name: 'clear',
      label: '',
      iconUrl: 'images/ic_cancel_24dp.png',
      isAvailable: function() { return !! this.softData.length; },
      action: function() {
        this.softData = '';
      }
    }
  ],

  listeners: [
    {
      name: 'onFocus',
      code: function() {
        this.focused = true;
      }
    },
    {
      name: 'onBlur',
      code: function() {
        this.focused = false;
      }
    },
    {
      name: 'onInput',
      code: function() {
      }
    },
    {
      name: 'onChange',
      code: function() {
        this.data = this.softData;
      }
    },
    {
      name: 'onKeyDown',
      code: function() {
      }
    },
    {
      name: 'onClick',
      code: function() {
        this.$input.focus();
      }
    }
  ]
});
<commit_msg>MD TextFieldView: Add "growable" property that uses a contenteditable div<commit_after>/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

CLASS({
  name: 'TextFieldView',
  package: 'foam.ui.md',
  extendsModel: 'View',

  properties: [
    {
      name: 'className',
      defaultValueFn: function() {
        return 'md-text-field-container' + (this.floatingLabel ?
            '' : ' md-text-field-no-label');
      }
    },
    { name: 'data' },
    { name: 'softData' },
    { name: 'inputId' },
    { name: '$input', getter: function() { return this.X.$(this.inputId); } },
    { name: 'labelId' },
    { name: '$label', getter: function() { return this.X.$(this.labelId); } },
    { model_: 'BooleanProperty', name: 'focused', defaultValue: false },
    'prop',
    { name: 'label', defaultValueFn: function() { return this.prop.label; } },
    { model_: 'BooleanProperty', name: 'onKeyMode', defautlValue: false },
    { model_: 'IntProperty', name: 'displayHeight' },
    { model_: 'IntProperty', name: 'displayWidth' },
    {
      model_: 'BooleanProperty',
      name: 'floatingLabel',
      documentation: 'Set true for the floating label (see MD spec) by ' +
          'default, but can be disabled where the label is redundant.',
      defaultValue: true
    },
    {
      model_: 'BooleanProperty',
      name: 'growable',
      documentation: 'Set true if this text area should grow with the text.',
      defaultValue: false
    },
    {
      name: 'clearAction',
      documentation: 'When true, will show an X for clearing the text box.',
      defaultValue: false
    }
  ],
  methods: {
    initHTML: function() {
      this.SUPER();
      this.softValue = DomValue.create(this.$input, 'input',
          this.growable ? 'textContent' : 'value');
      this.softValue.set(this.data);
      Events.link(this.softValue, this.softData$);

      if ( this.onKeyMode ) {
        Events.link(this.data$, this.softData$);
      } else {
        Events.follow(this.data$, this.softData$);
      }
    },
    focus: function() {
      this.$input.focus();
    }
  },
  templates: [
    function CSS() {/*
      .md-text-field-container {
        align-items: center;
        width: 100%;
        display: flex;
        position: relative;
      }
      .md-text-field-label {
        position: absolute;
        top: 40px;
        font-size: 14px;
        font-weight: 500;
        color: #999;
        transition: font-size 0.5s, top 0.5s;
        flex-grow: 1;
        margin-left: 16px;
        z-index: 0;
      }
      .md-text-field-input {
        background: transparent;
        border-bottom: 1px solid #e0e0e0 !important;
        border: none;
        color: #444;
        flex-grow: 1;
        font-family: Roboto;
        font-size: 14px;
        margin: 40px 16px 8px;
        padding: 0 0 7px 0;
        resize: none;
        z-index: 1;
      }
      .md-text-field-container.md-text-field-no-label .md-text-field-input {
        font-size: 16px;
        margin: 8px 0;
        padding: 8px 2px;
      }

      .md-text-field-input:focus {
        border-bottom: 2px solid #0288D1;
        padding: 0 0 6px 0;
        outline: none;
      }
      .md-text-field-label-offset {
        font-size: 12px;
        top: 16px;
      }
    */},
    function toHTML() {/*
      <%
        var input = this.inputId = this.nextID();
        var label = this.labelId = this.nextID();

        this.on('focus',   this.onFocus,   input);
        this.on('blur',    this.onBlur,    input);
        this.on('input',   this.onInput,   input);
        this.on('change',  this.onChange,  input);
        this.on('click',   this.onClick,   input);
        this.on('keydown', this.onKeyDown, input);

        if ( this.floatingLabel ) {
          this.setClass('md-text-field-label-offset',
            function() {
              var focused = self.focused;
              var data    = self.data;
              return focused || ('' + data).length > 0;
            }, label);
        }
      %>

        <% if (this.floatingLabel) { %>
          %%label
        <% } %>
        <% if ( this.growable ) { %>

        <% } else if ( this.displayHeight > 1 ) { %>
          <textarea id="{{{input}}}" type="text" class="md-text-field-input" rows="{{{this.displayHeight}}}"></textarea>
        <% } else { %>
          <input id="{{{input}}}" type="text" class="md-text-field-input"
              <%= this.floatingLabel ? '' : 'placeholder="' + this.label + '"' %> />
          <% if ( this.clearAction ) { %>
            $$clear
          <% } %>
        <% } %>

    */}
  ],

  actions: [
    {
      name: 'clear',
      label: '',
      iconUrl: 'images/ic_cancel_24dp.png',
      isAvailable: function() { return !! this.softData.length; },
      action: function() {
        this.softData = '';
      }
    }
  ],

  listeners: [
    {
      name: 'onFocus',
      code: function() {
        this.focused = true;
      }
    },
    {
      name: 'onBlur',
      code: function() {
        this.focused = false;
      }
    },
    {
      name: 'onInput',
      code: function() {
      }
    },
    {
      name: 'onChange',
      code: function() {
        this.data = this.softData;
      }
    },
    {
      name: 'onKeyDown',
      code: function() {
      }
    },
    {
      name: 'onClick',
      code: function() {
        this.$input.focus();
      }
    }
  ]
});
<|endoftext|>