<commit_before>
var globals = require("./globals.js"),
  fieldTags = globals.fieldTags,
  fieldTagNames = globals.fieldTagNames,
  arrayFields = globals.arrayFields,
  fieldTypes = globals.fieldTypes,
  fieldTypeNames = globals.fieldTypeNames;

var sum = function(array, start, end) {
  var s = 0;
  for (var i = start; i < end; ++i) {
    s += array[i];
  }
  return s;
};

/**
 * GeoTIFF sub-file image.
 * @constructor
 * @param {Object} fileDirectory The parsed file directory
 * @param {Object} geoKeys The parsed geo-keys
 * @param {DataView} dataView The DataView for the underlying file.
 * @param {Boolean} littleEndian Whether the file is encoded in little or big endian
 */

var GeoTIFFImage = function(fileDirectory, geoKeys, dataView, littleEndian) {
  this.fileDirectory = fileDirectory;
  this.geoKeys = geoKeys;
  this.dataView = dataView;
  this.littleEndian = littleEndian;
  this.tiles = {};
  this.isTiled = (fileDirectory.StripOffsets) ? false : true;
  var planarConfiguration = fileDirectory.PlanarConfiguration;
  this.planarConfiguration = (typeof planarConfiguration === "undefined") ? 1 : planarConfiguration;
  if (this.planarConfiguration !== 1 && this.planarConfiguration !== 2) {
    throw new Error("Invalid planar configuration.");
  }
};

GeoTIFFImage.prototype = {
  /**
   * Returns the associated parsed file directory.
   * @returns {Object} the parsed file directory
   */
  getFileDirectory: function() {
    return this.fileDirectory;
  },
  /**
   * Returns the associated parsed geo keys.
   * @returns {Object} the parsed geo keys
   */
  getGeoKeys: function() {
    return this.geoKeys;
  },
  /**
   * Returns the width of the image.
   * @returns {Number} the width of the image
   */
  getWidth: function() {
    return this.fileDirectory.ImageWidth;
  },
  /**
   * Returns the height of the image.
   * @returns {Number} the height of the image
   */
  getHeight: function() {
    return this.fileDirectory.ImageLength;
  },
  /**
   * Returns the number of samples per pixel.
   * @returns {Number} the number of samples per pixel
   */
  getSamplesPerPixel: function() {
    return this.fileDirectory.SamplesPerPixel;
  },
  /**
   * Returns the width of each tile.
   * @returns {Number} the width of each tile
   */
  getTileWidth: function() {
    return this.isTiled ? this.fileDirectory.TileWidth : this.getWidth();
  },
  /**
   * Returns the height of each tile.
   * @returns {Number} the height of each tile
   */
  getTileHeight: function() {
    return this.isTiled ? this.fileDirectory.TileLength : this.fileDirectory.RowsPerStrip;
  },

  getBytesPerPixel: function() {
    var bitsPerSample = 0;
    for (var i = 0; i < this.fileDirectory.BitsPerSample.length; ++i) {
      var bits = this.fileDirectory.BitsPerSample[i];
      if ((bits % 8) !== 0) {
        throw new Error("Sample bit-width of " + bits + " is not supported.");
      }
      else if (bits !== this.fileDirectory.BitsPerSample[0]) {
        throw new Error("Differing size of samples in a pixel are not supported.");
      }
      bitsPerSample += bits;
    }
    return bitsPerSample / 8;
  },

  getSampleByteSize: function(i) {
    if (i >= this.fileDirectory.BitsPerSample.length) {
      throw new RangeError("Sample index " + i + " is out of range.");
    }
    var bits = this.fileDirectory.BitsPerSample[i];
    if ((bits % 8) !== 0) {
      throw new Error("Sample bit-width of " + bits + " is not supported.");
    }
    return (bits / 8);
  },

  decodeBlock: function(offset, byteCount, outSize) {
    var slice = this.dataView.buffer.slice(offset, offset + byteCount);
    switch (this.fileDirectory.Compression) {
      case 1:  // no compression
        return slice;
      case 5: // LZW
        throw new Error("LZW compression not supported.");
      case 6: // JPEG
        throw new Error("JPEG compression not supported.");
      case 8: // Deflate
        throw new Error("Deflate compression not supported.");
      //case 32946: // deflate ??
      //  throw new Error("Deflate compression not supported.");
      case 32773: // packbits
        throw new Error("PackBits compression not supported.");
      default:
        throw new Error("Unknown compresseion method identifier: " + this.fileDirectory.Compression);
    }
  },

  getReaderForSample: function(sampleIndex) {
    var format = this.fileDirectory.SampleFormat[sampleIndex];
    var bitsPerSample = this.fileDirectory.BitsPerSample[sampleIndex];
    switch (format) {
      case 1: // unsigned integer data
        switch (bitsPerSample) {
          case 8:
            return DataView.prototype.getUint8;
          case 16:
            return DataView.prototype.getUint16;
          case 32:
            return DataView.prototype.getUint32;
        }
        break;
      case 2: // twos complement signed integer data
        switch (bitsPerSample) {
          case 8:
            return DataView.prototype.getInt8;
          case 16:
            return DataView.prototype.getInt16;
          case 32:
            return DataView.prototype.getInt32;
        }
        break;
      case 3:
        switch (bitsPerSample) {
          case 32:
            return DataView.prototype.getFloat32;
          case 64:
            return DataView.prototype.getFloat64;
        }
        break;
    }
  },

  getArrayForSample: function(sampleIndex, size) {
    var format = this.fileDirectory.SampleFormat[sampleIndex];
    var bitsPerSample = this.fileDirectory.BitsPerSample[sampleIndex];
    switch (format) {
      case 1: // unsigned integer data
        switch (bitsPerSample) {
          case 8:
            return new Uint8Array(size);
          case 16:
            return new Uint16Array(size);
          case 32:
            return new Uint32Array(size);
        }
        break;
      case 2: // twos complement signed integer data
        switch (bitsPerSample) {
          case 8:
            return new Int8Array(size);
          case 16:
            return new Int16Array(size);
          case 32:
            return new Int32Array(size);
        }
        break;
      case 3: // floating point data
        switch (bitsPerSample) {
          case 32:
            return new Float32Array(size);
          case 64:
            return new Float64Array(size);
        }
        break;
    }
    throw Error("Unsupported data format/bitsPerSample");
  },

  /**
   * Returns the decoded strip or tile.
   * @param {Number} x the strip or tile x-offset
   * @param {Number} y the tile y-offset (0 for stripped images)
   * @param {Number} plane the planar configuration (1: "chunky", 2: "separate samples")
   * @returns {(Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array)}
   */
  getTileOrStrip: function(x, y, plane) {
    var numTilesPerRow = Math.ceil(this.getWidth() / this.getTileWidth());
    var numTilesPerCol = Math.ceil(this.getHeight() / this.getTileHeight());
    var index;
    if (this.planarConfiguration === 1) {
      index = y * numTilesPerRow + x;
    }
    else if (this.planarConfiguration === 2) {
      index = plane * numTilesPerRow * numTilesPerCol + y * numTilesPerRow + x;
    }

    if (index in this.tiles && false) {
        return this.tiles[index];
      }
      else {
        var offset, byteCount;
        if (this.isTiled) {
          offset = this.fileDirectory.TileOffsets[index];
          byteCount = this.fileDirectory.TileByteCounts[index];
        }
        else {
          offset = this.fileDirectory.StripOffsets[index];
          byteCount = this.fileDirectory.StripByteCounts[index];
        }
        return this.tiles[index] = this.decodeBlock(offset, byteCount);
      }
  },

  _readRaster: function(imageWindow, samples, valueArrays) {
    var tileWidth = this.getTileWidth();
    var tileHeight = this.getTileHeight();

    var minXTile = Math.floor(imageWindow[0] / tileWidth);
    var maxXTile = Math.ceil(imageWindow[2] / tileWidth);
    var minYTile = Math.floor(imageWindow[1] / tileHeight);
    var maxYTile = Math.ceil(imageWindow[3] / tileHeight);

    var numTilesPerRow = Math.ceil(this.getWidth() / tileWidth);

    var windowWidth = imageWindow[2] - imageWindow[0];
    var windowHeight = imageWindow[3] - imageWindow[1];

    var bytesPerPixel = this.getBytesPerPixel();
    var imageWidth = this.getWidth();

    var srcSampleOffsets = [];
    var sampleReaders = [];
    for (var i = 0; i < samples.length; ++i) {
      if (this.planarConfiguration === 1) {
        srcSampleOffsets.push(sum(this.fileDirectory.BitsPerSample, 0, samples[i]) / 8);
      }
      else {
        srcSampleOffsets.push(0);
      }
      sampleReaders.push(this.getReaderForSample(samples[i]));
    }

    for (var yTile = minYTile; yTile <= maxYTile; ++yTile) {
      for (var xTile = minXTile; xTile <= maxXTile; ++xTile) {

        var firstLine = yTile * tileHeight;
        var firstCol = xTile * tileWidth;
        var lastLine = (yTile + 1) * tileHeight;
        var lastCol = (xTile + 1) * tileWidth;

        for (var sampleIndex = 0; sampleIndex < samples.length; ++sampleIndex) {
          var sample = samples[sampleIndex];
          if (this.planarConfiguration === 2) {
            bytesPerPixel = this.getSampleByteSize(sample);
          }
          var tile = new DataView(this.getTileOrStrip(xTile, yTile, sample));

          for (var y = Math.max(0, imageWindow[1] - firstLine); y < Math.min(tileHeight, tileHeight - (lastLine - imageWindow[3])); ++y) {
            for (var x = Math.max(0, imageWindow[0] - firstCol); x < Math.min(tileWidth, tileWidth - (lastCol - imageWindow[2])); ++x) {
              var pixelOffset = (y * tileWidth + x) * bytesPerPixel;
              var windowCoordinate = (
                y + firstLine - imageWindow[1]
              ) * windowWidth + x + firstCol - imageWindow[0];
              valueArrays[sampleIndex][windowCoordinate] = sampleReaders[sampleIndex].call(tile, pixelOffset + srcSampleOffsets[sampleIndex], this.littleEndian);
            }
          }
        }
      }
    }
  },

  /**
   * Reads raster data from the image. This function reads all selected samples
   * into separate arrays of the correct type for that sample. When provided,
   * only a subset of the raster is read for each sample.
   *
   * @param {Array} [imageWindow=whole image] the subset to read data from.
   * @param {Array} [samples=all samples]
   * @returns {TypedArray[]} the requested data as a summary array, one TypedArray for each requested sample
   */
  readRasters: function(imageWindow, samples) {
    imageWindow = imageWindow || [0, 0, this.getWidth(), this.getHeight()];

    if (imageWindow[0] < 0 || imageWindow[1] < 0 || imageWindow[2] > this.getWidth() || imageWindow[3] > this.getHeight()) {
      throw new Error("Select window is out of image bounds.");
    }
    else if (imageWindow[0] > imageWindow[2] || imageWindow[1] > imageWindow[3]) {
      throw new Error("Invalid subsets");
    }

    var imageWindowWidth = imageWindow[2] - imageWindow[0];
    var imageWindowHeight = imageWindow[3] - imageWindow[1];
    var numPixels = imageWindowWidth * imageWindowHeight;
    var i;

    if (!samples) {
      samples = [];
      for (i=0; i < this.fileDirectory.SamplesPerPixel; ++i) {
        samples.push(i);
      }
    }
    else {
      for (i = 0; i < samples.length; ++i) {
        if (samples[i] >= this.fileDirectory.SamplesPerPixel) {
          throw new RangeError("Invalid sample index '" + samples[i] + "'.");
        }
      }
    }
    var valueArrays = [];
    for (i = 0; i < samples.length; ++i) {
      valueArrays.push(this.getArrayForSample(samples[i], numPixels));
    }

    this._readRaster(imageWindow, samples, valueArrays);
    return valueArrays;
  },

  /**
   * Returns an array of tiepoints.
   * @returns {Object[]}
   */
  getTiePoints: function() {
    if (!this.fileDirectory.ModelTiepoint) {
      return [];
    }

    var tiePoints = [];
    for (var i = 0; i < this.fileDirectory.ModelTiepoint.length; i += 6) {
      tiePoints.push({
        i: this.fileDirectory.ModelTiepoint[i],
        j: this.fileDirectory.ModelTiepoint[i+1],
        k: this.fileDirectory.ModelTiepoint[i+2],
        x: this.fileDirectory.ModelTiepoint[i+3],
        y: this.fileDirectory.ModelTiepoint[i+4],
        z: this.fileDirectory.ModelTiepoint[i+5]
      });
    }
    return tiePoints;
  }
};

module.exports = GeoTIFFImage;<commit_msg>Preliminary implementation of async reading of rasters.<commit_after>
var globals = require("./globals.js"),
  fieldTags = globals.fieldTags,
  fieldTagNames = globals.fieldTagNames,
  arrayFields = globals.arrayFields,
  fieldTypes = globals.fieldTypes,
  fieldTypeNames = globals.fieldTypeNames;

var sum = function(array, start, end) {
  var s = 0;
  for (var i = start; i < end; ++i) {
    s += array[i];
  }
  return s;
};

/**
 * GeoTIFF sub-file image.
 * @constructor
 * @param {Object} fileDirectory The parsed file directory
 * @param {Object} geoKeys The parsed geo-keys
 * @param {DataView} dataView The DataView for the underlying file.
 * @param {Boolean} littleEndian Whether the file is encoded in little or big endian
 */

var GeoTIFFImage = function(fileDirectory, geoKeys, dataView, littleEndian) {
  this.fileDirectory = fileDirectory;
  this.geoKeys = geoKeys;
  this.dataView = dataView;
  this.littleEndian = littleEndian;
  this.tiles = {};
  this.isTiled = (fileDirectory.StripOffsets) ? false : true;
  var planarConfiguration = fileDirectory.PlanarConfiguration;
  this.planarConfiguration = (typeof planarConfiguration === "undefined") ? 1 : planarConfiguration;
  if (this.planarConfiguration !== 1 && this.planarConfiguration !== 2) {
    throw new Error("Invalid planar configuration.");
  }
};

GeoTIFFImage.prototype = {
  /**
   * Returns the associated parsed file directory.
   * @returns {Object} the parsed file directory
   */
  getFileDirectory: function() {
    return this.fileDirectory;
  },
  /**
   * Returns the associated parsed geo keys.
   * @returns {Object} the parsed geo keys
   */
  getGeoKeys: function() {
    return this.geoKeys;
  },
  /**
   * Returns the width of the image.
   * @returns {Number} the width of the image
   */
  getWidth: function() {
    return this.fileDirectory.ImageWidth;
  },
  /**
   * Returns the height of the image.
   * @returns {Number} the height of the image
   */
  getHeight: function() {
    return this.fileDirectory.ImageLength;
  },
  /**
   * Returns the number of samples per pixel.
   * @returns {Number} the number of samples per pixel
   */
  getSamplesPerPixel: function() {
    return this.fileDirectory.SamplesPerPixel;
  },
  /**
   * Returns the width of each tile.
   * @returns {Number} the width of each tile
   */
  getTileWidth: function() {
    return this.isTiled ? this.fileDirectory.TileWidth : this.getWidth();
  },
  /**
   * Returns the height of each tile.
   * @returns {Number} the height of each tile
   */
  getTileHeight: function() {
    return this.isTiled ? this.fileDirectory.TileLength : this.fileDirectory.RowsPerStrip;
  },

  getBytesPerPixel: function() {
    var bitsPerSample = 0;
    for (var i = 0; i < this.fileDirectory.BitsPerSample.length; ++i) {
      var bits = this.fileDirectory.BitsPerSample[i];
      if ((bits % 8) !== 0) {
        throw new Error("Sample bit-width of " + bits + " is not supported.");
      }
      else if (bits !== this.fileDirectory.BitsPerSample[0]) {
        throw new Error("Differing size of samples in a pixel are not supported.");
      }
      bitsPerSample += bits;
    }
    return bitsPerSample / 8;
  },

  getSampleByteSize: function(i) {
    if (i >= this.fileDirectory.BitsPerSample.length) {
      throw new RangeError("Sample index " + i + " is out of range.");
    }
    var bits = this.fileDirectory.BitsPerSample[i];
    if ((bits % 8) !== 0) {
      throw new Error("Sample bit-width of " + bits + " is not supported.");
    }
    return (bits / 8);
  },

  getReaderForSample: function(sampleIndex) {
    var format = this.fileDirectory.SampleFormat[sampleIndex];
    var bitsPerSample = this.fileDirectory.BitsPerSample[sampleIndex];
    switch (format) {
      case 1: // unsigned integer data
        switch (bitsPerSample) {
          case 8:
            return DataView.prototype.getUint8;
          case 16:
            return DataView.prototype.getUint16;
          case 32:
            return DataView.prototype.getUint32;
        }
        break;
      case 2: // twos complement signed integer data
        switch (bitsPerSample) {
          case 8:
            return DataView.prototype.getInt8;
          case 16:
            return DataView.prototype.getInt16;
          case 32:
            return DataView.prototype.getInt32;
        }
        break;
      case 3:
        switch (bitsPerSample) {
          case 32:
            return DataView.prototype.getFloat32;
          case 64:
            return DataView.prototype.getFloat64;
        }
        break;
    }
  },

  getArrayForSample: function(sampleIndex, size) {
    var format = this.fileDirectory.SampleFormat[sampleIndex];
    var bitsPerSample = this.fileDirectory.BitsPerSample[sampleIndex];
    switch (format) {
      case 1: // unsigned integer data
        switch (bitsPerSample) {
          case 8:
            return new Uint8Array(size);
          case 16:
            return new Uint16Array(size);
          case 32:
            return new Uint32Array(size);
        }
        break;
      case 2: // twos complement signed integer data
        switch (bitsPerSample) {
          case 8:
            return new Int8Array(size);
          case 16:
            return new Int16Array(size);
          case 32:
            return new Int32Array(size);
        }
        break;
      case 3: // floating point data
        switch (bitsPerSample) {
          case 32:
            return new Float32Array(size);
          case 64:
            return new Float64Array(size);
        }
        break;
    }
    throw Error("Unsupported data format/bitsPerSample");
  },

  decodeBlock: function(offset, byteCount) {
    var slice = this.dataView.buffer.slice(offset, offset + byteCount);
    switch (this.fileDirectory.Compression) {
      case 1:  // no compression
        return new Promise(function(resolve, reject) {
          resolve(slice);
        });
      case 5: // LZW
        var lzw = require("./lzw.js");
        return lzw.decode(slice);
        //throw new Error("LZW compression not supported.");
      case 6: // JPEG
        throw new Error("JPEG compression not supported.");
      case 8: // Deflate
        var deflate = require("./deflate.js");
        return deflate.decode(slice);
        //throw new Error("Deflate compression not supported.");
      //case 32946: // deflate ??
      //  throw new Error("Deflate compression not supported.");
      case 32773: // packbits
        throw new Error("PackBits compression not supported.");
      default:
        throw new Error("Unknown compresseion method identifier: " + this.fileDirectory.Compression);
    }
  },

  /**
   * Returns the decoded strip or tile.
   * @param {Number} x the strip or tile x-offset
   * @param {Number} y the tile y-offset (0 for stripped images)
   * @param {Number} plane the planar configuration (1: "chunky", 2: "separate samples")
   * @returns {(Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array)}
   */
  requestTileOrStrip: function(x, y, sample) {
    var numTilesPerRow = Math.ceil(this.getWidth() / this.getTileWidth());
    var numTilesPerCol = Math.ceil(this.getHeight() / this.getTileHeight());
    var index;
    var tiles = this.tiles;
    if (this.planarConfiguration === 1) {
      index = y * numTilesPerRow + x;
    }
    else if (this.planarConfiguration === 2) {
      index = sample * numTilesPerRow * numTilesPerCol + y * numTilesPerRow + x;
    }

    if (index in this.tiles && false) {
        return Promise.resolve({
          x: x, y: y, sample: sample, data: tiles[index]
        });
      }
      else {
        var offset, byteCount;
        if (this.isTiled) {
          offset = this.fileDirectory.TileOffsets[index];
          byteCount = this.fileDirectory.TileByteCounts[index];
        }
        else {
          offset = this.fileDirectory.StripOffsets[index];
          byteCount = this.fileDirectory.StripByteCounts[index];
        }

        return this.decodeBlock(offset, byteCount).then(function(data) {
          tiles[index] = data;
          return {
            x: x, y: y, sample: sample, data: tiles[index]
          };
        });
      }
  },

  _readRaster: function(imageWindow, samples, valueArrays) {
    var tileWidth = this.getTileWidth();
    var tileHeight = this.getTileHeight();

    var minXTile = Math.floor(imageWindow[0] / tileWidth);
    var maxXTile = Math.ceil(imageWindow[2] / tileWidth);
    var minYTile = Math.floor(imageWindow[1] / tileHeight);
    var maxYTile = Math.ceil(imageWindow[3] / tileHeight);

    var numTilesPerRow = Math.ceil(this.getWidth() / tileWidth);

    var windowWidth = imageWindow[2] - imageWindow[0];
    var windowHeight = imageWindow[3] - imageWindow[1];

    var bytesPerPixel = this.getBytesPerPixel();
    var imageWidth = this.getWidth();

    var srcSampleOffsets = [];
    var sampleReaders = [];
    for (var i = 0; i < samples.length; ++i) {
      if (this.planarConfiguration === 1) {
        srcSampleOffsets.push(sum(this.fileDirectory.BitsPerSample, 0, samples[i]) / 8);
      }
      else {
        srcSampleOffsets.push(0);
      }
      sampleReaders.push(this.getReaderForSample(samples[i]));
    }

    var promises = [];
    for (var yTile = minYTile; yTile <= maxYTile; ++yTile) {
      for (var xTile = minXTile; xTile <= maxXTile; ++xTile) {
        for (var sampleIndex = 0; sampleIndex < samples.length; ++sampleIndex) {
          var sample = samples[sampleIndex];
          if (this.planarConfiguration === 2) {
            bytesPerPixel = this.getSampleByteSize(sample);
          }

          var littleEndian = this.littleEndian;
          var _sampleIndex = sampleIndex;
          var promise = this.requestTileOrStrip(xTile, yTile, sample).then(function(tile) {
            var dataView = new DataView(tile.data);

            var firstLine = tile.y * tileHeight;
            var firstCol = tile.x * tileWidth;
            var lastLine = (tile.y + 1) * tileHeight;
            var lastCol = (tile.x + 1) * tileWidth;

            for (var y = Math.max(0, imageWindow[1] - firstLine); y < Math.min(tileHeight, tileHeight - (lastLine - imageWindow[3])); ++y) {
              for (var x = Math.max(0, imageWindow[0] - firstCol); x < Math.min(tileWidth, tileWidth - (lastCol - imageWindow[2])); ++x) {
                var pixelOffset = (y * tileWidth + x) * bytesPerPixel;
                var windowCoordinate = (
                  y + firstLine - imageWindow[1]
                ) * windowWidth + x + firstCol - imageWindow[0];
                valueArrays[_sampleIndex][windowCoordinate] = sampleReaders[_sampleIndex].call(dataView, pixelOffset + srcSampleOffsets[_sampleIndex], littleEndian);
              }
            }
          });
          promises.push(promise);
        }
      }
    }
    return Promise.all(promises).then(function() {
      return valueArrays;
    });
  },

  /**
   * Reads raster data from the image. This function reads all selected samples
   * into separate arrays of the correct type for that sample. When provided,
   * only a subset of the raster is read for each sample.
   *
   * @param {Array} [imageWindow=whole image] the subset to read data from.
   * @param {Array} [samples=all samples]
   * @returns {TypedArray[]} the requested data as a summary array, one TypedArray for each requested sample
   */
  readRasters: function(imageWindow, samples) {
    imageWindow = imageWindow || [0, 0, this.getWidth(), this.getHeight()];

    if (imageWindow[0] < 0 ||
        imageWindow[1] < 0 ||
        imageWindow[2] > this.getWidth() ||
        imageWindow[3] > this.getHeight()) {
      throw new Error("Select window is out of image bounds.");
    }
    else if (imageWindow[0] > imageWindow[2] || imageWindow[1] > imageWindow[3]) {
      throw new Error("Invalid subsets");
    }

    var imageWindowWidth = imageWindow[2] - imageWindow[0];
    var imageWindowHeight = imageWindow[3] - imageWindow[1];
    var numPixels = imageWindowWidth * imageWindowHeight;
    var i;

    if (!samples) {
      samples = [];
      for (i=0; i < this.fileDirectory.SamplesPerPixel; ++i) {
        samples.push(i);
      }
    }
    else {
      for (i = 0; i < samples.length; ++i) {
        if (samples[i] >= this.fileDirectory.SamplesPerPixel) {
          throw new RangeError("Invalid sample index '" + samples[i] + "'.");
        }
      }
    }
    var valueArrays = [];
    for (i = 0; i < samples.length; ++i) {
      valueArrays.push(this.getArrayForSample(samples[i], numPixels));
    }

    return this._readRaster(imageWindow, samples, valueArrays);
  },

  /**
   * Returns an array of tiepoints.
   * @returns {Object[]}
   */
  getTiePoints: function() {
    if (!this.fileDirectory.ModelTiepoint) {
      return [];
    }

    var tiePoints = [];
    for (var i = 0; i < this.fileDirectory.ModelTiepoint.length; i += 6) {
      tiePoints.push({
        i: this.fileDirectory.ModelTiepoint[i],
        j: this.fileDirectory.ModelTiepoint[i+1],
        k: this.fileDirectory.ModelTiepoint[i+2],
        x: this.fileDirectory.ModelTiepoint[i+3],
        y: this.fileDirectory.ModelTiepoint[i+4],
        z: this.fileDirectory.ModelTiepoint[i+5]
      });
    }
    return tiePoints;
  }
};

module.exports = GeoTIFFImage;<|endoftext|>


<commit_before>define(['js/core/Component', 'srv/core/HttpError', 'flow', 'require', 'JSON', 'js/data/Collection', 'js/data/DataSource', 'js/data/Model', 'underscore'], function (Component, HttpError, flow, require, JSON, Collection, DataSource, Model, _) {

    return Component.inherit('srv.handler.rest.ResourceHandler', {
        defaults: {
            autoStartSession: true
        },

        $collectionMethodMap: {
            GET: "_index",
            POST: "_create"
        },

        $modelMethodMap: {
            GET: "_show",
            PUT: "_update",
            DELETE: "_delete"
        },

        init: function (restHandler, configuration, resourceId, parentResource) {
            this.$restHandler = restHandler;
            this.$resourceId = resourceId;

            this.$resourceConfiguration = configuration;
            this.$parentResource = parentResource;
        },

        _isCollectionResource: function () {
            return !this.$resourceId;
        },

        getResourceHandlerInstance: function() {
            return this;
        },

        getDataSource: function (context, childResource) {
            if (this.$parentResource) {
                return this.$parentResource.getDataSource(context, this);
            } else {
                return this.$restHandler.getDataSource(context, this);
            }
        },

        handleRequest: function (context, callback) {

            var method = this._getRequestMethod(context),
                map = this._isCollectionResource() ? this.$collectionMethodMap : this.$modelMethodMap;

            var fn = this[map[method]];

            if (fn instanceof Function) {
                context.dataSource = this.getDataSource(context);
                var body = context.request.body.content;

                if (body !== "") {
                    // TODO: handle different payload formats -> format processor needed
                    try {
                        context.request.params = JSON.parse(body);
                    } catch (e) {
                        console.warn("Couldn't parse " + body);
                    }
                }
                // TODO: better apply json post value here to the function
                fn.call(this, context, callback);

            } else {
                throw new HttpError("Method not supported", 404);
            }
        },

        _findCollection: function (context) {
            if (this.$parentResource) {
                // TODO: refactor this
                var parentFactory = this.$parentResource._getModelFactory();
                var parent = context.dataSource.createEntity(parentFactory, this.$parentResource.$resourceId);

                return parent.getCollection(this.$resourceConfiguration.$.path);
            } else {
                return context.dataSource.createCollection(Collection.of(this._getModelFactory()));
            }
        },

        /***
         * determinate the request method from the request
         *
         * @param {srv.core.Context} context
         * @return {String} method
         * @private
         */
        _getRequestMethod: function (context) {

            var parameter = context.request.urlInfo.parameter;
            if (parameter.method) {
                return parameter.method.toUpperCase();
            }

            return context.request.method;
        },

        _getModelFactory: function () {
            return require(this.$resourceConfiguration.$.modelClassName.replace(/\./g, '/'));
        },

        /***
         *
         * @param context
         * @param callback
         * @private
         */
        _index: function (context, callback) {
            var collection = this._findCollection(context);

            var parameters = context.request.urlInfo.parameter;
            var options = {};
            if (parameters["limit"]) {
                options["limit"] = parseInt(parameters["limit"]);
            }
            if(parameters["sort"]) {
                options["sort"] = JSON.parse(parameters["sort"]);
            }
            var self = this;
            // TODO: read out offset, limit and query from query string
            collection.fetch(options, function (err, collection) {
                if (!err) {
                    var response = context.response;
                    var body = "", results = [];

                    // switch context of collection to restdatasource

                    // call compose
                    var processor = self.$restHandler.$restDataSource.getProcessorForCollection(collection);

                    results = processor.composeCollection(collection, null, options);

                    var res = {
                        count: collection.$itemsCount,
                        limit: options["limit"],
                        offset: 0,
                        results: results
                    };

                    body = JSON.stringify(res);

                    response.writeHead(200, "", {
                        'Content-Type': 'application/json; charset=utf-8'
                    });

                    response.write(body, 'utf8');
                    response.end();
                }

                callback(err);
            });
        },

        /***
         *
         * @param context
         * @param callback
         * @private
         */
        _create: function (context, callback) {
            var collection = this._findCollection(context);
            var model = collection.createItem();

            var payload = context.request.params;

            var processor = this.$restHandler.$restDataSource.getProcessorForModel(model);

            model.set(processor.parse(model, payload));

            model.set('created', new Date());

            var self = this;

            flow()
                .seq(function (cb){
                    self._beforeSave(model, context, cb);
                })
                .seq(function (cb) {
                    // TODO: add sub models
                    model.validateAndSave({}, function (err, model) {
                        if (!err) {
                            // TODO: do correct invalidation
                            collection.invalidatePageCache();

                            var body = JSON.stringify(processor.compose(model, null));

                            var response = context.response;
                            response.writeHead(201, "", {
                                'Content-Type': 'application/json',
                                'Location': context.request.urlInfo.uri + "/" + model.$.id
                            });

                            response.write(body);
                            response.end();

                            cb(null);
                        } else {
                            cb(new HttpError(err, 500));
                        }
                    });
                }).exec(callback);
        },

        /***
         *
         * @param context
         * @param callback
         * @private
         */
        _show: function (context, callback) {
            var modelFactory = this._getModelFactory();
            var model = context.dataSource.createEntity(modelFactory, this.$resourceId);
            var self = this;

            // TODO: add fields/include option handling
            model.fetch({}, function (err, model) {
                if (!err) {
                    var processor = self.$restHandler.$restDataSource.getProcessorForModel(model);

                    var body = JSON.stringify(processor.compose(model, null)),
                        response = context.response;

                    response.writeHead(200, "", {
                        'Content-Length': body.length,
                        'Content-Type': 'application/json'
                    });

                    response.write(body);
                    response.end();
                    callback(null);
                } else {
                    var statusCode = 500;
                    if(err === DataSource.ERROR.NOT_FOUND){
                        statusCode = 404;
                    }
                    callback(new HttpError(err, statusCode));
                }
            });
        },

        /***
         *
         * @param context
         * @param callback
         * @private
         */
        _update: function (context, callback) {
            var collection = this._findCollection(context);
            var model = collection.createItem(this.$resourceId);

            var payload = context.request.params;

            var processor = this.$restHandler.$restDataSource.getProcessorForModel(model);

            model.set(processor.parse(model, payload));

            var self = this;
            // TODO: add hook to add session data like user id
            flow()
                .seq(function (cb) {
                    self._beforeSave(model, context, cb);
                })
                .seq(function(cb){
                    model.validateAndSave({}, function (err) {
                        if (!err) {
                            // TODO: do correct invalidation
                            collection.invalidatePageCache();

                            // TODO: generate the location header
                            var body = JSON.stringify(processor.compose(model, null));

                            var response = context.response;
                            response.writeHead(200, "", {
                                'Content-Type': 'application/json'
                                // TODO : add updated date in head ???
                            });

                            response.write(body);
                            response.end();

                            cb(null);
                        } else {
                            var statusCode = 500;
                            if (err === DataSource.ERROR.NOT_FOUND) {
                                statusCode = 404;
                            }
                            cb(new HttpError(err, statusCode));
                        }
                    });
                }).exec(callback);

        },

        _autoGenerateValue: function(valueKey, context, model) {
            if(valueKey === Model.AUTO_GENERATE.CREATION_DATE){
                if(model.isNew()){
                    return new Date();
                }
            }

            if(valueKey === Model.AUTO_GENERATE.UPDATED_DATE){
                return new Date();
            }

            if(valueKey === "SESSION_USER"){
                // TODO: return session user
                return null;
            }
        },

        /**
         *
         * @param model
         * @param options
         * @param callback
         * @private
         */
        _beforeSave: function(model, context, callback) {
            var schema = model.schema, schemaObject;
            for(var schemaKey in schema){
                if(schema.hasOwnProperty(schemaKey)){
                    schemaObject = schema[schemaKey];
                    if(schemaObject.generated){
                        var value = this._autoGenerateValue(schemaObject.key, context, model);
                        if(!_.isUndefined(value)){
                            model.set(schemaKey, value);
                        }
                    }
                }
            }

            callback && callback();
        },

        _afterSave: function(model, options, callback){
            callback && callback();
        },
        /***
         *
         * @param context
         * @param callback
         * @private
         */
        _delete: function (context, callback) {
            var collection = this._findCollection(context);
            var model = collection.createItem(this.$resourceId);

            model.remove({}, function (err) {
                if (!err) {
                    // TODO: do correct invalidation
                    collection.invalidatePageCache();
                    // TODO: generate the location header
                    var body = "";

                    var response = context.response;
                    response.writeHead(200, "", {
                        'Content-Type': 'application/json'
                    });

                    response.write(body);
                    response.end();

                    callback(null);
                } else {
                    var statusCode = 500;
                    if (err === DataSource.ERROR.NOT_FOUND) {
                        statusCode = 404;
                    }
                    callback(new HttpError(err, statusCode));
                }
            });
        }

    });
});<commit_msg>added handling of where parameter<commit_after>define(['js/core/Component', 'srv/core/HttpError', 'flow', 'require', 'JSON', 'js/data/Collection', 'js/data/DataSource', 'js/data/Model', 'underscore'], function (Component, HttpError, flow, require, JSON, Collection, DataSource, Model, _) {

    return Component.inherit('srv.handler.rest.ResourceHandler', {
        defaults: {
            autoStartSession: true
        },

        $collectionMethodMap: {
            GET: "_index",
            POST: "_create"
        },

        $modelMethodMap: {
            GET: "_show",
            PUT: "_update",
            DELETE: "_delete"
        },

        init: function (restHandler, configuration, resourceId, parentResource) {
            this.$restHandler = restHandler;
            this.$resourceId = resourceId;

            this.$resourceConfiguration = configuration;
            this.$parentResource = parentResource;
        },

        _isCollectionResource: function () {
            return !this.$resourceId;
        },

        getResourceHandlerInstance: function() {
            return this;
        },

        getDataSource: function (context, childResource) {
            if (this.$parentResource) {
                return this.$parentResource.getDataSource(context, this);
            } else {
                return this.$restHandler.getDataSource(context, this);
            }
        },

        handleRequest: function (context, callback) {

            var method = this._getRequestMethod(context),
                map = this._isCollectionResource() ? this.$collectionMethodMap : this.$modelMethodMap;

            var fn = this[map[method]];

            if (fn instanceof Function) {
                context.dataSource = this.getDataSource(context);
                var body = context.request.body.content;

                if (body !== "") {
                    // TODO: handle different payload formats -> format processor needed
                    try {
                        context.request.params = JSON.parse(body);
                    } catch (e) {
                        console.warn("Couldn't parse " + body);
                    }
                }
                // TODO: better apply json post value here to the function
                fn.call(this, context, callback);

            } else {
                throw new HttpError("Method not supported", 404);
            }
        },

        _findCollection: function (context) {
            if (this.$parentResource) {
                // TODO: refactor this
                var parentFactory = this.$parentResource._getModelFactory();
                var parent = context.dataSource.createEntity(parentFactory, this.$parentResource.$resourceId);

                return parent.getCollection(this.$resourceConfiguration.$.path);
            } else {
                return context.dataSource.createCollection(Collection.of(this._getModelFactory()));
            }
        },

        /***
         * determinate the request method from the request
         *
         * @param {srv.core.Context} context
         * @return {String} method
         * @private
         */
        _getRequestMethod: function (context) {

            var parameter = context.request.urlInfo.parameter;
            if (parameter.method) {
                return parameter.method.toUpperCase();
            }

            return context.request.method;
        },

        _getModelFactory: function () {
            return require(this.$resourceConfiguration.$.modelClassName.replace(/\./g, '/'));
        },

        /***
         *
         * @param context
         * @param callback
         * @private
         */
        _index: function (context, callback) {
            var collection = this._findCollection(context);

            var parameters = context.request.urlInfo.parameter;
            var options = {};
            if (parameters["limit"]) {
                options["limit"] = parseInt(parameters["limit"]);
            }
            if(parameters["sort"]) {
                options["sort"] = JSON.parse(parameters["sort"]);
            }
            if(parameters["where"]){
                options["where"] = JSON.parse(parameters["where"]);
            }

            var self = this;
            // TODO: read out offset, limit and query from query string
            collection.fetch(options, function (err, collection) {
                if (!err) {
                    var response = context.response;
                    var body = "", results = [];

                    // switch context of collection to restdatasource

                    // call compose
                    var processor = self.$restHandler.$restDataSource.getProcessorForCollection(collection);

                    results = processor.composeCollection(collection, null, options);

                    var res = {
                        count: collection.$itemsCount,
                        limit: options["limit"],
                        offset: 0,
                        results: results
                    };

                    body = JSON.stringify(res);

                    response.writeHead(200, "", {
                        'Content-Type': 'application/json; charset=utf-8'
                    });

                    response.write(body, 'utf8');
                    response.end();
                }

                callback(err);
            });
        },

        /***
         *
         * @param context
         * @param callback
         * @private
         */
        _create: function (context, callback) {
            var collection = this._findCollection(context);
            var model = collection.createItem();

            var payload = context.request.params;

            var processor = this.$restHandler.$restDataSource.getProcessorForModel(model);

            model.set(processor.parse(model, payload));

            model.set('created', new Date());

            var self = this;

            flow()
                .seq(function (cb){
                    self._beforeSave(model, context, cb);
                })
                .seq(function (cb) {
                    // TODO: add sub models
                    model.validateAndSave({}, function (err, model) {
                        if (!err) {
                            // TODO: do correct invalidation
                            collection.invalidatePageCache();

                            var body = JSON.stringify(processor.compose(model, null));

                            var response = context.response;
                            response.writeHead(201, "", {
                                'Content-Type': 'application/json',
                                'Location': context.request.urlInfo.uri + "/" + model.$.id
                            });

                            response.write(body);
                            response.end();

                            cb(null);
                        } else {
                            cb(new HttpError(err, 500));
                        }
                    });
                }).exec(callback);
        },

        /***
         *
         * @param context
         * @param callback
         * @private
         */
        _show: function (context, callback) {
            var modelFactory = this._getModelFactory();
            var model = context.dataSource.createEntity(modelFactory, this.$resourceId);
            var self = this;

            // TODO: add fields/include option handling
            model.fetch({}, function (err, model) {
                if (!err) {
                    var processor = self.$restHandler.$restDataSource.getProcessorForModel(model);

                    var body = JSON.stringify(processor.compose(model, null)),
                        response = context.response;

                    response.writeHead(200, "", {
                        'Content-Length': body.length,
                        'Content-Type': 'application/json'
                    });

                    response.write(body);
                    response.end();
                    callback(null);
                } else {
                    var statusCode = 500;
                    if(err === DataSource.ERROR.NOT_FOUND){
                        statusCode = 404;
                    }
                    callback(new HttpError(err, statusCode));
                }
            });
        },

        /***
         *
         * @param context
         * @param callback
         * @private
         */
        _update: function (context, callback) {
            var collection = this._findCollection(context);
            var model = collection.createItem(this.$resourceId);

            var payload = context.request.params;

            var processor = this.$restHandler.$restDataSource.getProcessorForModel(model);

            model.set(processor.parse(model, payload));

            var self = this;
            // TODO: add hook to add session data like user id
            flow()
                .seq(function (cb) {
                    self._beforeSave(model, context, cb);
                })
                .seq(function(cb){
                    model.validateAndSave({}, function (err) {
                        if (!err) {
                            // TODO: do correct invalidation
                            collection.invalidatePageCache();

                            // TODO: generate the location header
                            var body = JSON.stringify(processor.compose(model, null));

                            var response = context.response;
                            response.writeHead(200, "", {
                                'Content-Type': 'application/json'
                                // TODO : add updated date in head ???
                            });

                            response.write(body);
                            response.end();

                            cb(null);
                        } else {
                            var statusCode = 500;
                            if (err === DataSource.ERROR.NOT_FOUND) {
                                statusCode = 404;
                            }
                            cb(new HttpError(err, statusCode));
                        }
                    });
                }).exec(callback);

        },

        _autoGenerateValue: function(valueKey, context, model) {
            if(valueKey === Model.AUTO_GENERATE.CREATION_DATE){
                if(model.isNew()){
                    return new Date();
                }
            }

            if(valueKey === Model.AUTO_GENERATE.UPDATED_DATE){
                return new Date();
            }

            if(valueKey === "SESSION_USER"){
                // TODO: return session user
                return null;
            }
        },

        /**
         *
         * @param model
         * @param options
         * @param callback
         * @private
         */
        _beforeSave: function(model, context, callback) {
            var schema = model.schema, schemaObject;
            for(var schemaKey in schema){
                if(schema.hasOwnProperty(schemaKey)){
                    schemaObject = schema[schemaKey];
                    if(schemaObject.generated){
                        var value = this._autoGenerateValue(schemaObject.key, context, model);
                        if(!_.isUndefined(value)){
                            model.set(schemaKey, value);
                        }
                    }
                }
            }

            callback && callback();
        },

        _afterSave: function(model, options, callback){
            callback && callback();
        },
        /***
         *
         * @param context
         * @param callback
         * @private
         */
        _delete: function (context, callback) {
            var collection = this._findCollection(context);
            var model = collection.createItem(this.$resourceId);

            model.remove({}, function (err) {
                if (!err) {
                    // TODO: do correct invalidation
                    collection.invalidatePageCache();
                    // TODO: generate the location header
                    var body = "";

                    var response = context.response;
                    response.writeHead(200, "", {
                        'Content-Type': 'application/json'
                    });

                    response.write(body);
                    response.end();

                    callback(null);
                } else {
                    var statusCode = 500;
                    if (err === DataSource.ERROR.NOT_FOUND) {
                        statusCode = 404;
                    }
                    callback(new HttpError(err, statusCode));
                }
            });
        }

    });
});<|endoftext|>


<commit_before>/* Opt-in, convenience construct used to update a global stream imperatively and in a type safe fashion */

import most from 'most';
import defaultLog from './log';

/*
 * A stream piloted by type-safe messages. Meant to be a global (application wide), never ending stream.
 */
export function GlobalStream(initialState, registerHandlers, log) {
  if (log === undefined) log = defaultLog.stream;

  const handlers = {};
  let dispatching = false;

  const on = (msg, fn) => { handlers[msg._id] = fn }
  registerHandlers(on);

  if (log)
    console.log('%cInitial state:', 'color: green', initialState);

  const stream = most.create((add, end, error) => {
    stream.emit = function(message) {
      const { _id, _name, payload } = message;

      // TODO: Is it even useful to prevent redispatching since we have async redraws? We could push to a temp queue.
      // The scenario would be: in the middle of a msg handling, we want to conditionally dispatch another msg.
      if (dispatching) throw new Error(
        'Cannot dispatch a Msg in the middle of another msg\'s dispatch');

      const handler = handlers[_id];
      if (!handler) {
        throw new Error('globalStream.emit: Unknown message: ', _name);
        return;
      }

      dispatching = true;

      let newState;

      try {
        newState = handler(stream.value, payload);
      }
      finally {
        if (log)
          console.log(`%cNew PushStream state:`, 'color: blue', newState);

        dispatching = false;
      }

      if (newState !== stream.value) {
        stream.value = newState;
        add(newState);
      }
    }
  })

  stream.value = initialState;
  stream.drain();

  return stream;
}
<commit_msg>Fix log typo<commit_after>/* Opt-in, convenience construct used to update a global stream imperatively and in a type safe fashion */

import most from 'most';
import defaultLog from './log';

/*
 * A stream piloted by type-safe messages. Meant to be a global (application wide), never ending stream.
 */
export function GlobalStream(initialState, registerHandlers, log) {
  if (log === undefined) log = defaultLog.stream;

  const handlers = {};
  let dispatching = false;

  const on = (msg, fn) => { handlers[msg._id] = fn }
  registerHandlers(on);

  if (log)
    console.log('%cInitial state:', 'color: green', initialState);

  const stream = most.create((add, end, error) => {
    stream.emit = function(message) {
      const { _id, _name, payload } = message;

      // TODO: Is it even useful to prevent redispatching since we have async redraws? We could push to a temp queue.
      // The scenario would be: in the middle of a msg handling, we want to conditionally dispatch another msg.
      if (dispatching) throw new Error(
        'Cannot dispatch a Msg in the middle of another msg\'s dispatch');

      const handler = handlers[_id];
      if (!handler) {
        throw new Error('globalStream.emit: Unknown message: ', _name);
        return;
      }

      dispatching = true;

      let newState;

      try {
        newState = handler(stream.value, payload);
      }
      finally {
        if (log)
          console.log(`%cNew GlobalStream state:`, 'color: blue', newState);

        dispatching = false;
      }

      if (newState !== stream.value) {
        stream.value = newState;
        add(newState);
      }
    }
  })

  stream.value = initialState;
  stream.drain();

  return stream;
}
<|endoftext|>


<commit_before>E2.p = E2.plugins["convert_color_hsla_modulator"] = function(core, node)
{
	this.desc = 'Create an RGBA color from hue, saturation and luminosity and alpha.';

	this.input_slots = [
		{ name: 'color', dt: core.datatypes.COLOR, desc: 'The corresponding RGBA color.', def: 'Black' }
	];

	this.output_slots = [
		{ name: 'hue', dt: core.datatypes.FLOAT, desc: 'The hue of the input color.', lo: 0, hi: 1, def: 0 },
		{ name: 'saturation', dt: core.datatypes.FLOAT, desc: 'The saturation (color intensity) of the input color.', lo: 0, hi: 1, def: 0 },
		{ name: 'luminosity', dt: core.datatypes.FLOAT, desc: 'The luminosity (brightness) of the input color.', lo: 0, hi: 1, def: 0 },
		{ name: 'alpha', dt: core.datatypes.FLOAT, desc: 'The alpha of the input color.', lo: 0, hi: 1, def: 0 }
	];
};

E2.p.prototype.reset = function()
{
	this.hsla = [0.0, 0.0, 0.0, 1.0];
	this.color = new Color(0.0, 0.0, 0.0, 1.0);
};

E2.p.prototype.update_input = function(slot, data)
{
	this.color = data;
};

E2.p.prototype.update_state = function(delta_t)
{
	var color = this.color.rgba;

	this.hsla[0] = this.hsla[1] = this.hsla[2] = 0.0;
	this.hsla[3] = color[3];

	var hi = Math.max(Math.max(color[0], color[1]), color[2]);
	var lo = Math.min(Math.min(color[0], color[1]), color[2]);

	var l = (lo + hi) * 0.5;

	if(l <= 0.0)
		return;

	var diff = hi - lo;
	var s = diff;

	if(s > 0.0)
		s /= (l <= 0.5) ? (lo + hi) : (2.0 - hi - lo);
	else
		return;

	var r = (hi - color[0]) / diff;
	var g = (hi - color[1]) / diff;
	var b = (hi - color[2]) / diff;
	var h = 0.0;

	if(color[0] == hi)
		h = (color[1] == lo ? 5.0 + b : 1.0 - g);
	else if(color[1] == hi)
		h = (color[2] == lo ? 1.0 + r : 3.0 - b);
	else
		h = (color[0] == lo ? 3.0 + g : 5.0 - r);

	this.hsla[0] = h / 6.0;
	this.hsla[1] = s;
	this.hsla[2] = l;
};

E2.p.prototype.update_output = function(slot)
{
	return this.hsla[slot.index];
};
<commit_msg>Fixed bug in the color -> HSLA converter plugin that emitted luma as zero whenever saturation was zero.<commit_after>E2.p = E2.plugins["convert_color_hsla_modulator"] = function(core, node)
{
	this.desc = 'Create an RGBA color from hue, saturation and luminosity and alpha.';

	this.input_slots = [
		{ name: 'color', dt: core.datatypes.COLOR, desc: 'The corresponding RGBA color.', def: 'Black' }
	];

	this.output_slots = [
		{ name: 'hue', dt: core.datatypes.FLOAT, desc: 'The hue of the input color.', lo: 0, hi: 1, def: 0 },
		{ name: 'saturation', dt: core.datatypes.FLOAT, desc: 'The saturation (color intensity) of the input color.', lo: 0, hi: 1, def: 0 },
		{ name: 'luminosity', dt: core.datatypes.FLOAT, desc: 'The luminosity (brightness) of the input color.', lo: 0, hi: 1, def: 0 },
		{ name: 'alpha', dt: core.datatypes.FLOAT, desc: 'The alpha of the input color.', lo: 0, hi: 1, def: 0 }
	];
};

E2.p.prototype.reset = function()
{
	this.hsla = [0.0, 0.0, 0.0, 1.0];
	this.color = new Color(0.0, 0.0, 0.0, 1.0);
};

E2.p.prototype.update_input = function(slot, data)
{
	this.color = data;
};

E2.p.prototype.update_state = function(delta_t)
{
	var color = this.color.rgba;

	this.hsla[0] = this.hsla[1] = this.hsla[2] = 0.0;
	this.hsla[3] = color[3];

	var hi = Math.max(Math.max(color[0], color[1]), color[2]);
	var lo = Math.min(Math.min(color[0], color[1]), color[2]);

	var l = (lo + hi) * 0.5;

	if(l <= 0.0)
		return;

	var diff = hi - lo;
	var s = diff;

	this.hsla[2] = l;

	if(s > 0.0)
		s /= (l <= 0.5) ? (lo + hi) : (2.0 - hi - lo);
	else
		return;

	var r = (hi - color[0]) / diff;
	var g = (hi - color[1]) / diff;
	var b = (hi - color[2]) / diff;
	var h = 0.0;

	if(color[0] == hi)
		h = (color[1] == lo ? 5.0 + b : 1.0 - g);
	else if(color[1] == hi)
		h = (color[2] == lo ? 1.0 + r : 3.0 - b);
	else
		h = (color[0] == lo ? 3.0 + g : 5.0 - r);

	this.hsla[0] = h / 6.0;
	this.hsla[1] = s;
};

E2.p.prototype.update_output = function(slot)
{
	return this.hsla[slot.index];
};
<|endoftext|>


<commit_before>    function log() {
      document.body.appendChild(document.createTextNode(Array.prototype.join.call(arguments, ", ") + '\n'));
      console.log.apply(console, arguments);
    }

    window.onerror = function(err) {
      log("Error", err);
    };

    if (navigator.serviceWorker && navigator.serviceWorker.getRegistrations) {
          //启动的时候先反注册所有sw
          navigator.serviceWorker.getRegistrations().then(function(registrations) {
            for (var i = registrations.length - 1; i >= 0; i--) {
              registrations[i].unregister()
            }

          })
      } else {
        setTimeout(function(){log("该浏览器不支持service worker")}, 1000)

      }

    var KTestTime = 32;

    function sendRequest(url, endFunction, index, count) {
      var xhr = new XMLHttpRequest();
      xhr.onreadystatechange = function() {
          if (xhr.readyState == XMLHttpRequest.DONE) {

             if (++index < count) {

                sendRequest(url, endFunction, index, count)

             } else {

                endFunction(xhr)
             }

          }
      }
      xhr.open('GET', url + "&" + new Date().getTime(), true);
      xhr.send(null);

    }

    function startOriginalAjaxTest(){

      var start = new Date().getTime();

      var i = 0;

      sendRequest("jsonBig.json?", function(xhr){

          var end = new Date().getTime();
          log("耗时 ", end - start);

      }, i , KTestTime);

    }

    function startSWAjaxTest(){

      navigator.serviceWorker.register('sw.js', {
        scope: './'
      }).then(function(sw) {
        log("注册成功", sw);
      }).catch(function(err) {
        log("Error", err);
      });

      var start = new Date().getTime();

      var i = 0;

      sendRequest("jsonBig.json?fake", function(xhr){

          var end = new Date().getTime();
          log("SW注册后耗时 ", end - start);

      }, i , KTestTime);

    }

    function startSWAjaxCacheTest() {

            var start = new Date().getTime();

      var i = 0;

      sendRequest("jsonBig.json", function(xhr){

          var end = new Date().getTime();
          log("SW注册后缓存耗时 ", end - start);

      }, i , KTestTime);

    }<commit_msg>兼容log<commit_after>    function log(content) {
      document.body.appendChild(document.createTextNode(content + '\n'));
      console.log.apply(console, arguments);
    }

    window.onerror = function(err) {
      log("Error", err);
    };

    if (navigator.serviceWorker && navigator.serviceWorker.getRegistrations) {
          //启动的时候先反注册所有sw
          navigator.serviceWorker.getRegistrations().then(function(registrations) {
            for (var i = registrations.length - 1; i >= 0; i--) {
              registrations[i].unregister()
            }

          })
      } else {
        setTimeout(function(){log("该浏览器不支持service worker")}, 1000)

      }

    var KTestTime = 32;

    function sendRequest(url, endFunction, index, count) {
      var xhr = new XMLHttpRequest();
      xhr.onreadystatechange = function() {
          if (xhr.readyState == XMLHttpRequest.DONE) {

             if (++index < count) {

                sendRequest(url, endFunction, index, count)

             } else {

                endFunction(xhr)
             }

          }
      }
      xhr.open('GET', url + "&" + new Date().getTime(), true);
      xhr.send(null);

    }

    function startOriginalAjaxTest(){

      var start = new Date().getTime();

      var i = 0;

      sendRequest("jsonBig.json?", function(xhr){

          var end = new Date().getTime();
          log("耗时 ", end - start);

      }, i , KTestTime);

    }

    function startSWAjaxTest(){

      navigator.serviceWorker.register('sw.js', {
        scope: './'
      }).then(function(sw) {
        log("注册成功", sw);
      }).catch(function(err) {
        log("Error", err);
      });

      var start = new Date().getTime();

      var i = 0;

      sendRequest("jsonBig.json?fake", function(xhr){

          var end = new Date().getTime();
          log("SW注册后耗时 ", end - start);

      }, i , KTestTime);

    }

    function startSWAjaxCacheTest() {

            var start = new Date().getTime();

      var i = 0;

      sendRequest("jsonBig.json", function(xhr){

          var end = new Date().getTime();
          log("SW注册后缓存耗时 ", end - start);

      }, i , KTestTime);

    }<|endoftext|>


<commit_before>/*!
 * Dropin replacement for webix 'form' component that supports
 * html5 validation attributes if supported by the browser.
 *
 * Provided under MIT License (MIT)
 * Copyright (C) 2016 IDNT Europe GmbH (www.idnt.net)
 */

if (typeof webix === 'undefined')
    throw new Error('h5form requires webix');

webix.protoUI({
	name:'h5form',
	defaults: {
		autoLabelPositioning: true,
		autoBottomPadding: true,
		defaultLabelWidth: 130,
		defaultLabelPosition: 'left',
		autoheight:true,
	},
	$init:function(config) {
		var oldobj = this._viewobj;
		this._contentobj = this._viewobj = webix.html.create("FORM",{
				'class':'webix_view webix_form webix_custom_h5form',
				'action':'javascript:0;',
			});

		while(oldobj.childNodes.length > 0)
			this._viewobj.appendChild(oldobj.childNodes[0]);

		this.$view = this._viewobj;

		this.config = webix.extend(config, this.defaults, false);

		if (!this.$view.checkValidity)
			return; // We are done if we have no validation API

		var self = this;

		config.elementsConfig = config.elementsConfig || {};
		config.elementsConfig.on = config.elementsConfig.on || {};
		if (config.autoLabelPositioning) {
			config.elementsConfig.labelPosition = config.elementsConfig.labelPosition || config.defaultLabelPosition;
			config.elementsConfig.labelWidth = config.elementsConfig.labelWidth || config.defaultLabelWidth;
		}
		var savedOnChange = config.elementsConfig.on.onChange;
		config.elementsConfig.on.onChange = function(newV, oldV) {
			if (this.config.name) {
				self.$view.checkValidity()
				var node = this.getInputNode();
				if (node && typeof node.willValidate !== 'undefined' && node.validity && !node.validity.valid)
					self.markInvalid(this.config.name, node.validationMessage || 'Please check your input.');
			}

			if (typeof savedOnChange === 'function')
				savedOnChange.call(this, newVm, oldV);
		}

		config.rules = config.rules || {};
		var savedObjRule = config.rules.$obj;
		config.rules.$obj = function() {
			var valid = true;
			Object.keys(self.elements).forEach(function (fieldName) {
				var inputView = self.elements[fieldName];
				if (inputView) {
					var node = inputView.getInputNode();
					if (node && typeof node.willValidate !== 'undefined' && node.validity && !node.validity.valid) {
						self.markInvalid(fieldName, node.validationMessage || 'Please check your input.');
						valid = false;
					}
				}
			});
			return valid && (!savedObjRule !== 'function' || savedObjRule.call(this, arguments));
		}

		config.on = config.on || {};
		var savedHandler = config.on.onBeforeValidate;
		config.on.onBeforeValidate = function() {
			self.$view.checkValidity()
			if (savedHandler === 'function')
				savedHandler.call(this, arguments);
		}

		this.$view.onsubmit = function(e) {
			self.clearValidation();
			self.validate();
			e.preventDefault();
			return false;
		};
	},
	_initLabelPosition:function(adjust) {
		var pos = 'left';
		var width = this.getParentView().$width;
		if (width < 500)
			pos='top';

		var chpos = chbp = false;
		if (this.config.elementsConfig.labelPosition != pos) {
			this.config.elementsConfig.labelPosition = pos;
			chpos = true;
		}

		if (chpos || this.config.autoBottomPadding) {
			for (var n in this.elements) {
				var e = this.elements[n];
				if (this.config.autoLabelPositioning && chpos) {
					if (pos == 'top') {
						e.config.labelPosition = 'top';
						e._settings.labelPosition = 'top';
						e._settings._savedLabelWidth = e._settings.labelWidth;
						e._settings._savedHeight = e._settings.height;
						e.config.height += 20;
						if (adjust)
							e.render();
					}
					else if (pos == 'left') {
						e.config.labelPosition = 'left';
						e._settings.labelPosition = e.config.labelPosition;
						e.config.labelWidth = e._settings._savedLabelWidth;
						e._settings.labelWidth = e.config.labelWidth;
						e.config.height = e._settings._savedHeight;
					}
				}

				// Adjust the bottom label if present
				if (this.config.autoBottomPadding &&
					typeof e.config.bottomLabel !== 'undefined' &&
					e.config.bottomLabel.length) {
					var fWidth = e._input_width || (width - e.config.labelWidth);
					var lSize = webix.html.getTextSize(e.config.bottomLabel);
					var bp = Math.ceil(lSize.width / fWidth) * lSize.height;
					if (e.config.bottomPadding != bp) {
						e.config.bottomPadding = bp;
						chbp = true;
					}
				}
			}
		}

		if (adjust && (chpos || chbp))
			this.adjust();
	},
	$setSize:function(x,y){
		var parentWidth = this.getParentView().$width;
		if (typeof parentWidth !== 'undefined')
			this._initLabelPosition(true);
		return webix.ui.form.prototype.$setSize.call(this,x,y);
	}
}, webix.ui.form);
<commit_msg>Fixed issue where all features were ignore if no validation API is available<commit_after>/*!
 * Dropin replacement for webix 'form' component that supports
 * html5 validation attributes if supported by the browser.
 *
 * Provided under MIT License (MIT)
 * Copyright (C) 2016 IDNT Europe GmbH (www.idnt.net)
 */

if (typeof webix === 'undefined')
    throw new Error('h5form requires webix');

webix.protoUI({
	name:'h5form',
	defaults: {
		autoLabelPositioning: true,
		autoBottomPadding: true,
		defaultLabelWidth: 130,
		defaultLabelPosition: 'left',
		autoheight:true,
	},
	$init:function(config) {
		var oldobj = this._viewobj;
		this._contentobj = this._viewobj = webix.html.create("FORM",{
				'class':'webix_view webix_form webix_custom_h5form',
				'action':'javascript:0;',
			});

		while(oldobj.childNodes.length > 0)
			this._viewobj.appendChild(oldobj.childNodes[0]);

		this.$view = this._viewobj;

		this.config = webix.extend(config, this.defaults, false);

		var self = this;

		config.elementsConfig = config.elementsConfig || {};
		config.elementsConfig.on = config.elementsConfig.on || {};
		if (config.autoLabelPositioning) {
			config.elementsConfig.labelPosition = config.elementsConfig.labelPosition || config.defaultLabelPosition;
			config.elementsConfig.labelWidth = config.elementsConfig.labelWidth || config.defaultLabelWidth;
		}

		if (this.$view.checkValidity) { // Ensure we have the validation API

			var savedOnChange = config.elementsConfig.on.onChange;
			config.elementsConfig.on.onChange = function(newV, oldV) {
				if (this.config.name) {
					self.$view.checkValidity()
					var node = this.getInputNode();
					if (node && typeof node.willValidate !== 'undefined' && node.validity && !node.validity.valid)
						self.markInvalid(this.config.name, node.validationMessage || 'Please check your input.');
				}

				if (typeof savedOnChange === 'function')
					savedOnChange.call(this, newVm, oldV);
			}

			config.rules = config.rules || {};
			var savedObjRule = config.rules.$obj;
			config.rules.$obj = function() {
				var valid = true;
				Object.keys(self.elements).forEach(function (fieldName) {
					var inputView = self.elements[fieldName];
					if (inputView) {
						var node = inputView.getInputNode();
						if (node && typeof node.willValidate !== 'undefined' && node.validity && !node.validity.valid) {
							self.markInvalid(fieldName, node.validationMessage || 'Please check your input.');
							valid = false;
						}
					}
				});
				return valid && (!savedObjRule !== 'function' || savedObjRule.call(this, arguments));
			}

			config.on = config.on || {};
			var savedHandler = config.on.onBeforeValidate;
			config.on.onBeforeValidate = function() {
				self.$view.checkValidity()
				if (savedHandler === 'function')
					savedHandler.call(this, arguments);
			}

			this.$view.onsubmit = function(e) {
				self.clearValidation();
				self.validate();
				e.preventDefault();
				return false;
			};
		}
	},
	_initLabelPosition:function(adjust) {
		var pos = 'left';
		var width = this.getParentView().$width;
		if (width < 500)
			pos='top';

		var chpos = chbp = false;
		if (this.config.elementsConfig.labelPosition != pos) {
			this.config.elementsConfig.labelPosition = pos;
			chpos = true;
		}

		if (chpos || this.config.autoBottomPadding) {
			for (var n in this.elements) {
				var e = this.elements[n];
				if (this.config.autoLabelPositioning && chpos) {
					if (pos == 'top') {
						e.config.labelPosition = 'top';
						e._settings.labelPosition = 'top';
						e._settings._savedLabelWidth = e._settings.labelWidth;
						e._settings._savedHeight = e._settings.height;
						e.config.height += 20;
						if (adjust)
							e.render();
					}
					else if (pos == 'left') {
						e.config.labelPosition = 'left';
						e._settings.labelPosition = e.config.labelPosition;
						e.config.labelWidth = e._settings._savedLabelWidth;
						e._settings.labelWidth = e.config.labelWidth;
						e.config.height = e._settings._savedHeight;
					}
				}

				// Adjust the bottom label if present
				if (this.config.autoBottomPadding &&
					typeof e.config.bottomLabel !== 'undefined' &&
					e.config.bottomLabel.length) {
					var fWidth = e._input_width || (width - e.config.labelWidth);
					var lSize = webix.html.getTextSize(e.config.bottomLabel);
					var bp = Math.ceil(lSize.width / fWidth) * lSize.height;
					if (e.config.bottomPadding != bp) {
						e.config.bottomPadding = bp;
						chbp = true;
					}
				}
			}
		}

		if (adjust && (chpos || chbp))
			this.adjust();
	},
	$setSize:function(x,y){
		var parentWidth = this.getParentView().$width;
		if (typeof parentWidth !== 'undefined')
			this._initLabelPosition(true);
		return webix.ui.form.prototype.$setSize.call(this,x,y);
	}
}, webix.ui.form);
<|endoftext|>


<commit_before>// Copyright (c) 2013 Ryan Clark
    // https://gist.github.com/rclark/5779673
    L.TopoJSON = L.GeoJSON.extend({
        addData: function (jsonData) {
            if (jsonData.type === "Topology") {
                for (key in jsonData.objects) {
                    geojson = topojson.feature(jsonData, jsonData.objects[key]);
                    L.GeoJSON.prototype.addData.call(this, geojson);
                }
            }
            else {
                L.GeoJSON.prototype.addData.call(this, jsonData);
            }
        }
    });

var spreadsheetID = "1mxcmAbjrVTU9c3zDy-Mz7PfziEtKNI1PejGuvwD4PW4";
var jsonurl = "https://spreadsheets.google.com/feeds/list/" + spreadsheetID + "/1/public/values?alt=json";
$.getJSON(jsonurl, function(datas) {
    $entrys = datas.feed.entry;
     $($entrys).each(function(){
        if(this.gsx$district.$t.toLowerCase()=="total") {
            if (this.gsx$nagarpalika.$t == '') {
                this.gsx$nagarpalika.$t = 0
            }
            if (this.gsx$gaupalika.$t == '') {
                this.gsx$gaupalika.$t = 0
            }
            if (this.gsx$upamahanarpalika.$t == '') {
                this.gsx$upamahanarpalika.$t = 0

            }
            if (this.gsx$mahanarpalika.$t == '') {
                this.gsx$mahanarpalika.$t = 0
            }
              if (this.gsx$totalnumberofregisteredvoters.$t == '') {
                this.gsx$mahanarpalika.$t = "NULL"
            }
            document.getElementById("nagar").innerHTML = this.gsx$nagarpalika.$t;
            document.getElementById("upnagar").innerHTML = this.gsx$upamahanarpalika.$t;
            document.getElementById("mahanagar").innerHTML = this.gsx$mahanarpalika.$t;
            document.getElementById("gau").innerHTML = this.gsx$gaupalika.$t;
            document.getElementById("tp").innerHTML = this.gsx$totalpopulation.$t;
            document.getElementById("rpp").innerHTML = this.gsx$registeredpoliticalparties.$t;
            document.getElementById("trv").innerHTML = this.gsx$totalnumberofregisteredvoters.$t;

        }

    });

});

function getUpdate(e) {
    $($entrys).each(function(){
        if(this.gsx$district.$t.toLowerCase()==e.toLowerCase()) {
            if (this.gsx$nagarpalika.$t == '') {
                this.gsx$nagarpalika.$t = 0
            }
            if (this.gsx$gaupalika.$t == '') {
                this.gsx$gaupalika.$t = 0
            }
            if (this.gsx$upamahanarpalika.$t == '') {
                this.gsx$upamahanarpalika.$t = 0

            }
            if (this.gsx$mahanarpalika.$t == '') {
                this.gsx$mahanarpalika.$t = 0
            }
            if (this.gsx$totalnumberofregisteredvoters.$t == '') {
                this.gsx$mahanarpalika.$t = "NULL"
            }            document.getElementById("nagar").innerHTML = this.gsx$nagarpalika.$t;
            document.getElementById("upnagar").innerHTML = this.gsx$upamahanarpalika.$t;
            document.getElementById("mahanagar").innerHTML = this.gsx$mahanarpalika.$t;
            document.getElementById("gau").innerHTML = this.gsx$gaupalika.$t;
            document.getElementById("district").innerHTML = e;
            document.getElementById("tp").innerHTML = this.gsx$totalpopulation.$t;
            document.getElementById("rpp").innerHTML = this.gsx$registeredpoliticalparties.$t;
            document.getElementById("trv").innerHTML = this.gsx$totalnumberofregisteredvoters.$t;

        }

    });

    }

     (function () {
        var map = L.map('map', {maxZoom:  6.9, minZoom:  6.9 }),
            topoLayer = new L.TopoJSON(),
            colorScale = chroma
                .scale(['#D5E3FF', '#003171'])
                .domain([0, 1]);
        map.setView([28.1999999, 84.100140],  6.9);

        $.getJSON('static/assets/javascripts/nepal-districts.topo.json').done(addTopoData);

        function addTopoData(topoData) {
            topoLayer.addData(topoData);
            topoLayer.addTo(map);
            topoLayer.eachLayer(handleLayer);
        }

        function highlightFeature(e) {
            var layer = e.target;
            layer.setStyle(
                {
                    weight: 1,
                    color: 'black',
                    fillColor: 'blue',
                }
            );
            if (!L.Browser.ie && !L.Browser.opera) {
                layer.bringToFront();
            }
        }

        function resetHighlight(e) {
            var layer = e.target;
            var setColor=layer.feature.properties.pradesh_no
            layer.setStyle(
                {
                    fillColor: getProvinceColor(setColor),
                    weight: 2,
                    opacity: 1,
                    color: 'white',
                    dashArray: 3,
                    fillOpacity: 0.7
                }
            );

            if (!L.Browser.ie && !L.Browser.opera) {
                layer.bringToFront();
            }
        }

        function handleLayer(layer) {
            layer.bindLabel(layer.feature.properties.name, {noHide: true})
            var code = layer.feature.properties.name;
            var setColor=layer.feature.properties.pradesh_no;
            layer.setStyle({
                fillColor: getProvinceColor(setColor),
                weight: 2,
                opacity: 1,
                color: 'white',
                dashArray: 3,
                fillOpacity: 0.7
            });
            layer.on({
                mouseover: highlightFeature,
                mouseout: resetHighlight,

            });

            layer.on('click', function (e) {
                 getUpdate(layer.feature.properties.name);
            });
        }

        function getProvinceColor(state) {
            if (state == 7) {
                return 'red';
            } else if (state == 6) {
                return '#c1a73e';
            } else if (state == 5) {
                return '#da8b4a';
            }
            else if (state == 4) {
                return '#26a9e8';
            }
            else if (state == 3) {
                return '#40a500';
            }
            else if (state == 2) {
                return '#e271a1';
            }
            else if (state == 1) {
                return '#900e94';
            }

        }

        var legend = L.control({position: 'topright'});
        legend.onAdd = function (map) {
            var div = L.DomUtil.create('div', 'legend');
            var labels = [
                "Province No. 1",
                "Province No. 2",
                "Province No. 3",
                "Province No. 4",
                "Province No. 5",
                "Province No. 6",
                "Province No. 7"
            ];
            var grades = [1, 2, 3, 4, 5, 6, 7];
            div.innerHTML = '

Province Index

';
            for (var i = 0; i < grades.length; i++) {
                div.innerHTML += '      '
                    + labels[i] + '
';
            }
            return div;
        }
        legend.addTo(map);

    }());
<commit_msg>Disable Dragging<commit_after>// Copyright (c) 2013 Ryan Clark
    // https://gist.github.com/rclark/5779673
    L.TopoJSON = L.GeoJSON.extend({
        addData: function (jsonData) {
            if (jsonData.type === "Topology") {
                for (key in jsonData.objects) {
                    geojson = topojson.feature(jsonData, jsonData.objects[key]);
                    L.GeoJSON.prototype.addData.call(this, geojson);
                }
            }
            else {
                L.GeoJSON.prototype.addData.call(this, jsonData);
            }
        }
    });

var spreadsheetID = "1mxcmAbjrVTU9c3zDy-Mz7PfziEtKNI1PejGuvwD4PW4";
var jsonurl = "https://spreadsheets.google.com/feeds/list/" + spreadsheetID + "/1/public/values?alt=json";
$.getJSON(jsonurl, function(datas) {
    $entrys = datas.feed.entry;
     $($entrys).each(function(){
        if(this.gsx$district.$t.toLowerCase()=="total") {
            if (this.gsx$nagarpalika.$t == '') {
                this.gsx$nagarpalika.$t = 0
            }
            if (this.gsx$gaupalika.$t == '') {
                this.gsx$gaupalika.$t = 0
            }
            if (this.gsx$upamahanarpalika.$t == '') {
                this.gsx$upamahanarpalika.$t = 0

            }
            if (this.gsx$mahanarpalika.$t == '') {
                this.gsx$mahanarpalika.$t = 0
            }
              if (this.gsx$totalnumberofregisteredvoters.$t == '') {
                this.gsx$mahanarpalika.$t = "NULL"
            }
            document.getElementById("nagar").innerHTML = this.gsx$nagarpalika.$t;
            document.getElementById("upnagar").innerHTML = this.gsx$upamahanarpalika.$t;
            document.getElementById("mahanagar").innerHTML = this.gsx$mahanarpalika.$t;
            document.getElementById("gau").innerHTML = this.gsx$gaupalika.$t;
            document.getElementById("tp").innerHTML = this.gsx$totalpopulation.$t;
            document.getElementById("rpp").innerHTML = this.gsx$registeredpoliticalparties.$t;
            document.getElementById("trv").innerHTML = this.gsx$totalnumberofregisteredvoters.$t;

        }

    });

});

function getUpdate(e) {
    $($entrys).each(function(){
        if(this.gsx$district.$t.toLowerCase()==e.toLowerCase()) {
            if (this.gsx$nagarpalika.$t == '') {
                this.gsx$nagarpalika.$t = 0
            }
            if (this.gsx$gaupalika.$t == '') {
                this.gsx$gaupalika.$t = 0
            }
            if (this.gsx$upamahanarpalika.$t == '') {
                this.gsx$upamahanarpalika.$t = 0

            }
            if (this.gsx$mahanarpalika.$t == '') {
                this.gsx$mahanarpalika.$t = 0
            }
            if (this.gsx$totalnumberofregisteredvoters.$t == '') {
                this.gsx$mahanarpalika.$t = "NULL"
            }            document.getElementById("nagar").innerHTML = this.gsx$nagarpalika.$t;
            document.getElementById("upnagar").innerHTML = this.gsx$upamahanarpalika.$t;
            document.getElementById("mahanagar").innerHTML = this.gsx$mahanarpalika.$t;
            document.getElementById("gau").innerHTML = this.gsx$gaupalika.$t;
            document.getElementById("district").innerHTML = e;
            document.getElementById("tp").innerHTML = this.gsx$totalpopulation.$t;
            document.getElementById("rpp").innerHTML = this.gsx$registeredpoliticalparties.$t;
            document.getElementById("trv").innerHTML = this.gsx$totalnumberofregisteredvoters.$t;

        }

    });

    }

     (function () {
        var map = L.map('map', {maxZoom:  7.9, minZoom:  6.9 }),
            topoLayer = new L.TopoJSON(),
            colorScale = chroma
                .scale(['#D5E3FF', '#003171'])
                .domain([0, 1]);
                 map.dragging.disable();

        map.setView([28.1999999, 84.100140],  6.9);

        $.getJSON('static/assets/javascripts/nepal-districts.topo.json').done(addTopoData);

        function addTopoData(topoData) {
            topoLayer.addData(topoData);
            topoLayer.addTo(map);
            topoLayer.eachLayer(handleLayer);
        }

        function highlightFeature(e) {
            var layer = e.target;
            layer.setStyle(
                {
                    weight: 1,
                    color: 'black',
                    fillColor: 'blue',
                }
            );
            if (!L.Browser.ie && !L.Browser.opera) {
                layer.bringToFront();
            }
        }

        function resetHighlight(e) {
            var layer = e.target;
            var setColor=layer.feature.properties.pradesh_no
            layer.setStyle(
                {
                    fillColor: getProvinceColor(setColor),
                    weight: 2,
                    opacity: 1,
                    color: 'white',
                    dashArray: 3,
                    fillOpacity: 0.7
                }
            );

            if (!L.Browser.ie && !L.Browser.opera) {
                layer.bringToFront();
            }
        }

        function handleLayer(layer) {
            layer.bindLabel(layer.feature.properties.name, {noHide: true})
            var code = layer.feature.properties.name;
            var setColor=layer.feature.properties.pradesh_no;
            layer.setStyle({
                fillColor: getProvinceColor(setColor),
                weight: 2,
                opacity: 1,
                color: 'white',
                dashArray: 3,
                fillOpacity: 0.7
            });
            layer.on({
                mouseover: highlightFeature,
                mouseout: resetHighlight,

            });

            layer.on('click', function (e) {
                 getUpdate(layer.feature.properties.name);
            });
        }

        function getProvinceColor(state) {
            if (state == 7) {
                return 'red';
            } else if (state == 6) {
                return '#c1a73e';
            } else if (state == 5) {
                return '#da8b4a';
            }
            else if (state == 4) {
                return '#26a9e8';
            }
            else if (state == 3) {
                return '#40a500';
            }
            else if (state == 2) {
                return '#e271a1';
            }
            else if (state == 1) {
                return '#900e94';
            }

        }

        var legend = L.control({position: 'topright'});
        legend.onAdd = function (map) {
            var div = L.DomUtil.create('div', 'legend');
            var labels = [
                "Province No. 1",
                "Province No. 2",
                "Province No. 3",
                "Province No. 4",
                "Province No. 5",
                "Province No. 6",
                "Province No. 7"
            ];
            var grades = [1, 2, 3, 4, 5, 6, 7];
            div.innerHTML = '

Province Index

';
            for (var i = 0; i < grades.length; i++) {
                div.innerHTML += '      '
                    + labels[i] + '
';
            }
            return div;
        }
        legend.addTo(map);

    }());
<|endoftext|>