<commit_before>/**
 * Wheel, copyright (c) 2017 - present by Arno van der Vegt
 * Distributed under an MIT license: https://arnovandervegt.github.io/wheel/license.txt
**/
const dispatcher  = require('../../../js/frontend/lib/dispatcher').dispatcher;
const testLogs    = require('../../utils').testLogs;
const testCompile = require('../../utils').testCompile;
const assert      = require('assert');

describe(
    'Test VM',
    function() {
        describe(
            'Test Log',
            function() {
                testLogs(
                    it,
                    'Should log number',
                    [
                        'number n',
                        'proc main()',
                        '    addr n',
                        '    n = 21',
                        '    mod 0, 1',
                        'end'
                    ],
                    [
                        21
                    ]
                );
                it(
                    'Should assert getters',
                    function() {
                        let source = [
                                'number n',
                                'proc main()',
                                '    addr n',
                                '    n = 22',
                                '    mod 0, 1',
                                'end'
                            ];
                        let info = testCompile(source);
                        dispatcher.on('Console.Log', this, function(opts) {
                            assert.equal(opts.message, 22);
                        });
                        info.vm.setCommands(info.commands);
                        assert.equal(info.vm.getModules().length, 12);
                        assert.equal(info.vm.getBreakpoint(),     false);
                    }
                );
                it(
                    'Should stop',
                    function(done) {
                        let source = [
                                'proc main()',
                                '    repeat',
                                '    end',
                                'end'
                            ];
                        let info = testCompile(source);
                        dispatcher.on('Console.Log', this, function(opts) {
                            assert.equal(opts.message, 22);
                        });
                        info.vm.setCommands(info.commands).startRunInterval(function() {});
                        setTimeout(
                            function() {
                                assert.equal(info.vm.running(), true);
                                info.vm.stop();
                                assert.equal(info.vm.running(), false);
                                done();
                            },
                            15
                        );
                    }
                );
                it(
                    'Should finish',
                    function(done) {
                        let source = [
                                'number n',
                                'proc main()',
                                '    n = 1',
                                'end'
                            ];
                        let info   = testCompile(source);
                        let called = false;
                        info.vm.setCommands(info.commands).startRunInterval(function() { called = true; });
                        setTimeout(
                            function() {
                                assert.equal(called, true);
                                done();
                            },
                            10
                        );
                    }
                );
                it(
                    'Should sleep',
                    function(done) {
                        let source = [
                                'proc main()',
                                '    repeat',
                                '    end',
                                'end'
                            ];
                        let info = testCompile(source);
                        info.vm.setCommands(info.commands).startRunInterval(function() {});
                        info.vm.sleep(5);
                        setTimeout(
                            function() {
                                info.vm.stop();
                                assert.equal(info.vm.running(), false);
                                done();
                            },
                            15
                        );
                    }
                );
                it(
                    'Should sleep with module call',
                    function(done) {
                        let source = [
                                'proc main()',
                                '    number time = 50',
                                '    addr time',
                                '    mod  0, 4',
                                '    repeat',
                                '    end',
                                'end'
                            ];
                        let info = testCompile(source);
                        info.vm.setCommands(info.commands).startRunInterval(function() {});
                        setTimeout(
                            function() {
                                assert.equal(info.vm.sleeping(), true);
                                info.vm.stop();
                                assert.equal(info.vm.running(), false);
                                done();
                            },
                            10
                        );
                    }
                );
                it(
                    'Should break',
                    function(done) {
                        let source = [
                                'proc main()',
                                '    number n',
                                '    n = 55',
                                '    addr n',
                                '    mod 0, 1',
                                'end'
                            ];
                        let info = testCompile(source);
                        let m    = false;
                        info.modules[0].on('Console.Log', this, function(opts) {
                            m = opts.message;
                        });
                        dispatcher.on('VM.Breakpoint', this, function(vm, breakpoint) {
                            assert.equal(breakpoint.test, true);
                            info.vm.continueAfterBreakpoint(breakpoint);
                        });
                        info.commands[1].setBreakpoint({test: true});
                        info.vm.setCommands(info.commands).startRunInterval(function() {});
                        setTimeout(
                            function() {
                                info.vm.stop();
                                assert.equal(info.vm.running(), false);
                                done();
                                assert.equal(m, 55);
                            },
                            15
                        );
                    }
                );
                it(
                    'Should ingore missing break',
                    function(done) {
                        let source = [
                                'proc main()',
                                '    repeat',
                                '    end',
                                'end'
                            ];
                        let info = testCompile(source);
                        info.vm.setCommands(info.commands).startRunInterval(function() {});
                        setTimeout(
                            function() {
                                info.vm.continueAfterBreakpoint(false);
                                info.vm.stop();
                                assert.equal(info.vm.running(), false);
                                done();
                            },
                            15
                        );
                    }
                );
                it(
                    'Should throw unknown module',
                    function() {
                        assert.throws(
                            function() {
                                let source = [
                                        'number n',
                                        'proc main()',
                                        '    mod 101, 0',
                                        'end'
                                    ];
                                let info = testCompile(source);
                                info.vm.setCommands(info.commands).run();
                            },
                            function(error) {
                                return (error.toString() === 'Error: Unknown module "101"');
                            }
                        );
                    }
                );
                it(
                    'Should stop vm',
                    function() {
                        let source = [
                                'proc main()',
                                '    repeat',
                                '        mod 0, 7',
                                '    end',
                                'end'
                            ];
                        let info = testCompile(source);
                        info.vm.setCommands(info.commands).startRunInterval(function() {});
                        assert.equal(info.vm.running(), true);
                    }
                );
                it(
                    'Should stop program',
                    function() {
                        let source = [
                                'proc main()',
                                '    repeat',
                                '        mod 0, 8',
                                '    end',
                                'end'
                            ];
                        let info = testCompile(source);
                        info.vm.setCommands(info.commands).startRunInterval(function() {});
                        assert.equal(info.vm.running(), true);
                    }
                );
            }
        );
    }
);
<commit_msg>Stop VM after test.<commit_after>/**
 * Wheel, copyright (c) 2017 - present by Arno van der Vegt
 * Distributed under an MIT license: https://arnovandervegt.github.io/wheel/license.txt
**/
const dispatcher  = require('../../../js/frontend/lib/dispatcher').dispatcher;
const testLogs    = require('../../utils').testLogs;
const testCompile = require('../../utils').testCompile;
const assert      = require('assert');

describe(
    'Test VM',
    function() {
        describe(
            'Test Log',
            function() {
                testLogs(
                    it,
                    'Should log number',
                    [
                        'number n',
                        'proc main()',
                        '    addr n',
                        '    n = 21',
                        '    mod 0, 1',
                        'end'
                    ],
                    [
                        21
                    ]
                );
                it(
                    'Should assert getters',
                    function() {
                        let source = [
                                'number n',
                                'proc main()',
                                '    addr n',
                                '    n = 22',
                                '    mod 0, 1',
                                'end'
                            ];
                        let info = testCompile(source);
                        dispatcher.on('Console.Log', this, function(opts) {
                            assert.equal(opts.message, 22);
                        });
                        info.vm.setCommands(info.commands);
                        assert.equal(info.vm.getModules().length, 12);
                        assert.equal(info.vm.getBreakpoint(),     false);
                    }
                );
                it(
                    'Should stop',
                    function(done) {
                        let source = [
                                'proc main()',
                                '    repeat',
                                '    end',
                                'end'
                            ];
                        let info = testCompile(source);
                        dispatcher.on('Console.Log', this, function(opts) {
                            assert.equal(opts.message, 22);
                        });
                        info.vm.setCommands(info.commands).startRunInterval(function() {});
                        setTimeout(
                            function() {
                                assert.equal(info.vm.running(), true);
                                info.vm.stop();
                                assert.equal(info.vm.running(), false);
                                done();
                            },
                            15
                        );
                    }
                );
                it(
                    'Should finish',
                    function(done) {
                        let source = [
                                'number n',
                                'proc main()',
                                '    n = 1',
                                'end'
                            ];
                        let info   = testCompile(source);
                        let called = false;
                        info.vm.setCommands(info.commands).startRunInterval(function() { called = true; });
                        setTimeout(
                            function() {
                                assert.equal(called, true);
                                done();
                            },
                            10
                        );
                    }
                );
                it(
                    'Should sleep',
                    function(done) {
                        let source = [
                                'proc main()',
                                '    repeat',
                                '    end',
                                'end'
                            ];
                        let info = testCompile(source);
                        info.vm.setCommands(info.commands).startRunInterval(function() {});
                        info.vm.sleep(5);
                        setTimeout(
                            function() {
                                info.vm.stop();
                                assert.equal(info.vm.running(), false);
                                done();
                            },
                            15
                        );
                    }
                );
                it(
                    'Should sleep with module call',
                    function(done) {
                        let source = [
                                'proc main()',
                                '    number time = 50',
                                '    addr time',
                                '    mod  0, 4',
                                '    repeat',
                                '    end',
                                'end'
                            ];
                        let info = testCompile(source);
                        info.vm.setCommands(info.commands).startRunInterval(function() {});
                        setTimeout(
                            function() {
                                assert.equal(info.vm.sleeping(), true);
                                info.vm.stop();
                                assert.equal(info.vm.running(), false);
                                done();
                            },
                            10
                        );
                    }
                );
                it(
                    'Should break',
                    function(done) {
                        let source = [
                                'proc main()',
                                '    number n',
                                '    n = 55',
                                '    addr n',
                                '    mod 0, 1',
                                'end'
                            ];
                        let info = testCompile(source);
                        let m    = false;
                        info.modules[0].on('Console.Log', this, function(opts) {
                            m = opts.message;
                        });
                        dispatcher.on('VM.Breakpoint', this, function(vm, breakpoint) {
                            assert.equal(breakpoint.test, true);
                            info.vm.continueAfterBreakpoint(breakpoint);
                        });
                        info.commands[1].setBreakpoint({test: true});
                        info.vm.setCommands(info.commands).startRunInterval(function() {});
                        setTimeout(
                            function() {
                                info.vm.stop();
                                assert.equal(info.vm.running(), false);
                                done();
                                assert.equal(m, 55);
                            },
                            15
                        );
                    }
                );
                it(
                    'Should ingore missing break',
                    function(done) {
                        let source = [
                                'proc main()',
                                '    repeat',
                                '    end',
                                'end'
                            ];
                        let info = testCompile(source);
                        info.vm.setCommands(info.commands).startRunInterval(function() {});
                        setTimeout(
                            function() {
                                info.vm.continueAfterBreakpoint(false);
                                info.vm.stop();
                                assert.equal(info.vm.running(), false);
                                done();
                            },
                            15
                        );
                    }
                );
                it(
                    'Should throw unknown module',
                    function() {
                        assert.throws(
                            function() {
                                let source = [
                                        'number n',
                                        'proc main()',
                                        '    mod 101, 0',
                                        'end'
                                    ];
                                let info = testCompile(source);
                                info.vm.setCommands(info.commands).run();
                            },
                            function(error) {
                                return (error.toString() === 'Error: Unknown module "101"');
                            }
                        );
                    }
                );
                it(
                    'Should stop vm',
                    function() {
                        let source = [
                                'proc main()',
                                '    repeat',
                                '        mod 0, 7',
                                '    end',
                                'end'
                            ];
                        let info = testCompile(source);
                        info.vm.setCommands(info.commands).startRunInterval(function() {});
                        assert.equal(info.vm.running(), true);
                        info.vm.stop();
                    }
                );
                it(
                    'Should stop program',
                    function() {
                        let source = [
                                'proc main()',
                                '    repeat',
                                '        mod 0, 8',
                                '    end',
                                'end'
                            ];
                        let info = testCompile(source);
                        info.vm.setCommands(info.commands).startRunInterval(function() {});
                        assert.equal(info.vm.running(), true);
                        info.vm.stop();
                    }
                );
            }
        );
    }
);
<|endoftext|>


<commit_before>/**
 * @license GridJS
 * (c) 2015 Sneezry http://gridjs.org
 * License: MIT
 */
(function(window, document, undefined) {'use strict';

var grid = window.grid = window.grid || {},
    workplace = createWorkplace(),
    imageDataWorkplace = createWorkplace(),
    ImageObject;

ImageObject = function() {
  this.width        = null;
  this.height       = null;
  this.pixel        = null;
  this.imageData    = null;
};

function createWorkplace() {
  return document.createElement('canvas');
}

function getImageDataFromURL(url, callback) {
  workplace = workplace || createWorkplace();
  var width,
      height,
      imageData,
      context = workplace.getContext('2d'),
      image = new Image();

  image.addEventListener('load', function() {
    width = image.width;
    height = image.height;
    workplace.width = width;
    workplace.height = height;
    context.drawImage(image, 0, 0);
    imageData = context.getImageData(0, 0, width, height);
    callback(imageData);
  }, false);
  image.src = url;
}

function getPixelFromImageData(imageData) {
  var x, y, index,
      width = imageData.width,
      height = imageData.height,
      I = imageData.data,
      pixel = {
        'r' : [],
        'g' : [],
        'b' : [],
        'a' : []
      };

  for (y = 0; y < height; y++) {
    pixel.r[y] = [];
    pixel.g[y] = [];
    pixel.b[y] = [];
    pixel.a[y] = [];
    for (x = 0; x < width; x++) {
      index = (y * width + x) * 4;
      pixel.r[y][x] = I[index];
      pixel.g[y][x] = I[index + 1];
      pixel.b[y][x] = I[index + 2];
      pixel.a[y][x] = I[index + 3] / 255;
    }
  }

  return pixel;
}

/*
function getPixelFromURL(url, callback) {
  getImageDataFromURL(url, function(imageData) {
    getPixelFromImageData(imageData, callback);
  });
}

function getPixel(image, callback) {
  if (typeof(image) === 'string') {
    getPixelFromURL(image, callback);
  } else if (Array.isArray(image.r) === true) {
    callback(image);
  } else {
    getPixelFromImageData(image, callback);
  }
}

function getImageData(image, callback) {
  if (typeof(image) === 'string') {
    getImageDataFromURL(image, callback);
  } else if (Array.isArray(image.r) === true) {
    callback(getImageDataFromPixel(image));
  } else {
    callback(image);
  }
}
*/

function getImageDataFromPixel(pixel) {
  workplace = workplace || createWorkplace();
  var x, y, index,
      width = pixel.r[0].length,
      height = pixel.r.length,
      context = workplace.getContext('2d'),
      imageData = context.createImageData(width, height);

  workplace.width = width;
  workplace.height = height;

  for (y = 0; y < height; y++) {
    for (x = 0; x < width; x++) {
      index = (y * width + x) * 4;
      imageData.data[index]   = pixel.r[y][x];
      imageData.data[index + 1] = pixel.g[y][x];
      imageData.data[index + 2] = pixel.b[y][x];
      imageData.data[index + 3] = Math.round(pixel.a[y][x] * 255);
    }
  }

  return imageData;
}

function getImageFromImageData(imageData) {
  var imageDataContext = imageDataWorkplace.getContext('2d');

  imageDataWorkplace.width = imageData.width;
  imageDataWorkplace.height = imageData.height;
  imageDataContext.putImageData(imageData, 0, 0);

  return imageDataWorkplace;
}

grid.open = function(image, callback) {
  if (typeof(image) === 'string') {
    grid.getImageObjectFromURL(image, callback);
  } else if (Array.isArray(image.r) === true) {
    callback(grid.getImageObjectFromPixel(image));
  } else if (typeof(image) === 'object') {
    callback(grid.getImageObjectFromImageData(image));
  }
};

grid.getImageObject = grid.open;

grid.getImageObjectFromURL = function(url, callback) {
  getImageDataFromURL(url, function(imageData) {
    var imageObject = new ImageObject();
    imageObject.imageData = imageData;
    imageObject.pixel = getPixelFromImageData(imageData);
    imageObject.width = imageData.width;
    imageObject.height = imageData.height;

    callback(imageObject);
  });
};

grid.getImageObjectFromImageData = function(imageData) {
  var width = imageData.width,
      height = imageData.height,
      pixel = getPixelFromImageData(imageData),
      imageObject = new ImageObject();

  imageObject.pixel = pixel;
  imageObject.imageData = imageData;
  imageObject.height = height;
  imageObject.width = width;

  return imageObject;
};

grid.getImageObjectFromPixel = function(pixel) {
  var width = pixel[0].length,
      height = pixel.length,
      imageData = getImageDataFromPixel(pixel),
      imageObject = new ImageObject();

    imageObject.pixel = pixel;
    imageObject.imageData = imageData;
    imageObject.height = height;
    imageObject.width = width;

    return imageObject;
};

ImageObject.prototype.grayscale = function() {
  var x, y, gray,
      imageObject = this,
      width = imageObject.width,
      height = imageObject.height,
      grayImageObject = new ImageObject(),
      pixel = {
        'r' : [],
        'g' : [],
        'b' : [],
        'a' : []
      };

  for (y = 0; y < height; y++) {
    pixel.r[y] = [];
    pixel.g[y] = [];
    pixel.b[y] = [];
    pixel.a[y] = [];
    for (x = 0; x < width; x++) {
      gray = 0.299 * imageObject.pixel.r[y][x] +
             0.587 * imageObject.pixel.g[y][x] +
             0.114 * imageObject.pixel.b[y][x];
      pixel.r[y][x] = pixel.g[y][x] = pixel.b[y][x] = gray;
      pixel.a[y][x] = imageObject.pixel.a[y][x];
    }
  }

  grayImageObject.pixel = pixel;
  grayImageObject.imageData = getImageDataFromPixel(pixel);
  grayImageObject.height = height;
  grayImageObject.width = width;

  return grayImageObject;
};

ImageObject.prototype.putImage = function(canvas) {
  var context,
      imageObject = this;

  canvas.width = imageObject.width;
  canvas.height = imageObject.height;
  context = canvas.getContext('2d');

  context.putImageData(imageObject.imageData, 0, 0);

  return imageObject;
};

ImageObject.prototype.blend = function(srcImageObject, offsetX, offsetY) {
  var x, y,
      imageObject = this,
      width = imageObject.width,
      height = imageObject.height,
      srcWidth = srcImageObject.width,
      srcHeight = srcImageObject.height,
      pixel = {
        'r' : [],
        'g' : [],
        'b' : [],
        'a' : []
      };

  offsetX = isNaN(offsetX) ? 0 : Math.round(offsetX);
  offsetY = isNaN(offsetY) ? 0 : Math.round(offsetY);

  for (y = 0; y < height; y++) {
    pixel.r[y] = [];
    pixel.g[y] = [];
    pixel.b[y] = [];
    pixel.a[y] = [];
    for (x = 0; x < width; x++) {
      pixel.a[y][x] = (y - offsetY < 0 || x - offsetX < 0 ||
              y - offsetY >= srcHeight || x - offsetX >= srcWidth) ?
          imageObject.pixel.a[y][x] :
          (srcImageObject.pixel.a[y - offsetY][x - offsetX] +
              imageObject.pixel.a[y][x] *
              (1 - srcImageObject.pixel.a[y - offsetY][x - offsetX]));

      pixel.r[y][x] = (y - offsetY < 0 || x - offsetX < 0 ||
              y - offsetY >= srcHeight || x - offsetX >= srcWidth || pixel.a[y][x] < 0.003) ?
          imageObject.pixel.r[y][x] :
          (srcImageObject.pixel.r[y - offsetY][x - offsetX] * srcImageObject.pixel.a[y - offsetY][x - offsetX] +
              imageObject.pixel.r[y][x] * imageObject.pixel.a[y][x] *
              (1 - srcImageObject.pixel.a[y - offsetY][x - offsetX])) / pixel.a[y][x];

      pixel.g[y][x] = (y - offsetY < 0 || x - offsetX < 0 ||
              y - offsetY >= srcHeight || x - offsetX >= srcWidth || pixel.a[y][x] < 0.003) ?
          imageObject.pixel.g[y][x] :
          (srcImageObject.pixel.g[y - offsetY][x - offsetX] * srcImageObject.pixel.a[y - offsetY][x - offsetX] +
              imageObject.pixel.g[y][x] * imageObject.pixel.a[y][x] *
              (1 - srcImageObject.pixel.a[y - offsetY][x - offsetX])) / pixel.a[y][x];

      pixel.b[y][x] = (y - offsetY < 0 || x - offsetX < 0 ||
              y - offsetY >= srcHeight || x - offsetX >= srcWidth || pixel.a[y][x] < 0.003) ?
          imageObject.pixel.b[y][x] :
          (srcImageObject.pixel.b[y - offsetY][x - offsetX] * srcImageObject.pixel.a[y - offsetY][x - offsetX] +
              imageObject.pixel.b[y][x] * imageObject.pixel.a[y][x] *
              (1 - srcImageObject.pixel.a[y - offsetY][x - offsetX])) / pixel.a[y][x];

      pixel.r[y][x] = Math.round(pixel.r[y][x]);
      pixel.g[y][x] = Math.round(pixel.g[y][x]);
      pixel.b[y][x] = Math.round(pixel.b[y][x]);

      if (pixel.a[y][x] < 0.003) {
        pixel.a[y][x] = imageObject.pixel.a[y][x];
      }
    }
  }

  imageObject.width = width;
  imageObject.height = height;
  imageObject.pixel = pixel;
  imageObject.imageData = getImageDataFromPixel(pixel);

  return imageObject;
};

ImageObject.prototype.copy = function() {
  var x, y,
      imageObject = this,
      width = imageObject.width,
      height = imageObject.height,
      newImageObject = new ImageObject(),
      pixel = {
        'r' : [],
        'g' : [],
        'b' : [],
        'a' : []
      };

  for (y = 0; y < height; y++) {
    pixel.r[y] = [];
    pixel.g[y] = [];
    pixel.b[y] = [];
    pixel.a[y] = [];
    for (x = 0; x < width; x++) {
      pixel.r[y][x] = imageObject.pixel.r[y][x];
      pixel.g[y][x] = imageObject.pixel.g[y][x];
      pixel.b[y][x] = imageObject.pixel.b[y][x];
      pixel.a[y][x] = imageObject.pixel.a[y][x];
    }
  }

  newImageObject.pixel = pixel;
  newImageObject.imageData = getImageDataFromPixel(pixel);
  newImageObject.height = height;
  newImageObject.width = width;

  return newImageObject;
};

ImageObject.prototype.resize = function(newWidth, newHeight) {
  var imageObject = this,
      context = workplace.getContext('2d'),
      image = getImageFromImageData(imageObject.imageData);

  workplace.width = newWidth;
  workplace.height = newHeight;
  context.drawImage(image, 0, 0, newWidth, newHeight);

  imageObject.width = newWidth;
  imageObject.height = newHeight;
  imageObject.imageData = context.getImageData(0, 0, newWidth, newHeight);
  imageObject.pixel = getPixelFromImageData(imageObject.imageData);

  return imageObject;
};

ImageObject.prototype.rotate = function(degree) {
  var imageObject = this,
      width = imageObject.width,
      height = imageObject.height,
      rad = -degree * Math.PI / 180,
      context = workplace.getContext('2d'),
      image = getImageFromImageData(imageObject.imageData),
      rotatedWidth, rotatedHeight;

  rotatedWidth = Math.abs(width * Math.cos(rad)) + Math.abs(height * Math.sin(rad));
  rotatedWidth = Math.ceil(rotatedWidth);
  rotatedHeight = Math.abs(width * Math.sin(rad)) + Math.abs(height * Math.cos(rad));
  rotatedHeight = Math.ceil(rotatedHeight);

  workplace.width = rotatedWidth;
  workplace.height = rotatedHeight;
  context.translate(rotatedWidth / 2, rotatedHeight / 2);
  context.rotate(rad);
  context.translate(-width / 2, -height / 2);
  context.drawImage(image, 0, 0);

  imageObject.width = rotatedWidth;
  imageObject.height = rotatedHeight;
  imageObject.imageData = context.getImageData(0, 0, rotatedWidth, rotatedHeight);
  imageObject.pixel = getPixelFromImageData(imageObject.imageData);

  return imageObject;
};

ImageObject.prototype.crop = function(left, top, cropWidth, cropHeight) {
  var imageObject = this,
      context = workplace.getContext('2d'),
      image = getImageFromImageData(imageObject.imageData);

  workplace.width = cropWidth;
  workplace.height = cropHeight;
  context.drawImage(image, left, top, cropWidth, cropHeight, 0, 0, cropWidth, cropHeight);

  imageObject.width = cropWidth;
  imageObject.height = cropHeight;
  imageObject.imageData = context.getImageData(0, 0, cropWidth, cropHeight);
  imageObject.pixel = getPixelFromImageData(imageObject.imageData);

  return imageObject;
};

ImageObject.prototype.updateImageData = function() {
  var imageObject = this;
  imageObject.imageData = getImageDataFromPixel(imageObject.pixel);

  return imageObject;
};

ImageObject.prototype.updatePixel = function() {
  var imageObject = this;
  imageObject.imageData = getPixelFromImageData(imageObject.imageData);

  return imageObject;
};

ImageObject.prototype.update = ImageObject.prototype.updateImageData;

})(window, document);<commit_msg>201505151258<commit_after>/**
 * @license GridJS
 * (c) 2015 Sneezry http://gridjs.org
 * License: MIT
 */
(function(window, document, undefined) {'use strict';

var grid = window.grid = window.grid || {},
    workplace = createWorkplace(),
    imageDataWorkplace = createWorkplace(),
    ImageObject;

ImageObject = function() {
  this.width        = null;
  this.height       = null;
  this.pixel        = null;
  this.imageData    = null;
};

function createWorkplace() {
  return document.createElement('canvas');
}

function getImageDataFromURL(url, callback) {
  workplace = workplace || createWorkplace();
  var width,
      height,
      imageData,
      context = workplace.getContext('2d'),
      image = new Image();

  image.addEventListener('load', function() {
    width = image.width;
    height = image.height;
    workplace.width = width;
    workplace.height = height;
    context.drawImage(image, 0, 0);
    imageData = context.getImageData(0, 0, width, height);
    callback(imageData);
  }, false);
  image.src = url;
}

function getPixelFromImageData(imageData) {
  var x, y, index,
      width = imageData.width,
      height = imageData.height,
      I = imageData.data,
      pixel = {
        'r' : [],
        'g' : [],
        'b' : [],
        'a' : []
      };

  for (y = 0; y < height; y++) {
    pixel.r[y] = [];
    pixel.g[y] = [];
    pixel.b[y] = [];
    pixel.a[y] = [];
    for (x = 0; x < width; x++) {
      index = (y * width + x) * 4;
      pixel.r[y][x] = I[index];
      pixel.g[y][x] = I[index + 1];
      pixel.b[y][x] = I[index + 2];
      pixel.a[y][x] = I[index + 3] / 255;
    }
  }

  return pixel;
}

/*
function getPixelFromURL(url, callback) {
  getImageDataFromURL(url, function(imageData) {
    getPixelFromImageData(imageData, callback);
  });
}

function getPixel(image, callback) {
  if (typeof(image) === 'string') {
    getPixelFromURL(image, callback);
  } else if (Array.isArray(image.r) === true) {
    callback(image);
  } else {
    getPixelFromImageData(image, callback);
  }
}

function getImageData(image, callback) {
  if (typeof(image) === 'string') {
    getImageDataFromURL(image, callback);
  } else if (Array.isArray(image.r) === true) {
    callback(getImageDataFromPixel(image));
  } else {
    callback(image);
  }
}
*/

function getImageDataFromPixel(pixel) {
  workplace = workplace || createWorkplace();
  var x, y, index,
      width = pixel.r[0].length,
      height = pixel.r.length,
      context = workplace.getContext('2d'),
      imageData = context.createImageData(width, height);

  workplace.width = width;
  workplace.height = height;

  for (y = 0; y < height; y++) {
    for (x = 0; x < width; x++) {
      index = (y * width + x) * 4;
      imageData.data[index]   = pixel.r[y][x];
      imageData.data[index + 1] = pixel.g[y][x];
      imageData.data[index + 2] = pixel.b[y][x];
      imageData.data[index + 3] = Math.round(pixel.a[y][x] * 255);
    }
  }

  return imageData;
}

function getImageFromImageData(imageData) {
  var imageDataContext = imageDataWorkplace.getContext('2d');

  imageDataWorkplace.width = imageData.width;
  imageDataWorkplace.height = imageData.height;
  imageDataContext.putImageData(imageData, 0, 0);

  return imageDataWorkplace;
}

grid.open = function(image, callback) {
  if (typeof(image) === 'string') {
    grid.getImageObjectFromURL(image, callback);
  } else if (Array.isArray(image.r) === true) {
    callback(grid.getImageObjectFromPixel(image));
  } else if (typeof(image) === 'object') {
    callback(grid.getImageObjectFromImageData(image));
  }
};

grid.getImageObject = grid.open;

grid.getImageObjectFromURL = function(url, callback) {
  getImageDataFromURL(url, function(imageData) {
    var imageObject = new ImageObject();
    imageObject.imageData = imageData;
    imageObject.pixel = getPixelFromImageData(imageData);
    imageObject.width = imageData.width;
    imageObject.height = imageData.height;

    callback(imageObject);
  });
};

grid.getImageObjectFromImageData = function(imageData) {
  var width = imageData.width,
      height = imageData.height,
      pixel = getPixelFromImageData(imageData),
      imageObject = new ImageObject();

  imageObject.pixel = pixel;
  imageObject.imageData = imageData;
  imageObject.height = height;
  imageObject.width = width;

  return imageObject;
};

grid.getImageObjectFromPixel = function(pixel) {
  var width = pixel[0].length,
      height = pixel.length,
      imageData = getImageDataFromPixel(pixel),
      imageObject = new ImageObject();

    imageObject.pixel = pixel;
    imageObject.imageData = imageData;
    imageObject.height = height;
    imageObject.width = width;

    return imageObject;
};

ImageObject.prototype.grayscale = function() {
  var x, y, gray,
      imageObject = this,
      width = imageObject.width,
      height = imageObject.height,
      grayImageObject = new ImageObject(),
      pixel = {
        'r' : [],
        'g' : [],
        'b' : [],
        'a' : []
      };

  for (y = 0; y < height; y++) {
    pixel.r[y] = [];
    pixel.g[y] = [];
    pixel.b[y] = [];
    pixel.a[y] = [];
    for (x = 0; x < width; x++) {
      gray = 0.299 * imageObject.pixel.r[y][x] +
             0.587 * imageObject.pixel.g[y][x] +
             0.114 * imageObject.pixel.b[y][x];
      pixel.r[y][x] = pixel.g[y][x] = pixel.b[y][x] = gray;
      pixel.a[y][x] = imageObject.pixel.a[y][x];
    }
  }

  grayImageObject.pixel = pixel;
  grayImageObject.imageData = getImageDataFromPixel(pixel);
  grayImageObject.height = height;
  grayImageObject.width = width;

  return grayImageObject;
};

ImageObject.prototype.putImage = function(canvas) {
  var context,
      imageObject = this;

  canvas.width = imageObject.width;
  canvas.height = imageObject.height;
  context = canvas.getContext('2d');

  context.putImageData(imageObject.imageData, 0, 0);

  return imageObject;
};

ImageObject.prototype.blend = function(srcImageObject, offsetX, offsetY) {
  var x, y,
      imageObject = this,
      width = imageObject.width,
      height = imageObject.height,
      srcWidth = srcImageObject.width,
      srcHeight = srcImageObject.height,
      pixel = {
        'r' : [],
        'g' : [],
        'b' : [],
        'a' : []
      };

  offsetX = isNaN(offsetX) ? 0 : Math.round(offsetX);
  offsetY = isNaN(offsetY) ? 0 : Math.round(offsetY);

  for (y = 0; y < height; y++) {
    pixel.r[y] = [];
    pixel.g[y] = [];
    pixel.b[y] = [];
    pixel.a[y] = [];
    for (x = 0; x < width; x++) {
      pixel.a[y][x] = (y - offsetY < 0 || x - offsetX < 0 ||
              y - offsetY >= srcHeight || x - offsetX >= srcWidth) ?
          imageObject.pixel.a[y][x] :
          (srcImageObject.pixel.a[y - offsetY][x - offsetX] +
              imageObject.pixel.a[y][x] *
              (1 - srcImageObject.pixel.a[y - offsetY][x - offsetX]));

      pixel.r[y][x] = (y - offsetY < 0 || x - offsetX < 0 ||
              y - offsetY >= srcHeight || x - offsetX >= srcWidth || pixel.a[y][x] < 0.003) ?
          imageObject.pixel.r[y][x] :
          (srcImageObject.pixel.r[y - offsetY][x - offsetX] * srcImageObject.pixel.a[y - offsetY][x - offsetX] +
              imageObject.pixel.r[y][x] * imageObject.pixel.a[y][x] *
              (1 - srcImageObject.pixel.a[y - offsetY][x - offsetX])) / pixel.a[y][x];

      pixel.g[y][x] = (y - offsetY < 0 || x - offsetX < 0 ||
              y - offsetY >= srcHeight || x - offsetX >= srcWidth || pixel.a[y][x] < 0.003) ?
          imageObject.pixel.g[y][x] :
          (srcImageObject.pixel.g[y - offsetY][x - offsetX] * srcImageObject.pixel.a[y - offsetY][x - offsetX] +
              imageObject.pixel.g[y][x] * imageObject.pixel.a[y][x] *
              (1 - srcImageObject.pixel.a[y - offsetY][x - offsetX])) / pixel.a[y][x];

      pixel.b[y][x] = (y - offsetY < 0 || x - offsetX < 0 ||
              y - offsetY >= srcHeight || x - offsetX >= srcWidth || pixel.a[y][x] < 0.003) ?
          imageObject.pixel.b[y][x] :
          (srcImageObject.pixel.b[y - offsetY][x - offsetX] * srcImageObject.pixel.a[y - offsetY][x - offsetX] +
              imageObject.pixel.b[y][x] * imageObject.pixel.a[y][x] *
              (1 - srcImageObject.pixel.a[y - offsetY][x - offsetX])) / pixel.a[y][x];

      pixel.r[y][x] = Math.round(pixel.r[y][x]);
      pixel.g[y][x] = Math.round(pixel.g[y][x]);
      pixel.b[y][x] = Math.round(pixel.b[y][x]);

      if (pixel.a[y][x] < 0.003) {
        pixel.a[y][x] = imageObject.pixel.a[y][x];
      }
    }
  }

  imageObject.width = width;
  imageObject.height = height;
  imageObject.pixel = pixel;
  imageObject.imageData = getImageDataFromPixel(pixel);

  return imageObject;
};

ImageObject.prototype.copy = function() {
  var x, y,
      imageObject = this,
      width = imageObject.width,
      height = imageObject.height,
      newImageObject = new ImageObject(),
      pixel = {
        'r' : [],
        'g' : [],
        'b' : [],
        'a' : []
      };

  for (y = 0; y < height; y++) {
    pixel.r[y] = [];
    pixel.g[y] = [];
    pixel.b[y] = [];
    pixel.a[y] = [];
    for (x = 0; x < width; x++) {
      pixel.r[y][x] = imageObject.pixel.r[y][x];
      pixel.g[y][x] = imageObject.pixel.g[y][x];
      pixel.b[y][x] = imageObject.pixel.b[y][x];
      pixel.a[y][x] = imageObject.pixel.a[y][x];
    }
  }

  newImageObject.pixel = pixel;
  newImageObject.imageData = getImageDataFromPixel(pixel);
  newImageObject.height = height;
  newImageObject.width = width;

  return newImageObject;
};

ImageObject.prototype.resize = function(newWidth, newHeight) {
  var imageObject = this,
      context = workplace.getContext('2d'),
      image = getImageFromImageData(imageObject.imageData);

  workplace.width = newWidth;
  workplace.height = newHeight;
  context.drawImage(image, 0, 0, newWidth, newHeight);

  imageObject.width = newWidth;
  imageObject.height = newHeight;
  imageObject.imageData = context.getImageData(0, 0, newWidth, newHeight);
  imageObject.pixel = getPixelFromImageData(imageObject.imageData);

  return imageObject;
};

ImageObject.prototype.rotate = function(degree) {
  var imageObject = this,
      width = imageObject.width,
      height = imageObject.height,
      rad = -degree * Math.PI / 180,
      context = workplace.getContext('2d'),
      image = getImageFromImageData(imageObject.imageData),
      rotatedWidth, rotatedHeight;

  rotatedWidth = Math.abs(width * Math.cos(rad)) + Math.abs(height * Math.sin(rad));
  rotatedWidth = Math.ceil(rotatedWidth);
  rotatedHeight = Math.abs(width * Math.sin(rad)) + Math.abs(height * Math.cos(rad));
  rotatedHeight = Math.ceil(rotatedHeight);

  workplace.width = rotatedWidth;
  workplace.height = rotatedHeight;
  context.translate(rotatedWidth / 2, rotatedHeight / 2);
  context.rotate(rad);
  context.translate(-width / 2, -height / 2);
  context.drawImage(image, 0, 0);

  imageObject.width = rotatedWidth;
  imageObject.height = rotatedHeight;
  imageObject.imageData = context.getImageData(0, 0, rotatedWidth, rotatedHeight);
  imageObject.pixel = getPixelFromImageData(imageObject.imageData);

  return imageObject;
};

ImageObject.prototype.crop = function(left, top, cropWidth, cropHeight) {
  var imageObject = this,
      context = workplace.getContext('2d'),
      image = getImageFromImageData(imageObject.imageData);

  workplace.width = cropWidth;
  workplace.height = cropHeight;
  context.drawImage(image, left, top, cropWidth, cropHeight, 0, 0, cropWidth, cropHeight);

  imageObject.width = cropWidth;
  imageObject.height = cropHeight;
  imageObject.imageData = context.getImageData(0, 0, cropWidth, cropHeight);
  imageObject.pixel = getPixelFromImageData(imageObject.imageData);

  return imageObject;
};

ImageObject.prototype.updateImageData = function() {
  var imageObject = this;
  imageObject.imageData = getImageDataFromPixel(imageObject.pixel);

  return imageObject;
};

ImageObject.prototype.updatePixel = function() {
  var imageObject = this;
  imageObject.imageData = getPixelFromImageData(imageObject.imageData);

  return imageObject;
};

ImageObject.prototype.update = ImageObject.prototype.updateImageData;

ImageObject.prototype.paste = function(srcImageObject, left, top) {
  var imageObject = this,
      width = imageObject.width,
      height = imageObject.height,
      context = workplace.getContext('2d');
  left = left || 0;
  top = top || 0;

  workplace.width = width;
  workplace.height = height;
  context.putImageData(imageObject, 0, 0);
  context.putImageData(srcImageObject, left, top);

  imageObject.imageData = context.getImageData(0, 0, width, height);
  imageObject.pixel = getPixelFromImageData(imageObject.imageData);

  return imageObject;
};

ImageObject.prototype.blank = function(width, height) {
  var imageObject = new ImageObject(),
      context = workplace.getContext('2d'),
      imageData = context.createImageData(width, height);

  imageObject.width = width;
  imageObject.height = height;
  imageObject.imageData = imageData;
  imageObject.pixel = getPixelFromImageData(imageData);

  return imageObject;
};

})(window, document);<|endoftext|>


<commit_before>'use strict';

/* eslint-disable func-names */
/* eslint-disable prefer-arrow-callback */

const assert = require('assert');
const supertest = require('supertest');
const Xible = require('..');

const CONFIG_PATH = '~/.xible/config.json';
const xible = new Xible({
  configPath: CONFIG_PATH
});

describe('/api/flows', () => {
  before(function () {
    return xible.init();
  });

  after(function () {
    return xible.close();
  });

  describe('GET /', () => {
    it('should return list of flows', () => {
      return supertest(xible.expressApp)
      .get('/api/flows')
      .expect(200);
    });
  });

  describe('POST /:flowId', () => {
    it('should create new flow', () => {
      return supertest(xible.expressApp)
      .post('/api/flows')
      .send({
        _id: 'new_test_flow',
        nodes: [],
        connectors: []
      })
      .expect(200)
      .expect(res => res.body._id === 'new_test_flow');
    });
  });

  describe('GET /:flowId', () => {
    it('existing should return flow', () => {
      return supertest(xible.expressApp)
      .get('/api/flows/new_test_flow')
      .expect(200)
      .expect(res => res.body._id === 'new_test_flow');
    });
  });

  describe('POST /:flowId/instances', () => {
    it('should create new instance', () => {
      return supertest(xible.expressApp)
      .post('/api/flows/new_test_flow/instances')
      .expect(200);
    });
  });

  describe('POST /:flowId/instances', function () {
    this.timeout(20000);
    it('should create and start new instance', () => {
      return supertest(xible.expressApp)
      .post('/api/flows/new_test_flow/instances')
      .send({ start: true })
      .expect(200);
    });
  });

  describe('DELETE /:flowId', () => {
    it('should delete flow', () => {
      return supertest(xible.expressApp)
      .delete('/api/flows/new_test_flow')
      .expect(200);
    });

    it('should return 404', () => {
      return supertest(xible.expressApp)
      .get('/api/flows/new_test_flow')
      .expect(404);
    });
  });
});<commit_msg>missing break on last line<commit_after>'use strict';

/* eslint-disable func-names */
/* eslint-disable prefer-arrow-callback */

const assert = require('assert');
const supertest = require('supertest');
const Xible = require('..');

const CONFIG_PATH = '~/.xible/config.json';
const xible = new Xible({
  configPath: CONFIG_PATH
});

describe('/api/flows', () => {
  before(function () {
    return xible.init();
  });

  after(function () {
    return xible.close();
  });

  describe('GET /', () => {
    it('should return list of flows', () => {
      return supertest(xible.expressApp)
      .get('/api/flows')
      .expect(200);
    });
  });

  describe('POST /:flowId', () => {
    it('should create new flow', () => {
      return supertest(xible.expressApp)
      .post('/api/flows')
      .send({
        _id: 'new_test_flow',
        nodes: [],
        connectors: []
      })
      .expect(200)
      .expect(res => res.body._id === 'new_test_flow');
    });
  });

  describe('GET /:flowId', () => {
    it('existing should return flow', () => {
      return supertest(xible.expressApp)
      .get('/api/flows/new_test_flow')
      .expect(200)
      .expect(res => res.body._id === 'new_test_flow');
    });
  });

  describe('POST /:flowId/instances', () => {
    it('should create new instance', () => {
      return supertest(xible.expressApp)
      .post('/api/flows/new_test_flow/instances')
      .expect(200);
    });
  });

  describe('POST /:flowId/instances', function () {
    this.timeout(20000);
    it('should create and start new instance', () => {
      return supertest(xible.expressApp)
      .post('/api/flows/new_test_flow/instances')
      .send({ start: true })
      .expect(200);
    });
  });

  describe('DELETE /:flowId', () => {
    it('should delete flow', () => {
      return supertest(xible.expressApp)
      .delete('/api/flows/new_test_flow')
      .expect(200);
    });

    it('should return 404', () => {
      return supertest(xible.expressApp)
      .get('/api/flows/new_test_flow')
      .expect(404);
    });
  });
});
<|endoftext|>


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

console.log(process.argv);

var args = process.argv.slice(2);

var tuppari = new Tuppari({
  host: 'https://api.tuppari.com',
  applicationId: 'your_application_id',
  accessKeyId: 'your_access_key_id',
  accessSecretKey: 'your_access_secret_key'
});

tuppari.on('log', function (eventType) {
  var args = Array.prototype.slice.call(arguments, 1);
  console.log(eventType, args);
});

var channel = tuppari.join('your_channel');
channel.on('log', function (eventType) {
  var args = Array.prototype.slice.call(arguments, 1);
  console.log(eventType, args);
});

channel.send('your_event', args[0], function (err, res, body) {
  if (err) {
    console.error(err);
  }
  console.log(res.statusCode, body);
});
<commit_msg>fix require path<commit_after>var Tuppari = require('../');

console.log(process.argv);

var args = process.argv.slice(2);

var tuppari = new Tuppari({
  host: 'https://api.tuppari.com',
  applicationId: 'your_application_id',
  accessKeyId: 'your_access_key_id',
  accessSecretKey: 'your_access_secret_key'
});

tuppari.on('log', function (eventType) {
  var args = Array.prototype.slice.call(arguments, 1);
  console.log(eventType, args);
});

var channel = tuppari.join('your_channel');
channel.on('log', function (eventType) {
  var args = Array.prototype.slice.call(arguments, 1);
  console.log(eventType, args);
});

channel.send('your_event', args[0], function (err, res, body) {
  if (err) {
    console.error(err);
  }
  console.log(res.statusCode, body);
});
<|endoftext|>


<commit_before>// DiagonalDivider

import React, { PropTypes } from 'react/addons'; // eslint-disable-line no-unused-vars
import styles from './DiagonalDivider.less';
import withStyles from '../../decorators/withStyles';

@withStyles(styles)
export default class DiagonalDivider extends React.Component {
  static propTypes = {
    id: React.PropTypes.string,
    color: React.PropTypes.string
  };

  componentDidMount() {
    let canvas = document.getElementById(this.props.id);

    // Check if the <canvas> element exists and the browser supports <canvas>
    if (canvas && canvas.getContext) {
      let context = canvas.getContext('2d');

      // Make canvas drawings look sharp on high-density ("Retina") screens
      if ('devicePixelRatio' in window) {
        if (window.devicePixelRatio > 1) {
          const devicePixelRatio = window.devicePixelRatio;
          canvas.width = canvas.width * devicePixelRatio;
          canvas.height = canvas.height * devicePixelRatio;

          // Update context for the new device pixel ratio
          context = canvas.getContext('2d');
        }
      }

      context.strokeStyle = this.props.color;
      context.lineWidth = 2;
      context.moveTo(1, 61);
      context.lineTo(13, 1);
      context.stroke();
    }
  }

  render() {
    return (
      <canvas id={this.props.id} className='DiagonalDivider' width='14' height='62'>
      </canvas>
    );
  }
}
<commit_msg>Fix DiagonalDivider scaling when devicePixelRatio > 1<commit_after>// DiagonalDivider

import React, { PropTypes } from 'react/addons'; // eslint-disable-line no-unused-vars
import styles from './DiagonalDivider.less';
import withStyles from '../../decorators/withStyles';

@withStyles(styles)
export default class DiagonalDivider extends React.Component {
  static propTypes = {
    id: React.PropTypes.string,
    color: React.PropTypes.string
  };

  componentDidMount() {
    let canvas = document.getElementById(this.props.id);

    // Check if the <canvas> element exists and the browser supports <canvas>
    if (canvas && canvas.getContext) {
      let context = canvas.getContext('2d');

      // Make canvas drawings look sharp on high-density ("Retina") screens
      let devicePixelRatio = 1;
      if ('devicePixelRatio' in window) {
        if (window.devicePixelRatio > 1) {
          devicePixelRatio = window.devicePixelRatio;
          canvas.width = canvas.width * devicePixelRatio;
          canvas.height = canvas.height * devicePixelRatio;

          // Update context for the new device pixel ratio
          context = canvas.getContext('2d');
        }
      }

      context.strokeStyle = this.props.color;
      context.lineWidth = 2 * devicePixelRatio;
      context.moveTo(1 * devicePixelRatio, 61 * devicePixelRatio);
      context.lineTo(13 * devicePixelRatio, 1 * devicePixelRatio);
      context.stroke();
    }
  }

  render() {
    return (
      <canvas id={this.props.id} className='DiagonalDivider' width='14' height='62'>
      </canvas>
    );
  }
}
<|endoftext|>


<commit_before>const assert = require('assert');

const alphabetSearching = str => {
  let array = str.split('');
  for (let i = 97; i+= 1) {
    if () {
       return false;
    }
  }

  return true;
};

const in1 = "abcdefghijklmnopqrstuvwxyyyy";
const expect1 = "false";
const test1 = alphabetSearching(in1);
assert.strictEqual(test1, expect1, `should be ${expect1}`);
<commit_msg>wip test<commit_after>const assert = require('assert');

const alphabetSearching = str => {
  let array = str.split('');
  for (let i = 97; i <= 122; i+= 1) {
    if (!array.includes(String.fromCharCode(i))) {
       return false;
    }
  }

  return true;
};

const in1 = "abcdefghijklmnopqrstuvwxyyyy";
const expect1 = "false";
const test1 = alphabetSearching(in1);
assert.strictEqual(test1, expect1, `should be ${expect1}`);
<|endoftext|>


<commit_before>import {ElementResizeDetector} from 'widget/elementResizeDetector'
import {ViewportResizeDetector} from 'widget/viewportResizeDetector'
import {Widget} from 'widget/widget'
import {animationFrameScheduler, combineLatest, distinctUntilChanged, filter, fromEvent, interval, map, mapTo, merge, of, scan, switchMap, withLatestFrom} from 'rxjs'
import {compose} from 'compose'
import Hammer from 'hammerjs'
import Portal from 'widget/portal'
import PropTypes from 'prop-types'
import React from 'react'
import _ from 'lodash'
import styles from './slider.module.css'
import withSubscriptions from 'subscription'

const clamp = (value, {min, max}) => Math.max(min, Math.min(max, value))

const lerp = (rate, speed = 1) => (value, target) => value + (target - value) * (rate * speed)

const normalizeLinear = (value, min, max) => {
    const offset = min
    return (value - offset) / (max - offset)
}

const denormalizeLinear = (value, min, max) => {
    const offset = min
    return value * (max - offset) + offset
}

const normalizeLog = (value, min, max) => {
    const offset = min - 1
    return Math.log(value - offset) / Math.log(max - offset)
}

const denormalizeLog = (value, min, max) => {
    const offset = min - 1
    return Math.exp(value * Math.log(max - offset)) + offset
}

const invertNormalized = (value, invert) =>
    invert ? 1 - value : value

const normalize = (value, min, max, scale, invert) =>
    invertNormalized(scale === 'log' ? normalizeLog(value, min, max) : normalizeLinear(value, min, max), invert)

const denormalize = (value, min, max, scale, invert) =>
    scale === 'log'
        ? denormalizeLog(invertNormalized(value, invert), min, max)
        : denormalizeLinear(invertNormalized(value, invert), min, max)

class SliderContainer extends React.Component {
    clickTarget = React.createRef()

    renderTick({position, value, label}) {
        const left = `${Math.trunc(position)}px`
        return (
            <React.Fragment key={value}>

{label}

            </React.Fragment>
        )
    }

    renderAxis() {
        const {ticks} = this.props
        return (

                {ticks.map(tick => this.renderTick(tick))}

        )
    }

    renderClickTarget() {
        return (

        )
    }

    renderDynamics() {
        const {value, width, range, decimals, ticks, snap, minValue, maxValue, invert, onChange} = this.props
        return (
            <SliderDynamics
                value={value}
                minValue={minValue}
                maxValue={maxValue}
                width={width}
                decimals={decimals}
                ticks={ticks}
                snap={snap}
                range={range}
                invert={invert}
                clickTarget={this.clickTarget}
                normalize={value => {
                    const {scale, minValue, maxValue} = this.props
                    return normalize(value, minValue, maxValue, scale, invert)
                }}
                denormalize={value => {
                    const {scale, minValue, maxValue} = this.props
                    return denormalize(value, minValue, maxValue, scale, invert)
                }}
                onChange={onChange}
            />
        )
    }

    render() {
        return (

                {this.renderAxis()}
                {this.renderClickTarget()}
                {this.renderDynamics()}

        )
    }
}

SliderContainer.propTypes = {
    decimals: PropTypes.number,
    denormalize: PropTypes.func,
    info: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.func
    ]),
    maxValue: PropTypes.number,
    minValue: PropTypes.number,
    normalize: PropTypes.func,
    snap: PropTypes.bool,
    ticks: PropTypes.oneOfType([
        PropTypes.number,
        PropTypes.array
    ]),
    value: PropTypes.any,
    width: PropTypes.number,
    onChange: PropTypes.func
}

class _SliderDynamics extends React.Component {
    state = {
        position: null,
        previewPosition: null,
        clickTargetOffset: null,
        dragging: null,
        inhibitInput: null
    }
    handle = React.createRef()

    renderLeftRange() {
        const {position} = this.state
        const {width} = this.props
        return <div className={styles.range} style={{right: `${width - position}px`}}/>
    }

    renderRightRange() {
        const {position} = this.state
        return <div className={styles.range} style={{left: `${position}px`}}/>
    }

    renderRanges() {
        const {range, invert} = this.props
        return (
            <React.Fragment>
                {((range === 'low' && !invert) || (range === 'high' && invert)) ? this.renderLeftRange() : null}
                {((range === 'high' && !invert) || (range === 'low' && invert)) ? this.renderRightRange() : null}
            </React.Fragment>
        )
    }

    renderPreview() {
        const {previewPosition} = this.state
        return previewPosition !== null ? (
            <div className={[styles.cursor, styles.preview].join(' ')} ref={this.preview}
                style={{left: `${previewPosition}px`}}/>
        ) : null
    }

    renderHandle() {
        const {position, dragging} = this.state
        return (
            <div className={[styles.cursor, styles.handle, dragging ? styles.dragging : null].join(' ')}
                ref={this.handle}
                style={{left: `${position}px`}}/>
        )
    }

    renderOverlay() {
        const {dragging} = this.state
        return dragging
            ? (
                <Portal type='global'>

                </Portal>
            ) : null
    }

    renderViewportResizer() {
        return (
            <ViewportResizeDetector onChange={() => this.setClickTargetOffset()}/>
        )
    }

    render() {
        return (
            <React.Fragment>
                {this.renderRanges()}
                {this.renderPreview()}
                {this.renderHandle()}
                {this.renderOverlay()}
                {this.renderViewportResizer()}
            </React.Fragment>
        )
    }

    componentDidMount() {
        this.initialize({
            handleRef: this.handle.current,
            clickableAreaRef: this.props.clickTarget.current
        })
    }

    initialize({handleRef, clickableAreaRef}) {
        const {addSubscription} = this.props

        this.setHandlePositionByValue()

        const handle = new Hammer(handleRef)
        // limit handle movement to horizontal axis
        handle.get('pan').set({
            direction: Hammer.DIRECTION_HORIZONTAL,
            threshold: 1
        })

        const clickableArea = new Hammer(clickableAreaRef, {threshold: 1})

        const mouseMove$ = fromEvent(clickableAreaRef, 'mousemove')
        const mouseLeave$ = fromEvent(clickableAreaRef, 'mouseleave')
        const pan$ = fromEvent(handle, 'panstart panmove panend')
        const panStart$ = pan$.pipe(filter(e => e.type === 'panstart'))
        const panMove$ = pan$.pipe(filter(e => e.type === 'panmove'))
        const panEnd$ = pan$.pipe(filter(e => e.type === 'panend'))
        const animationFrame$ = interval(0, animationFrameScheduler)

        const hoverPosition$ = merge(
            mouseMove$.pipe(
                map(e => e.clientX - this.state.clickTargetOffset)
            ),
            mouseLeave$.pipe(
                mapTo(null)
            )
        )

        // target position by clicking
        const clickPosition$ = fromEvent(clickableArea, 'tap').pipe(
            map(tap => this.snapPosition(tap.center.x - this.state.clickTargetOffset))
        )

        // target position by dragging
        const dragPosition$ = panStart$.pipe(
            switchMap(() => {
                const {position} = this.state
                return merge(
                    panMove$.pipe(
                        map(event => this.clampPosition(position + event.deltaX)),
                        distinctUntilChanged()
                    ),
                    panEnd$.pipe(
                        map(() => this.snapPosition(this.state.previewPosition))
                    )
                )
            })
        )

        const handleDragging$ = merge(
            of(false),
            panStart$.pipe(mapTo(true)),
            panEnd$.pipe(mapTo(false)),
        )

        const targetPosition$ = merge(clickPosition$, dragPosition$).pipe(
            map(position => Math.round(position))
        )

        const handlePosition$ = targetPosition$.pipe(
            withLatestFrom(handleDragging$),
            switchMap(([targetPosition, dragging]) => {
                const {position} = this.state
                return animationFrame$.pipe(
                    map(() => targetPosition),
                    scan(lerp(dragging ? .30 : .15), position),
                    map(position => Math.round(position)),
                    distinctUntilChanged()
                )
            })
        )

        const handleMoving$ = combineLatest(handlePosition$, targetPosition$).pipe(
            map(([currentPosition, targetPosition]) => currentPosition !== targetPosition),
            distinctUntilChanged()
        )

        const previewPosition$ = merge(targetPosition$, hoverPosition$).pipe(
            map(position => position === null ? null : this.snapPosition(position)),
            distinctUntilChanged()
        )

        const inhibitInput$ = handleMoving$.pipe(
            withLatestFrom(handleDragging$),
            map(([dragging, moving]) => dragging || moving)
        )

        const updateInput$ = merge(clickPosition$, panEnd$)

        addSubscription(
            handlePosition$.subscribe(position =>
                this.setHandlePosition(position)
            ),
            previewPosition$.subscribe(previewPosition =>
                this.setPreviewPosition(previewPosition)
            ),
            handleDragging$.subscribe(dragging =>
                this.setDragging(dragging)
            ),
            inhibitInput$.subscribe(inhibit =>
                this.setInhibitInput(inhibit)
            ),
            updateInput$.subscribe(() =>
                this.updateInputValue()
            )
        )
    }

    componentDidUpdate(prevProps) {
        const {inhibitInput} = this.state
        // prevent input from self-interfering during animation
        if (!inhibitInput && !_.isEqual(prevProps, this.props)) {
            this.setHandlePositionByValue()
        }
    }

    toPosition(value) {
        const {normalize, width} = this.props
        return normalize(value) * width
    }

    toValue(position) {
        const {denormalize, width} = this.props
        return denormalize(position / width)
    }

    clampPosition(position) {
        const {width} = this.props
        return Math.round(
            clamp(position, {
                min: 0,
                max: width
            })
        )
    }

    snapPosition(value) {
        const {ticks, snap} = this.props
        if (snap) {
            const closest = _(ticks)
                .map(({position}) => ({position, distance: Math.abs(position - value)}))
                .sortBy('distance')
                .head()
            return closest.position
        } else {
            return value
        }
    }

    setHandlePositionByValue() {
        const {value} = this.props
        this.setHandlePosition(this.toPosition(value))
    }

    setHandlePosition(position) {
        if (position >= 0) {
            position = Math.round(position)
            if (position !== this.state.position) {
                this.setState({position})
            }
        }
    }

    updateInputValue() {
        const {decimals, onChange} = this.props
        const {previewPosition} = this.state
        const value = this.toValue(this.snapPosition(previewPosition))
        const factor = Math.pow(10, decimals)
        const roundedValue = Math.round(value * factor) / factor
        onChange && onChange(roundedValue)
    }

    setPreviewPosition(previewPosition) {
        this.setState({previewPosition})
    }

    setInhibitInput(inhibitInput) {
        this.setState({inhibitInput})
    }

    setDragging(dragging) {
        this.setState({dragging})
    }

    setClickTargetOffset() {
        const {clickTarget} = this.props
        const clickTargetOffset = Math.trunc(clickTarget.current.getBoundingClientRect().left)
        if (this.state.clickTargetOffset !== clickTargetOffset) {
            this.setState({clickTargetOffset})
        }
    }
}

const SliderDynamics = compose(
    _SliderDynamics,
    withSubscriptions()
)

SliderDynamics.propTypes = {
    denormalize: PropTypes.func.isRequired,
    maxValue: PropTypes.number.isRequired,
    minValue: PropTypes.number.isRequired,
    normalize: PropTypes.func.isRequired,
    value: PropTypes.any.isRequired,
    decimals: PropTypes.number,
    invert: PropTypes.bool,
    snap: PropTypes.bool,
    ticks: PropTypes.array,
    width: PropTypes.number,
    onChange: PropTypes.func
}

export class Slider extends React.Component {
    state = {
        width: null,
        ticks: [],
        minValue: null,
        maxValue: null
    }

    static getDerivedStateFromProps(props, state) {
        const mapTicks = ticks =>
            ticks.map((tick, index) => {
                if (_.isObject(tick)) {
                    const value = tick.value || index
                    const label = tick.label || ''
                    return {value, label}
                }
                if (_.isString(tick)) {
                    return {value: index, externalValue: tick, label: tick}
                }
                return {value: tick, externalValue: tick, label: tick}
            })

        const ticks = mapTicks(props.ticks ? props.ticks : [props.minValue, props.maxValue])
        const minValue = props.minValue || ticks.reduce((min, {value}) => Math.min(min, value), null)
        const maxValue = props.maxValue || ticks.reduce((max, {value}) => Math.max(max, value), null)
        return {
            ticks: ticks
                .filter(({value}) => value >= minValue && value <= maxValue)
                .map(tick => ({
                    ...tick,
                    position: state.width * normalize(tick.value, minValue, maxValue, props.scale, props.invert)
                })),
            minValue,
            maxValue
        }
    }

    renderInfo() {
        const {value, info, alignment} = this.props
        const {ticks} = this.state
        const tick = ticks && ticks.find(tick => tick.value === value)
        const label = (tick && tick.label) || value
        return info ? (

                {_.isFunction(info) ? info(label, value) : info}

        ) : null
    }

    renderSlider() {
        const {width} = this.state
        return (

                    <ElementResizeDetector onResize={({width}) => this.setState({width})}/>
                    {width ? this.renderContainer() : null}

        )
    }

    renderContainer() {
        const {value, scale = 'linear', decimals = 0, snap, range = 'left', invert = false, info, onChange} = this.props
        const {ticks, minValue, maxValue, width} = this.state
        return (
            <SliderContainer
                value={value}
                minValue={minValue}
                maxValue={maxValue}
                decimals={decimals}
                ticks={ticks}
                snap={snap}
                range={range}
                scale={scale}
                invert={invert}
                info={info}
                width={width}
                onChange={onChange}
            />
        )

    }

    render() {
        const {label, tooltip, tooltipPlacement, alignment, disabled} = this.props
        return (
            <Widget
                className={styles.wrapper}
                label={label}
                alignment={alignment}
                disabled={disabled}
                tooltip={tooltip}
                tooltipPlacement={tooltipPlacement}>
                {this.renderInfo()}
                {this.renderSlider()}
            </Widget>
        )
    }
}

Slider.propTypes = {
    alignment: PropTypes.oneOf(['left', 'center', 'right']),
    decimals: PropTypes.number,
    disabled: PropTypes.any,
    info: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.func
    ]),
    invert: PropTypes.any,
    label: PropTypes.string,
    maxValue: PropTypes.number,
    minValue: PropTypes.number,
    range: PropTypes.oneOf(['none', 'low', 'high']),
    scale: PropTypes.oneOf(['linear', 'log']),
    snap: PropTypes.any,
    ticks: PropTypes.oneOfType([
        // PropTypes.number,
        PropTypes.array
    ]),
    tooltip: PropTypes.string,
    tooltipPlacement: PropTypes.string,
    value: PropTypes.any,
    onChange: PropTypes.func
}
<commit_msg>Refactoring.<commit_after>import {ElementResizeDetector} from 'widget/elementResizeDetector'
import {ViewportResizeDetector} from 'widget/viewportResizeDetector'
import {Widget} from 'widget/widget'
import {animationFrameScheduler, combineLatest, distinctUntilChanged, filter, fromEvent, interval, map, mapTo, merge, of, scan, switchMap, withLatestFrom} from 'rxjs'
import {compose} from 'compose'
import Hammer from 'hammerjs'
import Portal from 'widget/portal'
import PropTypes from 'prop-types'
import React from 'react'
import _ from 'lodash'
import styles from './slider.module.css'
import withSubscriptions from 'subscription'

const clamp = (value, {min, max}) => Math.max(min, Math.min(max, value))

const lerp = (rate, speed = 1) => (value, target) => value + (target - value) * (rate * speed)

const normalizeLinear = (value, min, max) => {
    const offset = min
    return (value - offset) / (max - offset)
}

const denormalizeLinear = (value, min, max) => {
    const offset = min
    return value * (max - offset) + offset
}

const normalizeLog = (value, min, max) => {
    const offset = min - 1
    return Math.log(value - offset) / Math.log(max - offset)
}

const denormalizeLog = (value, min, max) => {
    const offset = min - 1
    return Math.exp(value * Math.log(max - offset)) + offset
}

const invertNormalized = (value, invert) =>
    invert ? 1 - value : value

const normalize = (value, min, max, scale, invert) =>
    invertNormalized(scale === 'log' ? normalizeLog(value, min, max) : normalizeLinear(value, min, max), invert)

const denormalize = (value, min, max, scale, invert) =>
    scale === 'log'
        ? denormalizeLog(invertNormalized(value, invert), min, max)
        : denormalizeLinear(invertNormalized(value, invert), min, max)

class SliderContainer extends React.Component {
    clickTarget = React.createRef()

    renderTick({position, value, label}) {
        const left = `${Math.trunc(position)}px`
        return (
            <React.Fragment key={value}>

{label}

            </React.Fragment>
        )
    }

    renderAxis() {
        const {ticks} = this.props
        return (

                {ticks.map(tick => this.renderTick(tick))}

        )
    }

    renderClickTarget() {
        return (

        )
    }

    renderDynamics() {
        const {value, width, range, decimals, ticks, snap, minValue, maxValue, invert, onChange} = this.props
        return (
            <SliderDynamics
                value={value}
                minValue={minValue}
                maxValue={maxValue}
                width={width}
                decimals={decimals}
                ticks={ticks}
                snap={snap}
                range={range}
                invert={invert}
                clickTarget={this.clickTarget}
                normalize={value => {
                    const {scale, minValue, maxValue} = this.props
                    return normalize(value, minValue, maxValue, scale, invert)
                }}
                denormalize={value => {
                    const {scale, minValue, maxValue} = this.props
                    return denormalize(value, minValue, maxValue, scale, invert)
                }}
                onChange={onChange}
            />
        )
    }

    render() {
        return (

                {this.renderAxis()}
                {this.renderClickTarget()}
                {this.renderDynamics()}

        )
    }
}

SliderContainer.propTypes = {
    decimals: PropTypes.number,
    denormalize: PropTypes.func,
    info: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.func
    ]),
    maxValue: PropTypes.number,
    minValue: PropTypes.number,
    normalize: PropTypes.func,
    snap: PropTypes.bool,
    ticks: PropTypes.oneOfType([
        PropTypes.number,
        PropTypes.array
    ]),
    value: PropTypes.any,
    width: PropTypes.number,
    onChange: PropTypes.func
}

class _SliderDynamics extends React.Component {
    state = {
        position: null,
        previewPosition: null,
        clickTargetOffset: null,
        dragging: null,
        inhibitInput: null
    }
    handle = React.createRef()

    renderLeftRange() {
        const {position} = this.state
        const {width} = this.props
        return <div className={styles.range} style={{right: `${width - position}px`}}/>
    }

    renderRightRange() {
        const {position} = this.state
        return <div className={styles.range} style={{left: `${position}px`}}/>
    }

    renderRanges() {
        const {range, invert} = this.props
        return (
            <React.Fragment>
                {((range === 'low' && !invert) || (range === 'high' && invert)) ? this.renderLeftRange() : null}
                {((range === 'high' && !invert) || (range === 'low' && invert)) ? this.renderRightRange() : null}
            </React.Fragment>
        )
    }

    renderPreview() {
        const {previewPosition} = this.state
        return previewPosition !== null ? (
            <div className={[styles.cursor, styles.preview].join(' ')} ref={this.preview}
                style={{left: `${previewPosition}px`}}/>
        ) : null
    }

    renderHandle() {
        const {position, dragging} = this.state
        return (
            <div className={[styles.cursor, styles.handle, dragging ? styles.dragging : null].join(' ')}
                ref={this.handle}
                style={{left: `${position}px`}}/>
        )
    }

    renderOverlay() {
        const {dragging} = this.state
        return dragging
            ? (
                <Portal type='global'>

                </Portal>
            ) : null
    }

    renderViewportResizer() {
        return (
            <ViewportResizeDetector onChange={() => this.setClickTargetOffset()}/>
        )
    }

    render() {
        return (
            <React.Fragment>
                {this.renderRanges()}
                {this.renderPreview()}
                {this.renderHandle()}
                {this.renderOverlay()}
                {this.renderViewportResizer()}
            </React.Fragment>
        )
    }

    componentDidMount() {
        this.initialize({
            handleElement: this.handle.current,
            clickTargetElement: this.props.clickTarget.current
        })
    }

    initialize({handleElement, clickTargetElement}) {
        const {addSubscription} = this.props

        this.setHandlePositionByValue()

        const handle = new Hammer(handleElement)
        // limit handle movement to horizontal axis
        handle.get('pan').set({
            direction: Hammer.DIRECTION_HORIZONTAL,
            threshold: 1
        })

        const clickableArea = new Hammer(clickTargetElement, {threshold: 1})

        const mouseMove$ = fromEvent(clickTargetElement, 'mousemove')
        const mouseLeave$ = fromEvent(clickTargetElement, 'mouseleave')
        const pan$ = fromEvent(handle, 'panstart panmove panend')
        const panStart$ = pan$.pipe(filter(e => e.type === 'panstart'))
        const panMove$ = pan$.pipe(filter(e => e.type === 'panmove'))
        const panEnd$ = pan$.pipe(filter(e => e.type === 'panend'))
        const animationFrame$ = interval(0, animationFrameScheduler)

        const hoverPosition$ = merge(
            mouseMove$.pipe(
                map(e => e.clientX - this.state.clickTargetOffset)
            ),
            mouseLeave$.pipe(
                mapTo(null)
            )
        )

        // target position by clicking
        const clickPosition$ = fromEvent(clickableArea, 'tap').pipe(
            map(tap => this.snapPosition(tap.center.x - this.state.clickTargetOffset))
        )

        // target position by dragging
        const dragPosition$ = panStart$.pipe(
            switchMap(() => {
                const {position} = this.state
                return merge(
                    panMove$.pipe(
                        map(event => this.clampPosition(position + event.deltaX)),
                        distinctUntilChanged()
                    ),
                    panEnd$.pipe(
                        map(() => this.snapPosition(this.state.previewPosition))
                    )
                )
            })
        )

        const handleDragging$ = merge(
            of(false),
            panStart$.pipe(mapTo(true)),
            panEnd$.pipe(mapTo(false)),
        )

        const targetPosition$ = merge(clickPosition$, dragPosition$).pipe(
            map(position => Math.round(position))
        )

        const handlePosition$ = targetPosition$.pipe(
            withLatestFrom(handleDragging$),
            switchMap(([targetPosition, dragging]) => {
                const {position} = this.state
                return animationFrame$.pipe(
                    map(() => targetPosition),
                    scan(lerp(dragging ? .30 : .15), position),
                    map(position => Math.round(position)),
                    distinctUntilChanged()
                )
            })
        )

        const handleMoving$ = combineLatest(handlePosition$, targetPosition$).pipe(
            map(([currentPosition, targetPosition]) => currentPosition !== targetPosition),
            distinctUntilChanged()
        )

        const previewPosition$ = merge(targetPosition$, hoverPosition$).pipe(
            map(position => position === null ? null : this.snapPosition(position)),
            distinctUntilChanged()
        )

        const inhibitInput$ = handleMoving$.pipe(
            withLatestFrom(handleDragging$),
            map(([dragging, moving]) => dragging || moving)
        )

        const updateInput$ = merge(clickPosition$, panEnd$)

        addSubscription(
            handlePosition$.subscribe(position =>
                this.setHandlePosition(position)
            ),
            previewPosition$.subscribe(previewPosition =>
                this.setPreviewPosition(previewPosition)
            ),
            handleDragging$.subscribe(dragging =>
                this.setDragging(dragging)
            ),
            inhibitInput$.subscribe(inhibit =>
                this.setInhibitInput(inhibit)
            ),
            updateInput$.subscribe(() =>
                this.updateInputValue()
            )
        )
    }

    componentDidUpdate(prevProps) {
        const {inhibitInput} = this.state
        // prevent input from self-interfering during animation
        if (!inhibitInput && !_.isEqual(prevProps, this.props)) {
            this.setHandlePositionByValue()
        }
    }

    toPosition(value) {
        const {normalize, width} = this.props
        return normalize(value) * width
    }

    toValue(position) {
        const {denormalize, width} = this.props
        return denormalize(position / width)
    }

    clampPosition(position) {
        const {width} = this.props
        return Math.round(
            clamp(position, {
                min: 0,
                max: width
            })
        )
    }

    snapPosition(value) {
        const {ticks, snap} = this.props
        if (snap) {
            const closest = _(ticks)
                .map(({position}) => ({position, distance: Math.abs(position - value)}))
                .sortBy('distance')
                .head()
            return closest.position
        } else {
            return value
        }
    }

    setHandlePositionByValue() {
        const {value} = this.props
        this.setHandlePosition(this.toPosition(value))
    }

    setHandlePosition(position) {
        if (position >= 0) {
            position = Math.round(position)
            if (position !== this.state.position) {
                this.setState({position})
            }
        }
    }

    updateInputValue() {
        const {decimals, onChange} = this.props
        const {previewPosition} = this.state
        const value = this.toValue(this.snapPosition(previewPosition))
        const factor = Math.pow(10, decimals)
        const roundedValue = Math.round(value * factor) / factor
        onChange && onChange(roundedValue)
    }

    setPreviewPosition(previewPosition) {
        this.setState({previewPosition})
    }

    setInhibitInput(inhibitInput) {
        this.setState({inhibitInput})
    }

    setDragging(dragging) {
        this.setState({dragging})
    }

    setClickTargetOffset() {
        const {clickTarget} = this.props
        const clickTargetOffset = Math.trunc(clickTarget.current.getBoundingClientRect().left)
        if (this.state.clickTargetOffset !== clickTargetOffset) {
            this.setState({clickTargetOffset})
        }
    }
}

const SliderDynamics = compose(
    _SliderDynamics,
    withSubscriptions()
)

SliderDynamics.propTypes = {
    denormalize: PropTypes.func.isRequired,
    maxValue: PropTypes.number.isRequired,
    minValue: PropTypes.number.isRequired,
    normalize: PropTypes.func.isRequired,
    value: PropTypes.any.isRequired,
    decimals: PropTypes.number,
    invert: PropTypes.bool,
    snap: PropTypes.bool,
    ticks: PropTypes.array,
    width: PropTypes.number,
    onChange: PropTypes.func
}

export class Slider extends React.Component {
    state = {
        width: null,
        ticks: [],
        minValue: null,
        maxValue: null
    }

    static getDerivedStateFromProps(props, state) {
        const mapTicks = ticks =>
            ticks.map((tick, index) => {
                if (_.isObject(tick)) {
                    const value = tick.value || index
                    const label = tick.label || ''
                    return {value, label}
                }
                if (_.isString(tick)) {
                    return {value: index, externalValue: tick, label: tick}
                }
                return {value: tick, externalValue: tick, label: tick}
            })

        const ticks = mapTicks(props.ticks ? props.ticks : [props.minValue, props.maxValue])
        const minValue = props.minValue || ticks.reduce((min, {value}) => Math.min(min, value), null)
        const maxValue = props.maxValue || ticks.reduce((max, {value}) => Math.max(max, value), null)
        return {
            ticks: ticks
                .filter(({value}) => value >= minValue && value <= maxValue)
                .map(tick => ({
                    ...tick,
                    position: state.width * normalize(tick.value, minValue, maxValue, props.scale, props.invert)
                })),
            minValue,
            maxValue
        }
    }

    renderInfo() {
        const {value, info, alignment} = this.props
        const {ticks} = this.state
        const tick = ticks && ticks.find(tick => tick.value === value)
        const label = (tick && tick.label) || value
        return info ? (

                {_.isFunction(info) ? info(label, value) : info}

        ) : null
    }

    renderSlider() {
        const {width} = this.state
        return (

                    <ElementResizeDetector onResize={({width}) => this.setState({width})}/>
                    {width ? this.renderContainer() : null}

        )
    }

    renderContainer() {
        const {value, scale = 'linear', decimals = 0, snap, range = 'left', invert = false, info, onChange} = this.props
        const {ticks, minValue, maxValue, width} = this.state
        return (
            <SliderContainer
                value={value}
                minValue={minValue}
                maxValue={maxValue}
                decimals={decimals}
                ticks={ticks}
                snap={snap}
                range={range}
                scale={scale}
                invert={invert}
                info={info}
                width={width}
                onChange={onChange}
            />
        )

    }

    render() {
        const {label, tooltip, tooltipPlacement, alignment, disabled} = this.props
        return (
            <Widget
                className={styles.wrapper}
                label={label}
                alignment={alignment}
                disabled={disabled}
                tooltip={tooltip}
                tooltipPlacement={tooltipPlacement}>
                {this.renderInfo()}
                {this.renderSlider()}
            </Widget>
        )
    }
}

Slider.propTypes = {
    alignment: PropTypes.oneOf(['left', 'center', 'right']),
    decimals: PropTypes.number,
    disabled: PropTypes.any,
    info: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.func
    ]),
    invert: PropTypes.any,
    label: PropTypes.string,
    maxValue: PropTypes.number,
    minValue: PropTypes.number,
    range: PropTypes.oneOf(['none', 'low', 'high']),
    scale: PropTypes.oneOf(['linear', 'log']),
    snap: PropTypes.any,
    ticks: PropTypes.oneOfType([
        // PropTypes.number,
        PropTypes.array
    ]),
    tooltip: PropTypes.string,
    tooltipPlacement: PropTypes.string,
    value: PropTypes.any,
    onChange: PropTypes.func
}
<|endoftext|>


<commit_before>var assert = require('assert');
var path = require('path');
var fs = require('fs');
var muk = require('muk');

var _http = require('../_http.js');

var thinkjs = require('../../lib/index.js');

var tjs = new thinkjs();
tjs.load();

var Base = think.safeRequire(path.resolve(__dirname, '../../lib/core/http_base.js'));

var list = ['init', 'invoke', 'config', 'action', 'cache', 'hook', 'model', 'controller', 'service'];

describe('core/http_base.js', function(){
  it('Base is function', function(){
    assert.equal(typeof Base, 'function')
  })
  list.forEach(function(item){
    it(item + ' is function', function(){
      var instance = new Base({});
      assert.equal(typeof instance[item], 'function');
    })
  })
  it('get cache', function(done){
    var instance = new Base({});
    instance.cache('xxx', undefined, {type: 'memory'}).then(function(data){
      assert.equal(data, undefined)
      done();
    }).catch(function(err){
      console.log(err.stack)
    })
  })
  it('exec hook', function(done){
    var instance = new Base({res: {}, req: {}});
    instance.hook('testdd', {}).then(function(data){
      assert.deepEqual(data, {})
      done();
    })
  })
  it('service', function(){
    var instance = new Base({res: {}, req: {}});
    var cls = instance.service('fasdfasdfasfww', {});
    assert.equal(think.isFunction(cls), true)
  })
  it('controller not found', function(){
    var instance = new Base({res: {}, req: {}, view: function(){}});
    try{
      var cins = instance.controller('testddd');
      assert.equal(1, 2)
    }catch(e){

    }
  })
  it('model', function(){
    var instance = new Base({res: {}, req: {}, view: function(){}, module: 'home'});
    var model = instance.model('user');
    assert.equal(think.isObject(model), true)
  })
  it('model, empty', function(){
    var instance = new Base({res: {}, req: {}, view: function(){}, module: 'home'});
    var model = instance.model();
    assert.equal(think.isObject(model), true)
  })
  it('model, user', function(){
    var instance = new Base({res: {}, req: {}, view: function(){}, module: 'home'});
    var model = instance.model('user', {});
    assert.equal(think.isObject(model), true)
  })
  it('action, controller not found', function(){
    var instance = new Base({res: {}, req: {}, view: function(){}, module: 'home'});
    try{instance.action('user', 'test');
      assert.equal(1, 2)
    }catch(e){}
  })
  it('action, test', function(){
    var instance = new Base({res: {}, req: {}, view: function(){}, module: 'home'});
    instance.action({
      invoke: function(action){
        assert.equal(action, 'testAction')
      }
    }, 'test')
  })
  it('action, test_add', function(){
    var instance = new Base({res: {}, req: {}, view: function(){}, module: 'home'});
    instance.action({
      invoke: function(action){
        assert.equal(action, 'testAddAction')
      }
    }, 'test_add')
  })
  it('action, __call', function(){
    var instance = new Base({res: {}, req: {}, view: function(){}, module: 'home'});
    instance.action({
      invoke: function(action){
        assert.equal(action, '__call')
      }
    }, '__call')
  })
})<commit_msg>fix test error<commit_after>var assert = require('assert');
var path = require('path');
var fs = require('fs');
var muk = require('muk');

var _http = require('../_http.js');

var thinkjs = require('../../lib/index.js');

var tjs = new thinkjs();
tjs.load();

var Base = think.require(path.resolve(__dirname, '../../lib/core/http_base.js'));

var list = ['init', 'invoke', 'config', 'action', 'cache', 'hook', 'model', 'controller', 'service'];

describe('core/http_base.js', function(){
  it('Base is function', function(){
    assert.equal(typeof Base, 'function')
  })
  list.forEach(function(item){
    it(item + ' is function', function(){
      var instance = new Base({});
      assert.equal(typeof instance[item], 'function');
    })
  })
  it('get cache', function(done){
    var instance = new Base({});
    instance.cache('xxx', undefined, {type: 'memory'}).then(function(data){
      assert.equal(data, undefined)
      done();
    }).catch(function(err){
      console.log(err.stack)
    })
  })
  it('exec hook', function(done){
    var instance = new Base({res: {}, req: {}});
    instance.hook('testdd', {}).then(function(data){
      assert.deepEqual(data, {})
      done();
    })
  })
  it('service', function(){
    var instance = new Base({res: {}, req: {}});
    var cls = instance.service('fasdfasdfasfww', {});
    assert.equal(think.isFunction(cls), true)
  })
  it('controller not found', function(){
    var instance = new Base({res: {}, req: {}, view: function(){}});
    try{
      var cins = instance.controller('testddd');
      assert.equal(1, 2);
    }catch(e){

    }
  })
  it('model', function(){
    var instance = new Base({res: {}, req: {}, view: function(){}, module: 'home'});
    var model = instance.model('user');
    assert.equal(think.isObject(model), true)
  })
  it('model, empty', function(){
    var instance = new Base({res: {}, req: {}, view: function(){}, module: 'home'});
    var model = instance.model();
    assert.equal(think.isObject(model), true)
  })
  it('model, user', function(){
    var instance = new Base({res: {}, req: {}, view: function(){}, module: 'home'});
    var model = instance.model('user', {});
    assert.equal(think.isObject(model), true)
  })
  it('action, controller not found', function(){
    var instance = new Base({res: {}, req: {}, view: function(){}, module: 'home'});
    try{
      instance.action('user', 'test').catch(function(){});
      assert.equal(1, 2);
    }catch(e){}
  })
  it('action, test', function(done){
    var instance = new Base({res: {}, req: {}, view: function(){}, module: 'home'});
    instance.action({
      __filename: __filename,
      invoke: function(action){
        assert.equal(action, 'testAction');
        done();
        return Promise.resolve();
      }
    }, 'test')
  })
  it('action, test_add', function(done){
    var instance = new Base({res: {}, req: {}, view: function(){}, module: 'home'});
    instance.action({
      __filename: __dirname,
      invoke: function(action){
        assert.equal(action, 'testAddAction');
        done();
        return Promise.resolve();
      }
    }, 'test_add')
  })
  it('action, __call', function(done){
    var instance = new Base({res: {}, req: {}, view: function(){}, module: 'home'});
    instance.action({
      __filename: __filename,
      invoke: function(action){
        assert.equal(action, '__call');
        done();
        return Promise.resolve();
      }
    }, '__call')
  })
})<|endoftext|>


<commit_before>/**
 * ownCloud - Mail
 *
 * This file is licensed under the Affero General Public License version 3 or
 * later. See the COPYING file.
 *
 * @author Christoph Wurst <christoph@winzerhof-wurst.at>
 * @copyright Christoph Wurst 2016
 */

define(function(require) {
	'use strict';

	var $ = require('jquery');
	var FolderController = require('controller/foldercontroller');
	var Radio = require('radio');
	var UPDATE_INTERVAL = 5 * 60 * 1000; // 5 minutes

	Radio.account.on('load', loadAccounts);

	function startBackgroundChecks(accounts) {
		setInterval(function() {
			require('background').checkForNotifications(accounts);
		}, UPDATE_INTERVAL);
	}

	/**
	 * Load all accounts
	 *
	 * @returns {Promise}
	 */
	function loadAccounts() {
		var defer = $.Deferred();
		var fetchingAccounts = Radio.account.request('entities');

		$.when(fetchingAccounts).done(function(accounts) {
			if (accounts.length === 0) {
				addAccount();
			} else {
				var loadingAccounts = accounts.map(function(account) {
					return FolderController.loadFolder(account);
				});
				$.when.apply($, loadingAccounts).done(function() {
					defer.resolve(accounts);
				});
			}

			startBackgroundChecks(accounts);
		});
		$.when(fetchingAccounts).fail(function() {
			Radio.ui.trigger('error:show', t('mail', 'Error while loading the accounts.'));
		});

		return defer.promise();
	}

	return {
		loadAccounts: loadAccounts
	};
});
<commit_msg>Resolve accounts loading promise in all cases<commit_after>/**
 * ownCloud - Mail
 *
 * This file is licensed under the Affero General Public License version 3 or
 * later. See the COPYING file.
 *
 * @author Christoph Wurst <christoph@winzerhof-wurst.at>
 * @copyright Christoph Wurst 2016
 */

define(function(require) {
	'use strict';

	var $ = require('jquery');
	var FolderController = require('controller/foldercontroller');
	var Radio = require('radio');
	var UPDATE_INTERVAL = 5 * 60 * 1000; // 5 minutes

	Radio.account.on('load', loadAccounts);

	function startBackgroundChecks(accounts) {
		setInterval(function() {
			require('background').checkForNotifications(accounts);
		}, UPDATE_INTERVAL);
	}

	/**
	 * Load all accounts
	 *
	 * @returns {Promise}
	 */
	function loadAccounts() {
		var defer = $.Deferred();
		var fetchingAccounts = Radio.account.request('entities');

		$.when(fetchingAccounts).done(function(accounts) {
			if (accounts.length === 0) {
				defer.resolve(accounts);
				Radio.navigation.trigger('setup');
			} else {
				var loadingAccounts = accounts.map(function(account) {
					return FolderController.loadFolder(account);
				});
				$.when.apply($, loadingAccounts).done(function() {
					defer.resolve(accounts);
				});
			}

			startBackgroundChecks(accounts);
		});
		$.when(fetchingAccounts).fail(function() {
			Radio.ui.trigger('error:show', t('mail', 'Error while loading the accounts.'));
		});

		return defer.promise();
	}

	return {
		loadAccounts: loadAccounts
	};
});
<|endoftext|>