<commit_before>'use strict';

var _ = require('lodash');
var moment = window.moment;
var times = require('../times');
var d3 = (global && global.d3) || require('d3');

var weektoweek = {
  name: 'weektoweek'
  , label: 'Week to week'
  , pluginType: 'report'
};

function init() {
  return weektoweek;
}

module.exports = init;

weektoweek.html = function html(client) {
  var translate = client.translate;
  var ret =
    '
' + translate('Week to week') + '
'
    + '' + translate('To see this report, press SHOW while in this view') + '
'
    + ' '+translate('Size')
    + ' <select id="rp_size">'
    + '  <option x="800" y="250">800x250px</option>'
    + '  <option x="1000" y="300" selected>1000x300px</option>'
    + '  <option x="1200" y="400">1200x400px</option>'
    + '  <option x="1550" y="600">1550x600px</option>'
    + '</select>'
    + '
'
    + translate('Scale') + ': '
    + '<input type="radio" name="rp_scale" id="rp_linear" checked>'
    + translate('Linear')
    + '<input type="radio" name="rp_scale" id="rp_log">'
    + translate('Logarithmic')
    + '
'
    + '
'
    + '
'
    ;
    return ret;
};

weektoweek.prepareHtml = function weektoweekPrepareHtml(weekstoshow) {
  $('#weektoweekcharts').html('');
  weekstoshow.forEach(function eachWeek(d) {
    $('#weektoweekcharts').append($('

'));
  });
};

weektoweek.report = function report_weektoweek(datastorage,sorteddaystoshow,options) {
  var Nightscout = window.Nightscout;
  var client = Nightscout.client;
  var translate = client.translate;
  var profile = client.sbx.data.profile;
  var report_plugins = Nightscout.report_plugins;
  var scaledTreatmentBG = report_plugins.utils.scaledTreatmentBG;

  var TOOLTIP_TRANS_MS = 300;

  var padding = { top: 15, right: 22, bottom: 30, left: 35 };

  var tddSum = 0;
  var carbsSum = 0;

  var weekstoshow = [ ];
  var weekIdx = 0;
  var dayIdx = 0;
  var firstDayOfWeek = moment.localeData().firstDayOfWeek();

  sorteddaystoshow.forEach( function eachDay(day) {
    if (moment(day).day() === firstDayOfWeek) {
      weekIdx += 1;
      dayIdx = 0;
      weekstoshow[weekIdx][dayIdx] = day;
    } else {
      weekstoshow[weekIdx][dayIdx] = day;
      dayIdx += 1;
    }
  });

  daytoday.prepareHtml(weekstoshow);

  weekstoshow.forEach( function eachWeek(week) {
    day.forEach( function eachDay(week) {
      drawChart(week, day, datastorage[day], options);
    });
  });

  function timeTicks(n,i) {
    var t12 = [
      '12am', '', '2am', '', '4am', '', '6am', '', '8am', '', '10am', '',
      '12pm', '', '2pm', '', '4pm', '', '6pm', '', '8pm', '', '10pm', '', '12am'
    ];
    if (Nightscout.client.settings.timeFormat === 24) {
      return ('00' + i).slice(-2);
    } else {
      return t12[i];
    }
  }

  function drawChart(week,day,data,options) {
    var tickValues
      , charts
      , context
      , xScale2, yScale2
      , yInsulinScale, yCarbsScale, yScaleBasals
      , xAxis2, yAxis2
      , dateFn = function (d) { return new Date(d.date); }
      , foodtexts = 0;

   tickValues = client.ticks(client, {
     scaleY: options.scale === report_plugins.consts.SCALE_LOG ? 'log' : 'linear'
     , targetTop: options.targetHigh
     , targetBottom: options.targetLow
   });

  // add defs for combo boluses
  var dashWidth = 5;
  d3.select('body').append('svg')
    .append('defs')
    .append('pattern')
      .attr('id', 'hash')
      .attr('patternUnits', 'userSpaceOnUse')
      .attr('width', 6)
      .attr('height', 6)
      .attr('x', 0)
      .attr('y', 0)
      .append('g')
        .style('fill', 'none')
        .style('stroke', '#0099ff')
        .style('stroke-width', 2)
      .append('path').attr('d', 'M0,0 l' + dashWidth + ',' + dashWidth)
      .append('path').attr('d', 'M' + dashWidth + ',0 l-' + dashWidth + ',' + dashWidth);

    // create svg and g to contain the chart contents
    charts = d3.select('#weektoweekchart-' + week[0] + '-' + week[week.length-1]).html(
      ''+
      report_plugins.utils.localeDate(day)+
      '
'
      ).append('svg');

    charts.append('rect')
      .attr('width', '100%')
      .attr('height', '100%')
      .attr('fill', 'WhiteSmoke');

    context = charts.append('g');

    // define the parts of the axis that aren't dependent on width or height
    xScale2 = d3.time.scale()
      .domain(d3.extent(data.sgv, dateFn));

    if (options.scale === report_plugins.consts.SCALE_LOG) {
      yScale2 = d3.scale.log()
        .domain([client.utils.scaleMgdl(options.basal ? 30 : 36), client.utils.scaleMgdl(420)]);
    } else {
      yScale2 = d3.scale.linear()
        .domain([client.utils.scaleMgdl(options.basal ? -40 : 36), client.utils.scaleMgdl(420)]);
    }

    xAxis2 = d3.svg.axis()
      .scale(xScale2)
      .tickFormat(timeTicks)
      .ticks(24)
      .orient('bottom');

    yAxis2 = d3.svg.axis()
      .scale(yScale2)
      .tickFormat(d3.format('d'))
      .tickValues(tickValues)
      .orient('left');

    // get current data range
    var dataRange = d3.extent(data.sgv, dateFn);

    // get the entire container height and width subtracting the padding
    var chartWidth = options.width - padding.left - padding.right;
    var chartHeight = options.height - padding.top - padding.bottom;

    //set the width and height of the SVG element
    charts.attr('width', options.width)
      .attr('height', options.height);

    // ranges are based on the width and height available so reset
    xScale2.range([0, chartWidth]);
    yScale2.range([chartHeight,0]);

    // add target BG rect
    context.append('rect')
      .attr('x', xScale2(dataRange[0])+padding.left)
      .attr('y', yScale2(options.targetHigh)+padding.top)
      .attr('width', xScale2(dataRange[1]- xScale2(dataRange[0])))
      .attr('height', yScale2(options.targetLow)-yScale2(options.targetHigh))
      .style('fill', '#D6FFD6')
      .attr('stroke', 'grey');

    // create the x axis container
    context.append('g')
      .attr('class', 'x axis');

    // create the y axis container
    context.append('g')
      .attr('class', 'y axis');

    context.select('.y')
      .attr('transform', 'translate(' + (padding.left) + ',' + padding.top + ')')
      .style('stroke', 'black')
      .style('shape-rendering', 'crispEdges')
      .style('fill', 'none')
      .call(yAxis2);

    // if first run then just display axis with no transition
    context.select('.x')
      .attr('transform', 'translate(' + padding.left + ',' + (chartHeight + padding.top) + ')')
      .style('stroke', 'black')
      .style('shape-rendering', 'crispEdges')
      .style('fill', 'none')
      .call(xAxis2);

    _.each(tickValues, function (n, li) {
      context.append('line')
        .attr('class', 'high-line')
        .attr('x1', xScale2(dataRange[0])+padding.left)
        .attr('y1', yScale2(tickValues[li])+padding.top)
        .attr('x2', xScale2(dataRange[1])+padding.left)
        .attr('y2', yScale2(tickValues[li])+padding.top)
        .style('stroke-dasharray', ('1, 5'))
        .attr('stroke', 'grey');
    });

    // bind up the context chart data to an array of circles
    var contextCircles = context.selectAll('circle')
        .data(data.sgv);

    function prepareContextCircles(sel) {
      var badData = [];
      sel.attr('cx', function (d) {
        return xScale2(d.date) + padding.left;
        })
          .attr('cy', function (d) {
            if (isNaN(d.sgv)) {
                badData.push(d);
                return yScale2(client.utils.scaleMgdl(450) + padding.top);
            } else {
                return yScale2(d.sgv) + padding.top;
            }
          })
          .attr('fill', function (d) {
            return d.color;
          })
          .style('opacity', function () { return 0.5 })
          .attr('stroke-width', function (d) {if (d.type === 'mbg') { return 2; } else { return 0; }})
          .attr('stroke', function () { return 'black'; })
          .attr('r', function(d) {
            if (d.type === 'mbg') {
              return 4;
            } else {
              return 2 + (options.width - 800) / 400;
            }
          })
          .on('mouseout', hideTooltip);

          if (badData.length > 0) {
            console.warn('Bad Data: isNaN(sgv)', badData);
          }
          return sel;
      }

    // if new circle then just display
    prepareContextCircles(contextCircles.enter().append('circle'));

    contextCircles.exit()
      .remove();
  }

  function hideTooltip ( ) {
    client.tooltip.transition()
      .duration(TOOLTIP_TRANS_MS)
      .style('opacity', 0);
  }
};
<commit_msg>Fix initialization of weekstoshow array<commit_after>'use strict';

var _ = require('lodash');
var moment = window.moment;
var times = require('../times');
var d3 = (global && global.d3) || require('d3');

var weektoweek = {
  name: 'weektoweek'
  , label: 'Week to week'
  , pluginType: 'report'
};

function init() {
  return weektoweek;
}

module.exports = init;

weektoweek.html = function html(client) {
  var translate = client.translate;
  var ret =
    '
' + translate('Week to week') + '
'
    + '' + translate('To see this report, press SHOW while in this view') + '
'
    + ' '+translate('Size')
    + ' <select id="rp_size">'
    + '  <option x="800" y="250">800x250px</option>'
    + '  <option x="1000" y="300" selected>1000x300px</option>'
    + '  <option x="1200" y="400">1200x400px</option>'
    + '  <option x="1550" y="600">1550x600px</option>'
    + '</select>'
    + '
'
    + translate('Scale') + ': '
    + '<input type="radio" name="rp_scale" id="rp_linear" checked>'
    + translate('Linear')
    + '<input type="radio" name="rp_scale" id="rp_log">'
    + translate('Logarithmic')
    + '
'
    + '
'
    + '
'
    ;
    return ret;
};

weektoweek.prepareHtml = function weektoweekPrepareHtml(weekstoshow) {
  $('#weektoweekcharts').html('');
  weekstoshow.forEach(function eachWeek(d) {
    $('#weektoweekcharts').append($('

'));
  });
};

weektoweek.report = function report_weektoweek(datastorage,sorteddaystoshow,options) {
  var Nightscout = window.Nightscout;
  var client = Nightscout.client;
  var translate = client.translate;
  var profile = client.sbx.data.profile;
  var report_plugins = Nightscout.report_plugins;
  var scaledTreatmentBG = report_plugins.utils.scaledTreatmentBG;

  var TOOLTIP_TRANS_MS = 300;

  var padding = { top: 15, right: 22, bottom: 30, left: 35 };

  var tddSum = 0;
  var carbsSum = 0;

  var weekstoshow = [ ];
  weekstoshow[0] = [ ];
  var weekIdx = 0;
  var dayIdx = 0;
  var firstDayOfWeek = moment.localeData().firstDayOfWeek();

  sorteddaystoshow.forEach( function eachDay(day) {
    if (moment(day).day() === firstDayOfWeek) {
      weekIdx += 1;
      dayIdx = 0;
      weekstoshow[weekIdx][dayIdx] = day;
    } else {
      weekstoshow[weekIdx][dayIdx] = day;
      dayIdx += 1;
    }
  });

  daytoday.prepareHtml(weekstoshow);

  weekstoshow.forEach( function eachWeek(week) {
    day.forEach( function eachDay(week) {
      drawChart(week, day, datastorage[day], options);
    });
  });

  function timeTicks(n,i) {
    var t12 = [
      '12am', '', '2am', '', '4am', '', '6am', '', '8am', '', '10am', '',
      '12pm', '', '2pm', '', '4pm', '', '6pm', '', '8pm', '', '10pm', '', '12am'
    ];
    if (Nightscout.client.settings.timeFormat === 24) {
      return ('00' + i).slice(-2);
    } else {
      return t12[i];
    }
  }

  function drawChart(week,day,data,options) {
    var tickValues
      , charts
      , context
      , xScale2, yScale2
      , yInsulinScale, yCarbsScale, yScaleBasals
      , xAxis2, yAxis2
      , dateFn = function (d) { return new Date(d.date); }
      , foodtexts = 0;

   tickValues = client.ticks(client, {
     scaleY: options.scale === report_plugins.consts.SCALE_LOG ? 'log' : 'linear'
     , targetTop: options.targetHigh
     , targetBottom: options.targetLow
   });

  // add defs for combo boluses
  var dashWidth = 5;
  d3.select('body').append('svg')
    .append('defs')
    .append('pattern')
      .attr('id', 'hash')
      .attr('patternUnits', 'userSpaceOnUse')
      .attr('width', 6)
      .attr('height', 6)
      .attr('x', 0)
      .attr('y', 0)
      .append('g')
        .style('fill', 'none')
        .style('stroke', '#0099ff')
        .style('stroke-width', 2)
      .append('path').attr('d', 'M0,0 l' + dashWidth + ',' + dashWidth)
      .append('path').attr('d', 'M' + dashWidth + ',0 l-' + dashWidth + ',' + dashWidth);

    // create svg and g to contain the chart contents
    charts = d3.select('#weektoweekchart-' + week[0] + '-' + week[week.length-1]).html(
      ''+
      report_plugins.utils.localeDate(day)+
      '
'
      ).append('svg');

    charts.append('rect')
      .attr('width', '100%')
      .attr('height', '100%')
      .attr('fill', 'WhiteSmoke');

    context = charts.append('g');

    // define the parts of the axis that aren't dependent on width or height
    xScale2 = d3.time.scale()
      .domain(d3.extent(data.sgv, dateFn));

    if (options.scale === report_plugins.consts.SCALE_LOG) {
      yScale2 = d3.scale.log()
        .domain([client.utils.scaleMgdl(options.basal ? 30 : 36), client.utils.scaleMgdl(420)]);
    } else {
      yScale2 = d3.scale.linear()
        .domain([client.utils.scaleMgdl(options.basal ? -40 : 36), client.utils.scaleMgdl(420)]);
    }

    xAxis2 = d3.svg.axis()
      .scale(xScale2)
      .tickFormat(timeTicks)
      .ticks(24)
      .orient('bottom');

    yAxis2 = d3.svg.axis()
      .scale(yScale2)
      .tickFormat(d3.format('d'))
      .tickValues(tickValues)
      .orient('left');

    // get current data range
    var dataRange = d3.extent(data.sgv, dateFn);

    // get the entire container height and width subtracting the padding
    var chartWidth = options.width - padding.left - padding.right;
    var chartHeight = options.height - padding.top - padding.bottom;

    //set the width and height of the SVG element
    charts.attr('width', options.width)
      .attr('height', options.height);

    // ranges are based on the width and height available so reset
    xScale2.range([0, chartWidth]);
    yScale2.range([chartHeight,0]);

    // add target BG rect
    context.append('rect')
      .attr('x', xScale2(dataRange[0])+padding.left)
      .attr('y', yScale2(options.targetHigh)+padding.top)
      .attr('width', xScale2(dataRange[1]- xScale2(dataRange[0])))
      .attr('height', yScale2(options.targetLow)-yScale2(options.targetHigh))
      .style('fill', '#D6FFD6')
      .attr('stroke', 'grey');

    // create the x axis container
    context.append('g')
      .attr('class', 'x axis');

    // create the y axis container
    context.append('g')
      .attr('class', 'y axis');

    context.select('.y')
      .attr('transform', 'translate(' + (padding.left) + ',' + padding.top + ')')
      .style('stroke', 'black')
      .style('shape-rendering', 'crispEdges')
      .style('fill', 'none')
      .call(yAxis2);

    // if first run then just display axis with no transition
    context.select('.x')
      .attr('transform', 'translate(' + padding.left + ',' + (chartHeight + padding.top) + ')')
      .style('stroke', 'black')
      .style('shape-rendering', 'crispEdges')
      .style('fill', 'none')
      .call(xAxis2);

    _.each(tickValues, function (n, li) {
      context.append('line')
        .attr('class', 'high-line')
        .attr('x1', xScale2(dataRange[0])+padding.left)
        .attr('y1', yScale2(tickValues[li])+padding.top)
        .attr('x2', xScale2(dataRange[1])+padding.left)
        .attr('y2', yScale2(tickValues[li])+padding.top)
        .style('stroke-dasharray', ('1, 5'))
        .attr('stroke', 'grey');
    });

    // bind up the context chart data to an array of circles
    var contextCircles = context.selectAll('circle')
        .data(data.sgv);

    function prepareContextCircles(sel) {
      var badData = [];
      sel.attr('cx', function (d) {
        return xScale2(d.date) + padding.left;
        })
          .attr('cy', function (d) {
            if (isNaN(d.sgv)) {
                badData.push(d);
                return yScale2(client.utils.scaleMgdl(450) + padding.top);
            } else {
                return yScale2(d.sgv) + padding.top;
            }
          })
          .attr('fill', function (d) {
            return d.color;
          })
          .style('opacity', function () { return 0.5 })
          .attr('stroke-width', function (d) {if (d.type === 'mbg') { return 2; } else { return 0; }})
          .attr('stroke', function () { return 'black'; })
          .attr('r', function(d) {
            if (d.type === 'mbg') {
              return 4;
            } else {
              return 2 + (options.width - 800) / 400;
            }
          })
          .on('mouseout', hideTooltip);

          if (badData.length > 0) {
            console.warn('Bad Data: isNaN(sgv)', badData);
          }
          return sel;
      }

    // if new circle then just display
    prepareContextCircles(contextCircles.enter().append('circle'));

    contextCircles.exit()
      .remove();
  }

  function hideTooltip ( ) {
    client.tooltip.transition()
      .duration(TOOLTIP_TRANS_MS)
      .style('opacity', 0);
  }
};
<|endoftext|>


<commit_before>var assign = require('object-assign');
var fs = require('fs');
var nameFunctions = require('../../nameFunctions');
var path = require('path');
var sanitize = require('sanitize-filename');
var url = require('url');

var DEFAULT_OPTIONS = {
	generateFilename: nameFunctions.randomFilename,
	whenExists: 'retry',
	retryAttempts: 3, // For whenExists: 'retry'.
};

function ensurePath (path) {
	// Ensure that the specified path exists and is writable. This is quick and
	// happens on server startup, so sync functions are ok.
	try {
		// accessSync throws if the item doesn't exist or we don't have
		// permission to read + write it.
		fs.accessSync(path, fs.R_OK | fs.W_OK);

		if (!fs.statSync(path).isDirectory()) {
			throw Error('Specified output path is not a directory');
		}
	} catch (e) {
		if (e.code === 'ENOENT') {
			// Recover by creating the directory.
			fs.mkdirsSync(path);
			console.log('Storage output path \'' + path + '\' created');
			return;
		}
		throw e;
	}
}

function FSAdapter (options, schema) {
	if (!schema.filename) throw Error('Cannot use FSAdapter without storing filename');

	this.options = assign({}, DEFAULT_OPTIONS, options.fs);

	// The generateFilename option takes an optional callback. Wrap it to always
	// take a callback.
	if (this.options.generateFilename.length <= 2) { // (file) or (file, attempt)
		// If generateFilename throws we treat that as a runtime error and not
		// a file data error. If you need to pass errors upstream take a
		// callback.
		var original = options.generateFilename;
		options.generateFilename = function (file, attempt, callback) {
			callback(null, original(file, attempt));
		};
	}

	ensurePath(this.options.path);
}

FSAdapter.compatibilityLevel = 1;

// All the extra schema fields supported by this adapter.
FSAdapter.SCHEMA_TYPES = {
	// This adapter stores its key in the name of a file on disk.
	filename: String,
};

FSAdapter.SCHEMA_FIELD_DEFAULTS = {
	filename: true,
};

/**
	Gets the public path of a stored file by combining the publicPath option
	with the filename in the field value
*/
FSAdapter.prototype.getFileURL = function (file) {
	var publicPath = this.options.publicPath;
	if (!publicPath) return null; // No URL.

	return url.resolve(publicPath, file.filename);
};

/**
	Private function for getting the on-disk filename
*/
FSAdapter.prototype._pathForFile = function (filename) {
	return path.resolve(this.options.path, sanitize(filename));
};

/**
	Generates a filename with the provided method in a retry loop, used by
	_getFilename below
*/
FSAdapter.prototype._retryFilename = function (attempt, file, callback) {
	var adapter = this;
	if (attempt > this.options.retryAttempts) {
		return callback(Error('Unique filename could not be generated; Maximum attempts exceeded'));
	}
	this.options.generateFilename(file, attempt, function (err, filename) {
		if (err) return callback(err);
		adapter.fileExists(filename, function (err, exists) {
			if (err) return callback(err);
			if (exists) return adapter._retryFilename(attempt + 1, file, callback);
			callback(null, filename);
		});
	});
};

/**
	Gets a filename for uploaded files based on the adapter options
*/
FSAdapter.prototype._getFilename = function (file, callback) {
	var adapter = this;
	switch (this.options.whenExists) {
		case 'overwrite':
			this.options.generateFilename(file, 0, callback);
			break;
		case 'error':
			this.options.generateFilename(file, 0, function (err, filename) {
				if (err) return callback(err);
				adapter.fileExists(filename, function (err, result) {
					if (err) return callback(err);
					if (result === true) return callback(Error('File already exists'));
					callback(null, filename);
				});
			});
			break;
		case 'retry':
			this._retryFilename(0, file, callback);
			break;
	}
};

/**
	Uploads a file at the specified path and returns the value to be stored
	in the field value. The file argument must be an object as per the [multer
	file information spec](https://github.com/expressjs/multer#file-information)
*/
FSAdapter.prototype.uploadFile = function (file, callback) {
	var self = this;
	this._getFilename(file, function (err, filename) {
		if (err) return callback(err);
		filename = sanitize(filename);
		var uploadPath = path.resolve(this.options.path, filename);
		fs.move(file.path, uploadPath, function (err) {
			if (err) return callback(err);

			// TODO: Chmod the file.
			callback(null, {
				filename: filename,
				size: file.size,
				mimetype: file.mimetype,
				path: self.options.path,
				originalname: file.originalname,
			});
		});
	});
};

FSAdapter.prototype.removeFile = function (file, callback) {
	fs.unlink(this._pathForFile(file.filename), function (err) {
		if (err && err.code === 'ENOENT') {
			// The file doesn't exist.
			console.warn('Attempted to remove a non-existant file');
			return callback();
		}

		callback(err);
	});
};

FSAdapter.prototype.fileExists = function (filename, callback) {
	// Returns (err, bool) to the callback based on whether or not the file
	// already exists. Used if whenExists: 'error' or 'retry' in the options
	fs.stat(this._pathForFile(filename), function (err, stats) {
		if (err && err.code === 'ENOENT') {
			// File does not exist
			callback(null, false);
		} else if (err) {
			// Other error getting file info
			callback(err);
		} else if (stats.isFile()) {
			// File does exist
			callback(null, true);
		} else {
			// Object at path is not a file
			callback(Error('Invalid save destination - dest is not a file'));
		}
	});
};

module.exports = FSAdapter;
<commit_msg>FS Adapter needs fs-extra module<commit_after>var assign = require('object-assign');
var fs = require('fs-extra');
var nameFunctions = require('../../nameFunctions');
var path = require('path');
var sanitize = require('sanitize-filename');
var url = require('url');

var DEFAULT_OPTIONS = {
	generateFilename: nameFunctions.randomFilename,
	whenExists: 'retry',
	retryAttempts: 3, // For whenExists: 'retry'.
};

function ensurePath (path) {
	// Ensure that the specified path exists and is writable. This is quick and
	// happens on server startup, so sync functions are ok.
	try {
		// accessSync throws if the item doesn't exist or we don't have
		// permission to read + write it.
		fs.accessSync(path, fs.R_OK | fs.W_OK);

		if (!fs.statSync(path).isDirectory()) {
			throw Error('Specified output path is not a directory');
		}
	} catch (e) {
		if (e.code === 'ENOENT') {
			// Recover by creating the directory.
			fs.mkdirsSync(path);
			console.log('Storage output path \'' + path + '\' created');
			return;
		}
		throw e;
	}
}

function FSAdapter (options, schema) {
	if (!schema.filename) throw Error('Cannot use FSAdapter without storing filename');

	this.options = assign({}, DEFAULT_OPTIONS, options.fs);

	// The generateFilename option takes an optional callback. Wrap it to always
	// take a callback.
	if (this.options.generateFilename.length <= 2) { // (file) or (file, attempt)
		// If generateFilename throws we treat that as a runtime error and not
		// a file data error. If you need to pass errors upstream take a
		// callback.
		var original = options.generateFilename;
		options.generateFilename = function (file, attempt, callback) {
			callback(null, original(file, attempt));
		};
	}

	ensurePath(this.options.path);
}

FSAdapter.compatibilityLevel = 1;

// All the extra schema fields supported by this adapter.
FSAdapter.SCHEMA_TYPES = {
	// This adapter stores its key in the name of a file on disk.
	filename: String,
};

FSAdapter.SCHEMA_FIELD_DEFAULTS = {
	filename: true,
};

/**
	Gets the public path of a stored file by combining the publicPath option
	with the filename in the field value
*/
FSAdapter.prototype.getFileURL = function (file) {
	var publicPath = this.options.publicPath;
	if (!publicPath) return null; // No URL.

	return url.resolve(publicPath, file.filename);
};

/**
	Private function for getting the on-disk filename
*/
FSAdapter.prototype._pathForFile = function (filename) {
	return path.resolve(this.options.path, sanitize(filename));
};

/**
	Generates a filename with the provided method in a retry loop, used by
	_getFilename below
*/
FSAdapter.prototype._retryFilename = function (attempt, file, callback) {
	var adapter = this;
	if (attempt > this.options.retryAttempts) {
		return callback(Error('Unique filename could not be generated; Maximum attempts exceeded'));
	}
	this.options.generateFilename(file, attempt, function (err, filename) {
		if (err) return callback(err);
		adapter.fileExists(filename, function (err, exists) {
			if (err) return callback(err);
			if (exists) return adapter._retryFilename(attempt + 1, file, callback);
			callback(null, filename);
		});
	});
};

/**
	Gets a filename for uploaded files based on the adapter options
*/
FSAdapter.prototype._getFilename = function (file, callback) {
	var adapter = this;
	switch (this.options.whenExists) {
		case 'overwrite':
			this.options.generateFilename(file, 0, callback);
			break;
		case 'error':
			this.options.generateFilename(file, 0, function (err, filename) {
				if (err) return callback(err);
				adapter.fileExists(filename, function (err, result) {
					if (err) return callback(err);
					if (result === true) return callback(Error('File already exists'));
					callback(null, filename);
				});
			});
			break;
		case 'retry':
			this._retryFilename(0, file, callback);
			break;
	}
};

/**
	Uploads a file at the specified path and returns the value to be stored
	in the field value. The file argument must be an object as per the [multer
	file information spec](https://github.com/expressjs/multer#file-information)
*/
FSAdapter.prototype.uploadFile = function (file, callback) {
	var self = this;
	this._getFilename(file, function (err, filename) {
		if (err) return callback(err);
		filename = sanitize(filename);
		var uploadPath = path.resolve(this.options.path, filename);
		fs.move(file.path, uploadPath, function (err) {
			if (err) return callback(err);

			// TODO: Chmod the file.
			callback(null, {
				filename: filename,
				size: file.size,
				mimetype: file.mimetype,
				path: self.options.path,
				originalname: file.originalname,
			});
		});
	});
};

FSAdapter.prototype.removeFile = function (file, callback) {
	fs.unlink(this._pathForFile(file.filename), function (err) {
		if (err && err.code === 'ENOENT') {
			// The file doesn't exist.
			console.warn('Attempted to remove a non-existant file');
			return callback();
		}

		callback(err);
	});
};

FSAdapter.prototype.fileExists = function (filename, callback) {
	// Returns (err, bool) to the callback based on whether or not the file
	// already exists. Used if whenExists: 'error' or 'retry' in the options
	fs.stat(this._pathForFile(filename), function (err, stats) {
		if (err && err.code === 'ENOENT') {
			// File does not exist
			callback(null, false);
		} else if (err) {
			// Other error getting file info
			callback(err);
		} else if (stats.isFile()) {
			// File does exist
			callback(null, true);
		} else {
			// Object at path is not a file
			callback(Error('Invalid save destination - dest is not a file'));
		}
	});
};

module.exports = FSAdapter;
<|endoftext|>


<commit_before>;
/*!
 * Tarsier JavaScript Library v1.0.1
 * http://github.com/moky/Tarsier/
 *
 * Includes jquery.js
 * http://jquery.com/
 *
 * Copyright 2013 moKy at slanissue.com
 * Released under the MIT license
 * http://jquery.org/license
 *
 * Date: 2013-12-11 T10:43Z
 */

/**
 *
 *  main
 *
 *  Author: moKy @ Dec. 11, 2013
 *
 */

if (typeof(window.tarsier) != "object") {
	window.tarsier = {
		version: "1.0.1"
	};
}

// base functions
(function(tarsier) {

	////////////////////////////////////////////////////////////////////////////
	//
	//  namespace: base
	//
	tarsier.base = {
		// importing tasks
		importings: []
	};

	/**
	 *  class: Task
	 */
	tarsier.base.Task = function(args) {
		this.url = args.url;
		this.type = args.type;
		this.callback = args.callback;
		return this;
	};

	// finished current task
	tarsier.base.Task.prototype.finished = function() {
		tarsier.base.importings.shift(); // remove current task
		if (tarsier.base.importings.length > 0) {
			tarsier.base.importings[0].run(); // run next task
		} else {
			tarsier.events.onload(); // all tasks finished
		}
		return this;
	};

	// import js
	tarsier.base.Task.prototype.js = function() {
		var task = this;
		var doc = task.document || window.document;

		var script = doc.createElement("script");
		if (script) {
			script.type = "text/javascript";
			script.src = task.url;
			script.async = task.async;
			script.charset = task.charset || "UTF-8";

			// callback
			script.onload = function() {
				try {
					if (task.callback) task.callback();
				} catch(e) {
					alert("[Tarsier] callback error: " + e);
				}
				task.finished();
			}
			script.onreadystatechange = function() { // IE
				if (this.readyState == "complete") {
					script.onload();
				}
			}

			// load
			var head = doc.getElementsByTagName("head");
			if (head) {
				head.item(0).appendChild(script);
			}
		}
		return this;
	};

	// import css
	tarsier.base.Task.prototype.css = function() {
		var task = this;
		var doc = task.document || window.document;

		var link = doc.createElement("link");
		if (link) {
			link.rel = "stylesheet";
			link.type = "text/css";
			link.href = task.url;

			// load
			var head = doc.getElementsByTagName("head");
			if (head) {
				head.item(0).appendChild(link);
			}
		}

		task.finished();
		return this;
	};

	// run a task
	tarsier.base.Task.prototype.run = function() {
		if (this.type == "text/javascript") {
			this.js();
		} else if (this.type == "text/css") {
			this.css();
		} else {
			alert("[Tarsier] task run: could not happen");
		}
		return this;
	};

	// check duplicated
	tarsier.base.Task.prototype.isDuplicated = function() {
		for (var i = 0; i < tarsier.base.importings.length; ++i) {
			if (tarsier.base.importings[i].url == this.url) return true;
		}
		return false;
	}

	//
	// import something
	//
	tarsier.base.import = function(args) {
		var task;
		var type = args.type;
		if (type == "text/javascript") {
			task = new this.Task({url: args.src,
								 type: "text/javascript",
								 charset: args.charset,
								 async: args.async,
								 callback: args.callback});
		} else if (type == "text/css") {
			task = new this.Task({url: args.href,
								 type: "text/css"});
		} else {
			alert("[Tarsier] unknown import type: " + type);
			return this;
		}

		if (task.isDuplicated()) {
			//alert("[Tarsier] duplicated url: " + task.url);
			return this;
		}

		this.importings[this.importings.length] = task;
		if (this.importings.length == 1) {
			task.run();
		}
		return this;
	};

	////////////////////////////////////////////////////////////////////////////
	//
	//  namespace: events
	//

	tarsier.events = {

		isWindowLoaded: false,

		handlers: {
			onload: []
		}
	};

	// window loaded & importing finished?
	tarsier.events.isReady = function() {
		return this.isWindowLoaded && tarsier.base.importings.length == 0;
	};

	// add handler for event name
	tarsier.events.add = function(name, handler) {
		if (!name || !handler) return;
		if (name == "load" || name == "onload" || name == "ready") {
			this.handlers.onload[this.handlers.onload.length] = handler;
		} else {
			alert("[Tarsier] unknown event: " + name + " handler: " + handler);
		}
		return this;
	};

	tarsier.events.onload = function() {
		if (this.isReady()) {
			for (var i = 0; i < this.handlers.onload.length; ++i) {
				this.handlers.onload[i]();
			}
			this.handlers.onload = [];
		}
		return this;
	};

	//--------------------------------------------------------------------------

	/**
	 *  import javascript file
	 */
	tarsier.importJS = function(url, callback) {
		this.base.import({
						 src: url,
						 type: "text/javascript",
						 callback: callback
		});
		return this;
	};
	/**
	 *  import style sheet
	 */
	tarsier.importCSS = function(url) {
		this.base.import({
						 href: url,
						 type: "text/css"
		});
		return this;
	};

	/**
	 *  adding handler for 'onload' event
	 */
	tarsier.ready = function(func) {
		this.events.add("onload", func);
		return this;
	};

	var window_onload = window.onload; // save old handler
	window.onload = function() {
		tarsier.events.isWindowLoaded = true;
		tarsier.events.onload();
		if (typeof(window_onload) == "function") {
			window_onload(); // call old handler
		}
	};

	//--------------------------------------------------------------------------

	/**
	 *  Environment variables
	 */
	var __FILE__ = "http://moky.github.io/Tarsier/tarsier.js"; // current filename
	var __PATH__ = "http://moky.github.io/Tarsier/"; // current filepath

	var scripts = document.getElementsByTagName("script");
	if (scripts && scripts.length > 0) {
		for (var i = scripts.length - 1; i >= 0; --i) {
			if (scripts[i].src.lastIndexOf("tarsier.js") > 0) {
				__FILE__ = scripts[i].src;
				var pos = __FILE__.lastIndexOf("/");
				if (pos >= 0) {
					__PATH__ = __FILE__.substring(0, pos + 1);
					__FILE__ = __FILE__.substring(pos + 1);
				}
			}
		}
	}

	// include all dependences
//	tarsier.importJS("http://code.jquery.com/jquery.min.js");
//	tarsier.importJS("http://borismoore.github.io/jquery-tmpl/jquery.tmpl.min.js");
//	tarsier.importJS("http://jquery-xml2json-plugin.googlecode.com/svn/trunk/jquery.xml2json.js");
//	tarsier.importJS("http://steamdev.com/snippet/js/jquery.snippet.min.js");
//	tarsier.importCSS("http://steamdev.com/snippet/css/jquery.snippet.min.css");

	tarsier.importJS(__PATH__ + "3rd/jquery.min.js");
	tarsier.importJS(__PATH__ + "3rd/jquery.tmpl.min.js");
	tarsier.importJS(__PATH__ + "3rd/jquery.xml2json.js");
//	tarsier.importJS(__PATH__ + "3rd/jquery.snippet.min.js");
//	tarsier.importCSS(__PATH__ + "3rd/jquery.snippet.min.css");

	tarsier.importJS(__PATH__ + "http.js");
	tarsier.importJS(__PATH__ + "xml.js");
	tarsier.importJS(__PATH__ + "template.js");
	tarsier.importJS(__PATH__ + "widget.js");

})(tarsier);
<commit_msg>v1.0.1<commit_after>;
/*!
 * Tarsier JavaScript Library v1.0.1
 * http://github.com/moky/Tarsier/
 *
 * Includes jquery.js
 * http://jquery.com/
 *
 * Copyright 2013 moKy at slanissue.com
 * Released under the MIT license
 * http://jquery.org/license
 *
 * Date: 2013-12-11 T10:43Z
 */

/**
 *
 *  main
 *
 *  Author: moKy @ Dec. 11, 2013
 *
 */

if (typeof(window.tarsier) != "object") {
	window.tarsier = {
		version: "1.0.1"
	};
}

// base functions
(function(tarsier) {

	////////////////////////////////////////////////////////////////////////////
	//
	//  namespace: base
	//
	tarsier.base = {
		// importing tasks
		importings: []
	};

	/**
	 *  class: Task
	 */
	tarsier.base.Task = function(args) {
		this.url = args.url;
		this.type = args.type;
		this.callback = args.callback;
		return this;
	};

	// finished current task
	tarsier.base.Task.prototype.finished = function() {
		tarsier.base.importings.shift(); // remove current task
		if (tarsier.base.importings.length > 0) {
			tarsier.base.importings[0].run(); // run next task
		} else {
			tarsier.events.onload(); // all tasks finished
		}
		return this;
	};

	// import js
	tarsier.base.Task.prototype.js = function() {
		var task = this;
		var doc = task.document || window.document;

		var script = doc.createElement("script");
		if (script) {
			script.type = "text/javascript";
			script.src = task.url;
			script.async = task.async;
			script.charset = task.charset || "UTF-8";

			// callback
			script.onload = function() {
				try {
					if (task.callback) task.callback();
				} catch(e) {
					alert("[Tarsier] callback error: " + e);
				}
				task.finished();
			}
			script.onreadystatechange = function() { // IE
				if (this.readyState == "complete") {
					script.onload();
				}
			}

			// load
			var head = doc.getElementsByTagName("head")[0] || doc.documentElement;
			if (head) {
				head.appendChild(script);
			}
		}
		return this;
	};

	// import css
	tarsier.base.Task.prototype.css = function() {
		var task = this;
		var doc = task.document || window.document;

		var link = doc.createElement("link");
		if (link) {
			link.rel = "stylesheet";
			link.type = "text/css";
			link.href = task.url;

			// load
			var head = doc.getElementsByTagName("head")[0] || doc.documentElement;
			if (head) {
				head.appendChild(link);
			}
		}

		task.finished();
		return this;
	};

	// run a task
	tarsier.base.Task.prototype.run = function() {
		if (this.type == "text/javascript") {
			this.js();
		} else if (this.type == "text/css") {
			this.css();
		} else {
			alert("[Tarsier] task run: could not happen");
		}
		return this;
	};

	// check duplicated
	tarsier.base.Task.prototype.isDuplicated = function() {
		for (var i = 0; i < tarsier.base.importings.length; ++i) {
			if (tarsier.base.importings[i].url == this.url) return true;
		}
		return false;
	}

	//
	// import something
	//
	tarsier.base.import = function(args) {
		var task;
		var type = args.type;
		if (type == "text/javascript") {
			task = new this.Task({url: args.src,
								 type: "text/javascript",
								 charset: args.charset,
								 async: args.async,
								 callback: args.callback});
		} else if (type == "text/css") {
			task = new this.Task({url: args.href,
								 type: "text/css"});
		} else {
			alert("[Tarsier] unknown import type: " + type);
			return this;
		}

		if (task.isDuplicated()) {
			//alert("[Tarsier] duplicated url: " + task.url);
			return this;
		}

		this.importings[this.importings.length] = task;
		if (this.importings.length == 1) {
			task.run();
		}
		return this;
	};

	////////////////////////////////////////////////////////////////////////////
	//
	//  namespace: events
	//

	tarsier.events = {

		isWindowLoaded: false,

		handlers: {
			onload: []
		}
	};

	// window loaded & importing finished?
	tarsier.events.isReady = function() {
		return this.isWindowLoaded && tarsier.base.importings.length == 0;
	};

	// add handler for event name
	tarsier.events.add = function(name, handler) {
		if (!name || !handler) return;
		if (name == "load" || name == "onload" || name == "ready") {
			this.handlers.onload[this.handlers.onload.length] = handler;
		} else {
			alert("[Tarsier] unknown event: " + name + " handler: " + handler);
		}
		return this;
	};

	tarsier.events.onload = function() {
		if (this.isReady()) {
			for (var i = 0; i < this.handlers.onload.length; ++i) {
				this.handlers.onload[i]();
			}
			this.handlers.onload = [];
		}
		return this;
	};

	//--------------------------------------------------------------------------

	/**
	 *  import javascript file
	 */
	tarsier.importJS = function(url, callback) {
		this.base.import({
						 src: url,
						 type: "text/javascript",
						 callback: callback
		});
		return this;
	};
	/**
	 *  import style sheet
	 */
	tarsier.importCSS = function(url) {
		this.base.import({
						 href: url,
						 type: "text/css"
		});
		return this;
	};

	/**
	 *  adding handler for 'onload' event
	 */
	tarsier.ready = function(func) {
		this.events.add("onload", func);
		return this;
	};

	var window_onload = window.onload; // save old handler
	window.onload = function() {
		tarsier.events.isWindowLoaded = true;
		tarsier.events.onload();
		if (typeof(window_onload) == "function") {
			window_onload(); // call old handler
		}
	};

	//--------------------------------------------------------------------------

	/**
	 *  Environment variables
	 */
	var __FILE__ = "http://moky.github.io/Tarsier/tarsier.js"; // current filename
	var __PATH__ = "http://moky.github.io/Tarsier/"; // current filepath

	var scripts = document.getElementsByTagName("script");
	if (scripts && scripts.length > 0) {
		for (var i = scripts.length - 1; i >= 0; --i) {
			if (scripts[i].src.lastIndexOf("tarsier.js") > 0) {
				__FILE__ = scripts[i].src;
				var pos = __FILE__.lastIndexOf("/");
				if (pos >= 0) {
					__PATH__ = __FILE__.substring(0, pos + 1);
					__FILE__ = __FILE__.substring(pos + 1);
				}
			}
		}
	}

	// include all dependences
//	tarsier.importJS("http://code.jquery.com/jquery.min.js");
//	tarsier.importJS("http://borismoore.github.io/jquery-tmpl/jquery.tmpl.min.js");
//	tarsier.importJS("http://jquery-xml2json-plugin.googlecode.com/svn/trunk/jquery.xml2json.js");
//	tarsier.importJS("http://steamdev.com/snippet/js/jquery.snippet.min.js");
//	tarsier.importCSS("http://steamdev.com/snippet/css/jquery.snippet.min.css");

	tarsier.importJS(__PATH__ + "3rd/jquery.min.js");
	tarsier.importJS(__PATH__ + "3rd/jquery.tmpl.min.js");
	tarsier.importJS(__PATH__ + "3rd/jquery.xml2json.js");
//	tarsier.importJS(__PATH__ + "3rd/jquery.snippet.min.js");
//	tarsier.importCSS(__PATH__ + "3rd/jquery.snippet.min.css");

	tarsier.importJS(__PATH__ + "http.js");
	tarsier.importJS(__PATH__ + "xml.js");
	tarsier.importJS(__PATH__ + "template.js");
	tarsier.importJS(__PATH__ + "widget.js");

})(tarsier);
<|endoftext|>


<commit_before>var http = require('http')
  , fs = require('fs')
  , _ = require('underscore')
  , temp = require('temp')
  , path = require('path')
  , os = require('os');

function fileExt(name) {
  var ext = path.extname(name).split(".");
  return ext[ext.length-1];
}

exports.download = function(url, callback) {
  var now = new Date();
  var tmpfn = path.join(os.tmpDir(), [
    "tmp-", now.getTime(), "-", Math.floor(Math.random()*1000000),
    ".", fileExt(url)
  ].join(""));
  console.log("Downloading " + url + " to " + tmpfn);
  var stream = fs.createWriteStream(tmpfn);
  var req = http.get(url, function(response) {
    response.on("data", function(chunk){stream.write(chunk);});
    response.on("end", function() {
      stream.on("close", function() {
        callback(null,tmpfn, function() {
          fs.unlinkSync(tmpfn);
        });
      });
      stream.end();
      stream.destroy();
    });
  });
}
<commit_msg>fix unneeded dependency<commit_after>var http = require('http')
  , fs = require('fs')
  , _ = require('underscore')
  , path = require('path')
  , os = require('os');

function fileExt(name) {
  var ext = path.extname(name).split(".");
  return ext[ext.length-1];
}

exports.download = function(url, callback) {
  var now = new Date();
  var tmpfn = path.join(os.tmpDir(), [
    "tmp-", now.getTime(), "-", Math.floor(Math.random()*1000000),
    ".", fileExt(url)
  ].join(""));
  console.log("Downloading " + url + " to " + tmpfn);
  var stream = fs.createWriteStream(tmpfn);
  var req = http.get(url, function(response) {
    response.on("data", function(chunk){stream.write(chunk);});
    response.on("end", function() {
      stream.on("close", function() {
        callback(null,tmpfn, function() {
          fs.unlinkSync(tmpfn);
        });
      });
      stream.end();
      stream.destroy();
    });
  });
}
<|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var util = require('util');
var assert = require('assert');
var _ = require('@sailshq/lodash');
var flaverr = require('flaverr');

/**
 * getModel()
 *
 * Look up a Waterline model by identity.
 *
 * > Note that we do a few quick assertions in the process, purely as sanity checks
 * > and to help prevent bugs.  If any of these fail, then it means there is some
 * > unhandled usage error, or a bug going on elsewhere in Waterline.
 *
 * ------------------------------------------------------------------------------------------
 * @param {String} modelIdentity
 *        The identity of the model this criteria is referring to (e.g. "pet" or "user")
 *        > Useful for looking up the Waterline model and accessing its attribute definitions.
 *
 * @param {Ref} orm
 *        The Waterline ORM instance.
 * ------------------------------------------------------------------------------------------
 * @returns {Ref}  [the Waterline model]
 * ------------------------------------------------------------------------------------------
 * @throws {Error} If no such model exists.
 *         E_MODEL_NOT_REGISTERED
 *
 * @throws {Error} If anything else goes wrong.
 * ------------------------------------------------------------------------------------------
 */

module.exports = function getModel(modelIdentity, orm) {

  // Check that this utility function is being used properly, and that the provided `modelIdentity` and `orm` are valid.
  assert(_.isString(modelIdentity), new Error('Consistency violation: `modelIdentity` must be a non-empty string.'));
  assert(modelIdentity !== '', new Error('Consistency violation: `modelIdentity` must be a non-empty string.'));
  assert(_.isObject(orm) && !_.isArray(orm) && !_.isFunction(orm), new Error('Consistency violation: `orm` must be a valid Waterline ORM instance (must be a dictionary)'));
  assert(_.isObject(orm.collections) && !_.isArray(orm.collections) && !_.isFunction(orm.collections), new Error('Consistency violation: `orm` must be a valid Waterline ORM instance (must have a dictionary of "collections")'));

  // Try to look up the Waterline model.
  //
  // > Note that, in addition to being the model definition, this
  // > "WLModel" is actually the hydrated model object (fka a "Waterline collection")
  // > which has methods like `find`, `create`, etc.
  var WLModel = orm.collections[modelIdentity];
  if (_.isUndefined(WLModel)) {
    throw flaverr('E_MODEL_NOT_REGISTERED', new Error('The provided `modelIdentity` references a model (`'+modelIdentity+'`) which does not exist in the provided `orm`.'));
  }

  // Finally, do a couple of quick sanity checks on the registered
  // Waterline model, such as verifying that it declares an extant,
  // valid primary key attribute.
  assert(_.isObject(WLModel) && !_.isArray(WLModel) && !_.isFunction(WLModel), new Error('Consistency violation: All model definitions must be dictionaries, but somehow, the referenced Waterline model (`'+modelIdentity+'`) seems to have become corrupted.  Here it is: '+util.inspect(WLModel, {depth: null})));
  assert(_.isObject(WLModel.attributes) && !_.isArray(WLModel.attributes) && !_.isFunction(WLModel.attributes), new Error('Consistency violation: All model definitions must have a dictionary of `attributes`.  But somehow, the referenced Waterline model (`'+modelIdentity+'`) seems to have become corrupted and has a missing or invalid `attributes` property.  Here is the Waterline model: '+util.inspect(WLModel, {depth: null})));
  assert(_.isString(WLModel.primaryKey), new Error('Consistency violation: The referenced Waterline model (`'+modelIdentity+'`) has an invalid `primaryKey`.  Should be a string, but instead, got: '+util.inspect(WLModel.primaryKey, {depth:null})));
  var pkAttrDef = WLModel.attributes[WLModel.primaryKey];
  assert(!_.isUndefined(pkAttrDef), new Error('Consistency violation: The referenced Waterline model (`'+modelIdentity+'`) declares `primaryKey: \''+WLModel.primaryKey+'\'`, yet there is no `'+WLModel.primaryKey+'` attribute defined in the model!'));
  assert(_.isObject(pkAttrDef) && !_.isArray(pkAttrDef) && !_.isFunction(pkAttrDef), new Error('Consistency violation: The `primaryKey` (`'+WLModel.primaryKey+'`) in the referenced Waterline model (`'+modelIdentity+'`) corresponds with a CORRUPTED attribute definition: '+util.inspect(pkAttrDef, {depth:null})+'\n(^^this should have been caught already by waterline-schema!)'));
  assert(pkAttrDef.type === 'number' || pkAttrDef.type === 'string', new Error('Consistency violation: The `primaryKey` (`'+WLModel.primaryKey+'`) in the referenced Waterline model (`'+modelIdentity+'`) corresponds with an INCOMPATIBLE attribute definition.  In order to be used as the logical primary key, the referenced attribute should declare itself `type: \'string\'` or `type: \'number\'`...but instead its `type` is: '+util.inspect(pkAttrDef.type, {depth:null})+'\n(^^this should have been caught already by waterline-schema!)'));

  // Send back a reference to this Waterline model.
  return WLModel;

};
<commit_msg>Trivial (improve assertion to clarify that it's talking about the new 'primaryKey' model setting in the model's definition-- not an actual primary key value from a record, or anything like that.)<commit_after>/**
 * Module dependencies
 */

var util = require('util');
var assert = require('assert');
var _ = require('@sailshq/lodash');
var flaverr = require('flaverr');

/**
 * getModel()
 *
 * Look up a Waterline model by identity.
 *
 * > Note that we do a few quick assertions in the process, purely as sanity checks
 * > and to help prevent bugs.  If any of these fail, then it means there is some
 * > unhandled usage error, or a bug going on elsewhere in Waterline.
 *
 * ------------------------------------------------------------------------------------------
 * @param {String} modelIdentity
 *        The identity of the model this criteria is referring to (e.g. "pet" or "user")
 *        > Useful for looking up the Waterline model and accessing its attribute definitions.
 *
 * @param {Ref} orm
 *        The Waterline ORM instance.
 * ------------------------------------------------------------------------------------------
 * @returns {Ref}  [the Waterline model]
 * ------------------------------------------------------------------------------------------
 * @throws {Error} If no such model exists.
 *         E_MODEL_NOT_REGISTERED
 *
 * @throws {Error} If anything else goes wrong.
 * ------------------------------------------------------------------------------------------
 */

module.exports = function getModel(modelIdentity, orm) {

  // Check that this utility function is being used properly, and that the provided `modelIdentity` and `orm` are valid.
  assert(_.isString(modelIdentity), new Error('Consistency violation: `modelIdentity` must be a non-empty string.'));
  assert(modelIdentity !== '', new Error('Consistency violation: `modelIdentity` must be a non-empty string.'));
  assert(_.isObject(orm) && !_.isArray(orm) && !_.isFunction(orm), new Error('Consistency violation: `orm` must be a valid Waterline ORM instance (must be a dictionary)'));
  assert(_.isObject(orm.collections) && !_.isArray(orm.collections) && !_.isFunction(orm.collections), new Error('Consistency violation: `orm` must be a valid Waterline ORM instance (must have a dictionary of "collections")'));

  // Try to look up the Waterline model.
  //
  // > Note that, in addition to being the model definition, this
  // > "WLModel" is actually the hydrated model object (fka a "Waterline collection")
  // > which has methods like `find`, `create`, etc.
  var WLModel = orm.collections[modelIdentity];
  if (_.isUndefined(WLModel)) {
    throw flaverr('E_MODEL_NOT_REGISTERED', new Error('The provided `modelIdentity` references a model (`'+modelIdentity+'`) which does not exist in the provided `orm`.'));
  }

  // Finally, do a couple of quick sanity checks on the registered
  // Waterline model, such as verifying that it declares an extant,
  // valid primary key attribute.
  assert(_.isObject(WLModel) && !_.isArray(WLModel) && !_.isFunction(WLModel), new Error('Consistency violation: All model definitions must be dictionaries, but somehow, the referenced Waterline model (`'+modelIdentity+'`) seems to have become corrupted.  Here it is: '+util.inspect(WLModel, {depth: null})));
  assert(_.isObject(WLModel.attributes) && !_.isArray(WLModel.attributes) && !_.isFunction(WLModel.attributes), new Error('Consistency violation: All model definitions must have a dictionary of `attributes`.  But somehow, the referenced Waterline model (`'+modelIdentity+'`) seems to have become corrupted and has a missing or invalid `attributes` property.  Here is the Waterline model: '+util.inspect(WLModel, {depth: null})));
  assert(_.isString(WLModel.primaryKey), new Error('Consistency violation: The referenced Waterline model (`'+modelIdentity+'`) defines an invalid `primaryKey` setting.  Should be a string (the name of the primary key attribute), but instead, it is: '+util.inspect(WLModel.primaryKey, {depth:null})));
  var pkAttrDef = WLModel.attributes[WLModel.primaryKey];
  assert(!_.isUndefined(pkAttrDef), new Error('Consistency violation: The referenced Waterline model (`'+modelIdentity+'`) declares `primaryKey: \''+WLModel.primaryKey+'\'`, yet there is no `'+WLModel.primaryKey+'` attribute defined in the model!'));
  assert(_.isObject(pkAttrDef) && !_.isArray(pkAttrDef) && !_.isFunction(pkAttrDef), new Error('Consistency violation: The `primaryKey` (`'+WLModel.primaryKey+'`) in the referenced Waterline model (`'+modelIdentity+'`) corresponds with a CORRUPTED attribute definition: '+util.inspect(pkAttrDef, {depth:null})+'\n(^^this should have been caught already by waterline-schema!)'));
  assert(pkAttrDef.type === 'number' || pkAttrDef.type === 'string', new Error('Consistency violation: The `primaryKey` (`'+WLModel.primaryKey+'`) in the referenced Waterline model (`'+modelIdentity+'`) corresponds with an INCOMPATIBLE attribute definition.  In order to be used as the logical primary key, the referenced attribute should declare itself `type: \'string\'` or `type: \'number\'`...but instead its `type` is: '+util.inspect(pkAttrDef.type, {depth:null})+'\n(^^this should have been caught already by waterline-schema!)'));

  // Send back a reference to this Waterline model.
  return WLModel;

};
<|endoftext|>


<commit_before>const si = require('../lib/index');

const testWithTimeout = async (fn) => {
  return new Promise((resolve, reject) => {
    (async () => {
      const timeout = setTimeout(() => {
        reject('Test Timeout');
      }, 20000);
      const result = await fn();
      clearTimeout(timeout);
      return resolve(result);
    })();
  });
};

(async () => {
  try {
    console.log('Testing system:');
    console.log(await testWithTimeout(si.system));

    console.log('Testing cpu:');
    console.log(await testWithTimeout(si.cpu));

    console.log('Testing mem:');
    console.log(await testWithTimeout(si.mem));

    console.log('Testing memLayout:');
    console.log(await testWithTimeout(si.memLayout));

    console.log('Testing graphics:');
    console.log(await testWithTimeout(si.graphics));

    console.log('Testing diskLayout:');
    console.log(await testWithTimeout(si.diskLayout));

    console.log('Testing osInfo:');
    console.log(await testWithTimeout(si.osInfo));

    console.log('Testing networkInterfaces:');
    console.log(await testWithTimeout(si.networkInterfaces));

    console.log('Testing networkInterfaceDefault:');
    console.log(await testWithTimeout(si.networkInterfaceDefault));

    console.log('Testing time:');
    console.log(await testWithTimeout(si.time));

    console.log('Testing currentLoad:');
    console.log(await testWithTimeout(si.currentLoad));

    console.log('Testing cpuTemperature:');
    console.log(await testWithTimeout(si.cpuTemperature));

    console.log('Testing UUID:');
    console.log(await testWithTimeout(si.uuid()));

    console.log('Testing versions:');
    console.log(await testWithTimeout(si.versions()));

    console.log('All tests complete.');
    process.exit(0);
  } catch (e) {
    console.log(e);
    console.log('One or more tests failed.');
    process.exit(1);
  }
})();
<commit_msg>extended auto-tests<commit_after>const si = require('../lib/index');

const testWithTimeout = async (fn) => {
  return new Promise((resolve, reject) => {
    (async () => {
      const timeout = setTimeout(() => {
        reject('Test Timeout');
      }, 20000);
      const result = await fn();
      clearTimeout(timeout);
      return resolve(result);
    })();
  });
};

(async () => {
  try {
    console.log('Testing system:');
    console.log(await testWithTimeout(si.system));

    console.log('Testing cpu:');
    console.log(await testWithTimeout(si.cpu));

    console.log('Testing mem:');
    console.log(await testWithTimeout(si.mem));

    console.log('Testing memLayout:');
    console.log(await testWithTimeout(si.memLayout));

    console.log('Testing graphics:');
    console.log(await testWithTimeout(si.graphics));

    console.log('Testing diskLayout:');
    console.log(await testWithTimeout(si.diskLayout));

    console.log('Testing osInfo:');
    console.log(await testWithTimeout(si.osInfo));

    console.log('Testing networkInterfaces:');
    console.log(await testWithTimeout(si.networkInterfaces));

    console.log('Testing networkInterfaceDefault:');
    console.log(await testWithTimeout(si.networkInterfaceDefault));

    console.log('Testing time:');
    console.log(await testWithTimeout(si.time));

    console.log('Testing currentLoad:');
    console.log(await testWithTimeout(si.currentLoad));

    console.log('Testing cpuTemperature:');
    console.log(await testWithTimeout(si.cpuTemperature));

    console.log('Testing UUID:');
    console.log(await testWithTimeout(si.uuid));

    console.log('Testing versions:');
    console.log(await testWithTimeout(si.versions));

    console.log('All tests complete.');
    process.exit(0);
  } catch (e) {
    console.log(e);
    console.log('One or more tests failed.');
    process.exit(1);
  }
})();
<|endoftext|>


<commit_before>/* ========================================================================
 * DBH-PG: test
 * ========================================================================
 * Copyright 2014 Sapienlab
 * Licensed under MIT (https://github.com/sapienlab/dbh-pg/blob/master/LICENSE)
 * ======================================================================== */
'use strict';

describe('DBH', function() {

    var assert = require('assert'),
        DBH = require('../'),
        Promise = require('bluebird'),
        using = Promise.using,
        db = new DBH('postgres://postgres@localhost/db2test'),
        people = [
            {name: 'Aaron',    age: 10},
            {name: 'Brian',    age: 20},
            {name: 'Chris',    age: 30},
            {name: 'David',    age: 40},
            {name: 'Elvis',    age: 50},
            {name: 'Frank',    age: 60},
            {name: 'Grace',    age: 70},
            {name: 'Haley',    age: 80},
            {name: 'Irma',     age: 90},
            {name: 'Jenny',    age: 100},
            {name: 'Kevin',    age: 110},
            {name: 'Larry',    age: 120},
            {name: 'Michelle', age: 130},
            {name: 'Nancy',    age: 140},
            {name: 'Olivia',   age: 150},
            {name: 'Peter',    age: 160},
            {name: 'Quinn',    age: 170},
            {name: 'Ronda',    age: 180},
            {name: 'Shelley',  age: 190},
            {name: 'Tobias',   age: 200},
            {name: 'Uma',      age: 210},
            {name: 'Veena',    age: 220},
            {name: 'Wanda',    age: 230},
            {name: 'Xavier',   age: 240},
            {name: 'Yoyo',     age: 250},
            {name: 'Zanzabar', age: 260}
        ];

    before(function() {

        Promise.longStackTraces();

        db.verbose = true;

        return using(db.conn(), function (conn) {
            return conn.exec(
                'create table person(\
                    id serial primary key,\
                    name varchar(10),\
                    age integer\
                )'
            ).then(function () {
                var me = this,
                prepared = DBH.prepare('insert into person(name, age) values ($1, $2)');
                return Promise.all(people.map(function (person) {
                    return me.exec(prepared(person.name, person.age));
                }));
            })
        });

    });

    describe('elemental', function() {

        it('db is instance of DBH', function() {
            assert.equal(db instanceof DBH, true);
        });

    });

    describe('#conn', function() {

        it('create connection', function() {
            return using(db.conn(), function (conn) {
                return true;
            });
        });

        it('exec "select count(age) from person" whith conn.exec', function() {
            return using(db.conn(), function (conn) {
                return conn.exec('select count(age) from person')
                    .then(function (result) {
                        assert.equal(result.rows[0].count, 26);
                    });
            });
        });

        it('exec "select count(age) from person" whith conn.count', function() {
            return using(db.conn(), function (conn) {
                return conn.count('person')
                    .then(function (count) {
                        assert.equal(count, 26);
                    });
            });
        });

        it('exec "select count(age) from person" whith conn.fetchScalar', function() {
            return using(db.conn(), function (conn) {
                return conn.fetchScalar('select count(age) from person')
                    .then(function (count) {
                        assert.equal(count, 26);
                    });
            });
        });

    });

});
<commit_msg>Update db.js<commit_after>/* ========================================================================
 * DBH-PG: test
 * ========================================================================
 * Copyright 2014 Sapienlab
 * Licensed under MIT (https://github.com/sapienlab/dbh-pg/blob/master/LICENSE)
 * ======================================================================== */
'use strict';

describe('DBH', function() {

    var assert = require('assert'),
        DBH = require('../'),
        Promise = require('bluebird'),
        using = Promise.using,
        db = new DBH('postgres://postgres@localhost/db2test'),
        people = [
            {name: 'Aaron',    age: 10},
            {name: 'Brian',    age: 20},
            {name: 'Chris',    age: 30},
            {name: 'David',    age: 40},
            {name: 'Elvis',    age: 50},
            {name: 'Frank',    age: 60},
            {name: 'Grace',    age: 70},
            {name: 'Haley',    age: 80},
            {name: 'Irma',     age: 90},
            {name: 'Jenny',    age: 100},
            {name: 'Kevin',    age: 110},
            {name: 'Larry',    age: 120},
            {name: 'Michelle', age: 130},
            {name: 'Nancy',    age: 140},
            {name: 'Olivia',   age: 150},
            {name: 'Peter',    age: 160},
            {name: 'Quinn',    age: 170},
            {name: 'Ronda',    age: 180},
            {name: 'Shelley',  age: 190},
            {name: 'Tobias',   age: 200},
            {name: 'Uma',      age: 210},
            {name: 'Veena',    age: 220},
            {name: 'Wanda',    age: 230},
            {name: 'Xavier',   age: 240},
            {name: 'Yoyo',     age: 250},
            {name: 'Zanzabar', age: 260}
        ];

    before(function() {

        Promise.longStackTraces();

        db.verbose = true;

        return using(db.conn(), function (conn) {
            return conn.exec(
                'create table person(\
                    id serial primary key,\
                    name varchar(10),\
                    age integer\
                )'
            ).then(function () {
                var me = this,
                prepared = DBH.prepare('insert into person(name, age) values ($name, $age)');
                return Promise.all(people.map(function (person) {
                    return me.exec(prepared(person));
                }));
            })
        });

    });

    describe('elemental', function() {

        it('db is instance of DBH', function() {
            assert.equal(db instanceof DBH, true);
        });

    });

    describe('#conn', function() {

        it('create connection', function() {
            return using(db.conn(), function (conn) {
                return true;
            });
        });

        it('exec "select count(age) from person" whith conn.exec', function() {
            return using(db.conn(), function (conn) {
                return conn.exec('select count(age) from person')
                    .then(function (result) {
                        assert.equal(result.rows[0].count, 26);
                    });
            });
        });

        it('exec "select count(age) from person" whith conn.count', function() {
            return using(db.conn(), function (conn) {
                return conn.count('person')
                    .then(function (count) {
                        assert.equal(count, 26);
                    });
            });
        });

        it('exec "select count(age) from person" whith conn.fetchScalar', function() {
            return using(db.conn(), function (conn) {
                return conn.fetchScalar('select count(age) from person')
                    .then(function (count) {
                        assert.equal(count, 26);
                    });
            });
        });

    });

});
<|endoftext|>


<commit_before>exports.baseTechName = 'vanilla.js';

exports.techMixin = {

    getSuffixes : function() {
        return ['vanilla.js', 'node.js'];
    },

    getCreateSuffixes : function() {
        return ['node.js'];
    },

    getBuildSuffixes : function() {
        return ['node.js'];
    },

    getBuildSuffixesMap : function() {
        return {
            'node.js' : this.getSuffixes()
        };
    },

    getYmChunk : function() {
        var ymRelPath = this.__base.apply(this, arguments);
        return [
            "if(typeof module !== 'undefined') {\n",
            "modules = " + this.getBuildResultChunk(ymRelPath),
            "}\n"
        ].join('');
    },

    getBuildResultChunk : function(relPath, path) {
        var fChar = relPath.charAt(0);
        if(fChar !== '/' && fChar !== '.') {
            relPath = './' + relPath;
        }
        return "require('" + relPath + "');\n";
    }

};<commit_msg>Generated module paths should respect windows systems (fix #274)<commit_after>var PATH = require('path');

exports.baseTechName = 'vanilla.js';

exports.techMixin = {

    getSuffixes : function() {
        return ['vanilla.js', 'node.js'];
    },

    getCreateSuffixes : function() {
        return ['node.js'];
    },

    getBuildSuffixes : function() {
        return ['node.js'];
    },

    getBuildSuffixesMap : function() {
        return {
            'node.js' : this.getSuffixes()
        };
    },

    getYmChunk : function() {
        var ymRelPath = this.__base.apply(this, arguments);
        return [
            "if(typeof module !== 'undefined') {\n",
            "modules = " + this.getBuildResultChunk(ymRelPath),
            "}\n"
        ].join('');
    },

    getBuildResultChunk : function(relPath) {
        // NOTE: module's path is always an UNIX path,
        // so `relPath` should be converted on Windows systems
        if(PATH.sep !== '/') {
            relPath = relPath.replace(/\\/g, '/');
        }
        // NOTE: Without a leading '/' or './' to indicate a file, the module is either
        // a "core module" or is loaded from a node_modules folder
        if(/^\w/.test(relPath)) {
            relPath = './' + relPath;
        }
        return 'require(\'' + relPath + '\');\n';
    }

};
<|endoftext|>


<commit_before>const webdriver = require("selenium-webdriver");
const driver = new webdriver.Builder().forBrowser("chrome").build();

driver.get("http://localhost:8080/test/");
driver.wait(webdriver.until.titleMatches(/: Complete$/), 20).then(exit).catch(exit);

function exit() {
    driver.manage().logs().get(webdriver.logging.Type.BROWSER).then((entries) => {
        entries.forEach((entry) => {
            console.log('[%s] %s', entry.level.name, entry.message);
        });
    });
    require("fs").writeFileSync("result.html", driver.executeScript("return document.documentElement.outerHTML"));
    driver.takeScreenshot().then((data) => {
        require("fs").writeFileSync("screenshot.png", data, "base64");
        driver.quit();
    });
}
<commit_msg>Setting circleci up.<commit_after>const webdriver = require("selenium-webdriver");
const driver = new webdriver.Builder().forBrowser("chrome").build();

driver.get("http://localhost:8080/test/");
driver.wait(webdriver.until.titleMatches(/: Complete$/), 20).then(exit).catch(exit);

function exit() {
    driver.manage().logs().get(webdriver.logging.Type.BROWSER).then((entries) => {
        entries.forEach((entry) => {
            console.log('[%s] %s', entry.level.name, entry.message);
        });
    });
    driver.executeScript("return document.documentElement.outerHTML").then((html) => {
        require("fs").writeFileSync("result.html", html);
    });
    driver.takeScreenshot().then((data) => {
        require("fs").writeFileSync("screenshot.png", data, "base64");
        driver.quit();
    });
}
<|endoftext|>


<commit_before>import React from 'react'
import {ApplyTheme} from '@instructure/ui-themeable'
import {ApplyTextDirection} from '@instructure/ui-i18n'
import '@instructure/canvas-high-contrast-theme'
import '@instructure/canvas-theme'

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
}

export const globalTypes = {
  canvasTheme: {
    name: 'Canvas Theme',
    description: 'Default or High Contrast',
    defaultValue: 'canvas',
    toolbar: {
      icon: 'user',
      items: ['canvas', 'canvas-high-contrast']
    }
  },
  bidirectional: {
    name: 'Bidirectional',
    description: 'Left-to-right or Right-to-left',
    defaultValue: 'ltr',
    toolbar: {
      icon: 'transfer',
      items: ['ltr', 'rtl']
    }
  }
}

const canvasThemeProvider = (Story, context) => {
  const canvasTheme = context.globals.canvasTheme
  return (
    <ApplyTheme theme={ApplyTheme.generateTheme(canvasTheme)}>
      <Story {...context}/>
    </ApplyTheme>
  )
}

const bidirectionalProvider = (Story, context) => {
  const direction = context.globals.bidirectional
  return (
    <ApplyTextDirection dir={direction}>
          <Story {...context}/>
    </ApplyTextDirection>
  )
}

export const decorators = [canvasThemeProvider, bidirectionalProvider]
<commit_msg>Add lolcalize toggle to storybook<commit_after>import React from 'react'
import {ApplyTheme} from '@instructure/ui-themeable'
import {ApplyTextDirection} from '@instructure/ui-i18n'
import I18n from 'i18n-js'
import i18nLolcalize from 'coffeescripts/str/i18nLolcalize'
import '@instructure/canvas-high-contrast-theme'
import '@instructure/canvas-theme'

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
}

export const globalTypes = {
  canvasTheme: {
    name: 'Canvas Theme',
    description: 'Default or High Contrast',
    defaultValue: 'canvas',
    toolbar: {
      icon: 'accessibility',
      items: ['canvas', 'canvas-high-contrast']
    }
  },
  bidirectional: {
    name: 'Bidirectional',
    description: 'Left-to-right or Right-to-left',
    defaultValue: 'ltr',
    toolbar: {
      icon: 'transfer',
      items: ['ltr', 'rtl']
    }
  },
  lolcalize: {
    name: 'LOLcalize',
    description: 'Enable/Disable LOLcalize (requires page refresh to take effect)',
    defaultValue: 'disable',
    toolbar: {
      icon: 'facehappy',
      items: ['enable', 'disable']
    }
  }
}

const canvasThemeProvider = (Story, context) => {
  const canvasTheme = context.globals.canvasTheme
  return (
    <ApplyTheme theme={ApplyTheme.generateTheme(canvasTheme)}>
      <Story {...context}/>
    </ApplyTheme>
  )
}

const bidirectionalProvider = (Story, context) => {
  const direction = context.globals.bidirectional
  return (
    <ApplyTextDirection dir={direction}>
      <Story {...context}/>
    </ApplyTextDirection>
  )
}

const lolcalizeProvider = (Story, context) => {
  const enableLolcalize = context.globals.lolcalize
  if (enableLolcalize === 'enable') {
    I18n.CallHelpers.normalizeDefault = i18nLolcalize
  }
  return (
    <Story {...context}/>
  )
}

export const decorators = [canvasThemeProvider, bidirectionalProvider, lolcalizeProvider]
<|endoftext|>


<commit_before>// Load data tiles from an AJAX data source
L.TileLayer.Ajax = L.TileLayer.extend({
    _requests: [],
    _addTile: function (tilePoint) {
        var tile = { datum: null, processed: false };
        this._tiles[tilePoint.x + ':' + tilePoint.y] = tile;
        this._loadTile(tile, tilePoint);
    },
    // XMLHttpRequest handler; closure over the XHR object, the layer, and the tile
    _xhrHandler: function (req, layer, tile, tilePoint) {
        return function () {
            if (req.readyState !== 4) {
                return;
            }
            var s = req.status;
            if ((s >= 200 && s < 300 && s != 204) || s === 304) {
                tile.datum = JSON.parse(req.responseText);
                layer._tileLoaded(tile, tilePoint);
            } else {
                layer._tileLoaded(tile, tilePoint);
            }
        };
    },
    // Load the requested tile via AJAX
    _loadTile: function (tile, tilePoint) {
        this._adjustTilePoint(tilePoint);
        var layer = this;
        var req = new XMLHttpRequest();
        this._requests.push(req);
        req.onreadystatechange = this._xhrHandler(req, layer, tile, tilePoint);
        req.open('GET', this.getTileUrl(tilePoint), true);
        req.send();
    },
    _reset: function () {
        L.TileLayer.prototype._reset.apply(this, arguments);
        for (var i = 0; i < this._requests.length; i++) {
            this._requests[i].abort();
        }
        this._requests = [];
    },
    _update: function () {
        if (this._map && this._map._panTransition && this._map._panTransition._inProgress) { return; }
        if (this._tilesToLoad < 0) { this._tilesToLoad = 0; }
        L.TileLayer.prototype._update.apply(this, arguments);
    }
});

L.TileLayer.GeoJSON = L.TileLayer.Ajax.extend({
    // Store each GeometryCollection's layer by key, if options.unique function is present
    _keyLayers: {},

    // Used to calculate svg path string for clip path elements
    _clipPathRectangles: {},

    initialize: function (url, options, geojsonOptions) {
        L.TileLayer.Ajax.prototype.initialize.call(this, url, options);
        this.geojsonLayer = new L.GeoJSON(null, geojsonOptions);
    },
    onAdd: function (map) {
        this._map = map;
        L.TileLayer.Ajax.prototype.onAdd.call(this, map);
        map.addLayer(this.geojsonLayer);
    },
    onRemove: function (map) {
        map.removeLayer(this.geojsonLayer);
        L.TileLayer.Ajax.prototype.onRemove.call(this, map);
    },
    _reset: function () {
        this.geojsonLayer.clearLayers();
        this._keyLayers = {};
        this._removeOldClipPaths();
        L.TileLayer.Ajax.prototype._reset.apply(this, arguments);
    },

    _getUniqueId: function() {
        return String(this._leaflet_id || ''); // jshint ignore:line
    },

    // Remove clip path elements from other earlier zoom levels
    _removeOldClipPaths: function  () {
        for (var clipPathId in this._clipPathRectangles) {
            var prefix = clipPathId.split('tileClipPath')[0];
            if (this._getUniqueId() === prefix) {
                var clipPathZXY = clipPathId.split('_').slice(1);
                var zoom = parseInt(clipPathZXY[0], 10);
                if (zoom !== this._map.getZoom()) {
                    var rectangle = this._clipPathRectangles[clipPathId];
                    this._map.removeLayer(rectangle);
                    var clipPath = document.getElementById(clipPathId);
                    if (clipPath !== null) {
                        clipPath.parentNode.removeChild(clipPath);
                    }
                    delete this._clipPathRectangles[clipPathId];
                }
            }
        }
    },

    // Recurse LayerGroups and call func() on L.Path layer instances
    _recurseLayerUntilPath: function (func, layer) {
        if (layer instanceof L.Path) {
            func(layer);
        }
        else if (layer instanceof L.LayerGroup) {
            // Recurse each child layer
            layer.getLayers().forEach(this._recurseLayerUntilPath.bind(this, func), this);
        }
    },

    _clipLayerToTileBoundary: function (layer, tilePoint) {
        // Only perform SVG clipping if the browser is using SVG
        if (!L.Path.SVG) { return; }
        if (!this._map) { return; }

        if (!this._map._pathRoot) {
            this._map._pathRoot = L.Path.prototype._createElement('svg');
            this._map._panes.overlayPane.appendChild(this._map._pathRoot);
        }
        var svg = this._map._pathRoot;

        // create the defs container if it doesn't exist
        var defs = null;
        if (svg.getElementsByTagName('defs').length === 0) {
            defs = document.createElementNS(L.Path.SVG_NS, 'defs');
            svg.insertBefore(defs, svg.firstChild);
        }
        else {
            defs = svg.getElementsByTagName('defs')[0];
        }

        // Create the clipPath for the tile if it doesn't exist
        var clipPathId = this._getUniqueId() + 'tileClipPath_' + tilePoint.z + '_' + tilePoint.x + '_' + tilePoint.y;
        var clipPath = document.getElementById(clipPathId);
        if (clipPath === null) {
            clipPath = document.createElementNS(L.Path.SVG_NS, 'clipPath');
            clipPath.id = clipPathId;

            // Create a hidden L.Rectangle to represent the tile's area
            var tileSize = this.options.tileSize,
            nwPoint = tilePoint.multiplyBy(tileSize),
            sePoint = nwPoint.add([tileSize, tileSize]),
            nw = this._map.unproject(nwPoint),
            se = this._map.unproject(sePoint);
            this._clipPathRectangles[clipPathId] = new L.Rectangle(new L.LatLngBounds([nw, se]), {
                opacity: 0,
                fillOpacity: 0,
                clickable: false,
                noClip: true
            });
            this._map.addLayer(this._clipPathRectangles[clipPathId]);

            // Add a clip path element to the SVG defs element
            // With a path element that has the hidden rectangle's SVG path string
            var path = document.createElementNS(L.Path.SVG_NS, 'path');
            var pathString = this._clipPathRectangles[clipPathId].getPathString();
            path.setAttribute('d', pathString);
            clipPath.appendChild(path);
            defs.appendChild(clipPath);
        }

        // Add the clip-path attribute to reference the id of the tile clipPath
        this._recurseLayerUntilPath(function (pathLayer) {
            pathLayer._container.setAttribute('clip-path', 'url(#' + clipPathId + ')');
        }, layer);
    },

    // Add a geojson object from a tile to the GeoJSON layer
    // * If the options.unique function is specified, merge geometries into GeometryCollections
    // grouped by the key returned by options.unique(feature) for each GeoJSON feature
    // * If options.clipTiles is set, and the browser is using SVG, perform SVG clipping on each
    // tile's GeometryCollection
    addTileData: function (geojson, tilePoint) {
        var features = L.Util.isArray(geojson) ? geojson : geojson.features,
            i, len, feature;

        if (features) {
            for (i = 0, len = features.length; i < len; i++) {
                // Only add this if geometry or geometries are set and not null
                feature = features[i];
                if (feature.geometries || feature.geometry || feature.features || feature.coordinates) {
                    this.addTileData(features[i], tilePoint);
                }
            }
            return this;
        }

        var options = this.geojsonLayer.options;

        if (options.filter && !options.filter(geojson)) { return; }

        var parentLayer = this.geojsonLayer;
        var incomingLayer = null;
        if (this.options.unique && typeof(this.options.unique) === 'function') {
            var key = this.options.unique(geojson);

            // When creating the layer for a unique key,
            // Force the geojson to be a geometry collection
            if (!(key in this._keyLayers && geojson.geometry.type !== 'GeometryCollection')) {
                geojson.geometry = {
                    type: 'GeometryCollection',
                    geometries: [geojson.geometry]
                };
            }

            // Transform the geojson into a new Layer
            try {
                incomingLayer = L.GeoJSON.geometryToLayer(geojson, options.pointToLayer, options.coordsToLatLng);
            }
            // Ignore GeoJSON objects that could not be parsed
            catch (e) {
                return this;
            }

            incomingLayer.feature = L.GeoJSON.asFeature(geojson);
            // Add the incoming Layer to existing key's GeometryCollection
            if (key in this._keyLayers) {
                parentLayer = this._keyLayers[key];
                parentLayer.feature.geometry.geometries.push(geojson.geometry);
            }
            // Convert the incoming GeoJSON feature into a new GeometryCollection layer
            else {
                this._keyLayers[key] = incomingLayer;
            }
        }
        // Add the incoming geojson feature to the L.GeoJSON Layer
        else {
            // Transform the geojson into a new layer
            try {
                incomingLayer = L.GeoJSON.geometryToLayer(geojson, options.pointToLayer, options.coordsToLatLng);
            }
            // Ignore GeoJSON objects that could not be parsed
            catch (e) {
                return this;
            }
            incomingLayer.feature = L.GeoJSON.asFeature(geojson);
        }
        incomingLayer.defaultOptions = incomingLayer.options;

        this.geojsonLayer.resetStyle(incomingLayer);

        if (options.onEachFeature) {
            options.onEachFeature(geojson, incomingLayer);
        }
        parentLayer.addLayer(incomingLayer);

        // If options.clipTiles is set and the browser is using SVG
        // then clip the layer using SVG clipping
        if (this.options.clipTiles) {
            this._clipLayerToTileBoundary(incomingLayer, tilePoint);
        }
        return this;
    },

    _tileLoaded: function (tile, tilePoint) {
        L.TileLayer.Ajax.prototype._tileLoaded.apply(this, arguments);
        if (tile.datum === null) { return null; }
        this.addTileData(tile.datum, tilePoint);
    }
});
<commit_msg>Fixes #36 Angular 2.0.0 breaks svg clipping path By appending window.location to the referenced clip-path<commit_after>// Load data tiles from an AJAX data source
L.TileLayer.Ajax = L.TileLayer.extend({
    _requests: [],
    _addTile: function (tilePoint) {
        var tile = { datum: null, processed: false };
        this._tiles[tilePoint.x + ':' + tilePoint.y] = tile;
        this._loadTile(tile, tilePoint);
    },
    // XMLHttpRequest handler; closure over the XHR object, the layer, and the tile
    _xhrHandler: function (req, layer, tile, tilePoint) {
        return function () {
            if (req.readyState !== 4) {
                return;
            }
            var s = req.status;
            if ((s >= 200 && s < 300 && s != 204) || s === 304) {
                tile.datum = JSON.parse(req.responseText);
                layer._tileLoaded(tile, tilePoint);
            } else {
                layer._tileLoaded(tile, tilePoint);
            }
        };
    },
    // Load the requested tile via AJAX
    _loadTile: function (tile, tilePoint) {
        this._adjustTilePoint(tilePoint);
        var layer = this;
        var req = new XMLHttpRequest();
        this._requests.push(req);
        req.onreadystatechange = this._xhrHandler(req, layer, tile, tilePoint);
        req.open('GET', this.getTileUrl(tilePoint), true);
        req.send();
    },
    _reset: function () {
        L.TileLayer.prototype._reset.apply(this, arguments);
        for (var i = 0; i < this._requests.length; i++) {
            this._requests[i].abort();
        }
        this._requests = [];
    },
    _update: function () {
        if (this._map && this._map._panTransition && this._map._panTransition._inProgress) { return; }
        if (this._tilesToLoad < 0) { this._tilesToLoad = 0; }
        L.TileLayer.prototype._update.apply(this, arguments);
    }
});

L.TileLayer.GeoJSON = L.TileLayer.Ajax.extend({
    // Store each GeometryCollection's layer by key, if options.unique function is present
    _keyLayers: {},

    // Used to calculate svg path string for clip path elements
    _clipPathRectangles: {},

    initialize: function (url, options, geojsonOptions) {
        L.TileLayer.Ajax.prototype.initialize.call(this, url, options);
        this.geojsonLayer = new L.GeoJSON(null, geojsonOptions);
    },
    onAdd: function (map) {
        this._map = map;
        L.TileLayer.Ajax.prototype.onAdd.call(this, map);
        map.addLayer(this.geojsonLayer);
    },
    onRemove: function (map) {
        map.removeLayer(this.geojsonLayer);
        L.TileLayer.Ajax.prototype.onRemove.call(this, map);
    },
    _reset: function () {
        this.geojsonLayer.clearLayers();
        this._keyLayers = {};
        this._removeOldClipPaths();
        L.TileLayer.Ajax.prototype._reset.apply(this, arguments);
    },

    _getUniqueId: function() {
        return String(this._leaflet_id || ''); // jshint ignore:line
    },

    // Remove clip path elements from other earlier zoom levels
    _removeOldClipPaths: function  () {
        for (var clipPathId in this._clipPathRectangles) {
            var prefix = clipPathId.split('tileClipPath')[0];
            if (this._getUniqueId() === prefix) {
                var clipPathZXY = clipPathId.split('_').slice(1);
                var zoom = parseInt(clipPathZXY[0], 10);
                if (zoom !== this._map.getZoom()) {
                    var rectangle = this._clipPathRectangles[clipPathId];
                    this._map.removeLayer(rectangle);
                    var clipPath = document.getElementById(clipPathId);
                    if (clipPath !== null) {
                        clipPath.parentNode.removeChild(clipPath);
                    }
                    delete this._clipPathRectangles[clipPathId];
                }
            }
        }
    },

    // Recurse LayerGroups and call func() on L.Path layer instances
    _recurseLayerUntilPath: function (func, layer) {
        if (layer instanceof L.Path) {
            func(layer);
        }
        else if (layer instanceof L.LayerGroup) {
            // Recurse each child layer
            layer.getLayers().forEach(this._recurseLayerUntilPath.bind(this, func), this);
        }
    },

    _clipLayerToTileBoundary: function (layer, tilePoint) {
        // Only perform SVG clipping if the browser is using SVG
        if (!L.Path.SVG) { return; }
        if (!this._map) { return; }

        if (!this._map._pathRoot) {
            this._map._pathRoot = L.Path.prototype._createElement('svg');
            this._map._panes.overlayPane.appendChild(this._map._pathRoot);
        }
        var svg = this._map._pathRoot;

        // create the defs container if it doesn't exist
        var defs = null;
        if (svg.getElementsByTagName('defs').length === 0) {
            defs = document.createElementNS(L.Path.SVG_NS, 'defs');
            svg.insertBefore(defs, svg.firstChild);
        }
        else {
            defs = svg.getElementsByTagName('defs')[0];
        }

        // Create the clipPath for the tile if it doesn't exist
        var clipPathId = this._getUniqueId() + 'tileClipPath_' + tilePoint.z + '_' + tilePoint.x + '_' + tilePoint.y;
        var clipPath = document.getElementById(clipPathId);
        if (clipPath === null) {
            clipPath = document.createElementNS(L.Path.SVG_NS, 'clipPath');
            clipPath.id = clipPathId;

            // Create a hidden L.Rectangle to represent the tile's area
            var tileSize = this.options.tileSize,
            nwPoint = tilePoint.multiplyBy(tileSize),
            sePoint = nwPoint.add([tileSize, tileSize]),
            nw = this._map.unproject(nwPoint),
            se = this._map.unproject(sePoint);
            this._clipPathRectangles[clipPathId] = new L.Rectangle(new L.LatLngBounds([nw, se]), {
                opacity: 0,
                fillOpacity: 0,
                clickable: false,
                noClip: true
            });
            this._map.addLayer(this._clipPathRectangles[clipPathId]);

            // Add a clip path element to the SVG defs element
            // With a path element that has the hidden rectangle's SVG path string
            var path = document.createElementNS(L.Path.SVG_NS, 'path');
            var pathString = this._clipPathRectangles[clipPathId].getPathString();
            path.setAttribute('d', pathString);
            clipPath.appendChild(path);
            defs.appendChild(clipPath);
        }

        // Add the clip-path attribute to reference the id of the tile clipPath
        this._recurseLayerUntilPath(function (pathLayer) {
            pathLayer._container.setAttribute('clip-path', 'url(' + window.location.href + '#' + clipPathId + ')');
        }, layer);
    },

    // Add a geojson object from a tile to the GeoJSON layer
    // * If the options.unique function is specified, merge geometries into GeometryCollections
    // grouped by the key returned by options.unique(feature) for each GeoJSON feature
    // * If options.clipTiles is set, and the browser is using SVG, perform SVG clipping on each
    // tile's GeometryCollection
    addTileData: function (geojson, tilePoint) {
        var features = L.Util.isArray(geojson) ? geojson : geojson.features,
            i, len, feature;

        if (features) {
            for (i = 0, len = features.length; i < len; i++) {
                // Only add this if geometry or geometries are set and not null
                feature = features[i];
                if (feature.geometries || feature.geometry || feature.features || feature.coordinates) {
                    this.addTileData(features[i], tilePoint);
                }
            }
            return this;
        }

        var options = this.geojsonLayer.options;

        if (options.filter && !options.filter(geojson)) { return; }

        var parentLayer = this.geojsonLayer;
        var incomingLayer = null;
        if (this.options.unique && typeof(this.options.unique) === 'function') {
            var key = this.options.unique(geojson);

            // When creating the layer for a unique key,
            // Force the geojson to be a geometry collection
            if (!(key in this._keyLayers && geojson.geometry.type !== 'GeometryCollection')) {
                geojson.geometry = {
                    type: 'GeometryCollection',
                    geometries: [geojson.geometry]
                };
            }

            // Transform the geojson into a new Layer
            try {
                incomingLayer = L.GeoJSON.geometryToLayer(geojson, options.pointToLayer, options.coordsToLatLng);
            }
            // Ignore GeoJSON objects that could not be parsed
            catch (e) {
                return this;
            }

            incomingLayer.feature = L.GeoJSON.asFeature(geojson);
            // Add the incoming Layer to existing key's GeometryCollection
            if (key in this._keyLayers) {
                parentLayer = this._keyLayers[key];
                parentLayer.feature.geometry.geometries.push(geojson.geometry);
            }
            // Convert the incoming GeoJSON feature into a new GeometryCollection layer
            else {
                this._keyLayers[key] = incomingLayer;
            }
        }
        // Add the incoming geojson feature to the L.GeoJSON Layer
        else {
            // Transform the geojson into a new layer
            try {
                incomingLayer = L.GeoJSON.geometryToLayer(geojson, options.pointToLayer, options.coordsToLatLng);
            }
            // Ignore GeoJSON objects that could not be parsed
            catch (e) {
                return this;
            }
            incomingLayer.feature = L.GeoJSON.asFeature(geojson);
        }
        incomingLayer.defaultOptions = incomingLayer.options;

        this.geojsonLayer.resetStyle(incomingLayer);

        if (options.onEachFeature) {
            options.onEachFeature(geojson, incomingLayer);
        }
        parentLayer.addLayer(incomingLayer);

        // If options.clipTiles is set and the browser is using SVG
        // then clip the layer using SVG clipping
        if (this.options.clipTiles) {
            this._clipLayerToTileBoundary(incomingLayer, tilePoint);
        }
        return this;
    },

    _tileLoaded: function (tile, tilePoint) {
        L.TileLayer.Ajax.prototype._tileLoaded.apply(this, arguments);
        if (tile.datum === null) { return null; }
        this.addTileData(tile.datum, tilePoint);
    }
});
<|endoftext|>