<commit_before>/* globals dom file KellyColorPicker palettes */

// Initialize
const canvas = document.querySelector('#canvas');
canvas.setAttribute('width', document.body.clientWidth + 'px');
canvas.setAttribute('height', document.body.clientHeight + 'px');
const colorpaletteselect = document.querySelector('.colorpalette');
palettes.forEach((p,i) => {
  let opt = document.createElement('option');
  opt.setAttribute('value', i);
  opt.innerText = p.name;
  colorpaletteselect.append(opt);
});
colorpaletteselect.addEventListener('change', setPalette);
// Color picker
const colorpicker = new KellyColorPicker(
  {
    place : document.querySelector('.popup-colour'),
    input : '.js-colour',
    size : 200,
    color : '#ffffff',
    method : 'square',
    input_color : false, // or inputColor (sice v1.15)
    input_format : 'mixed', // or inputFormat (since v1.15)
    alpha : 1,
    alpha_slider : false, // or alphaSlider (since v1.15)
    colorSaver : false,
    resizeWith : true, // auto redraw canvas on resize window
    popupClass: 'popup-colour',
    userEvents : {
      // change : function(self) {
      //   // set background color for 'input' to current color of color picker
      //   if(self.getCurColorHsv().v < 0.5){
      //   self.getInput().style.color = "#FFF";
      // } else {
      //   self.getInput().style.color = "#000";
      // }
      // self.getInput().style.background = self.getCurColorHex();
    // }
  }
  });
setPalette({target: colorpaletteselect});

const mouse = {};

function setPalette(evt){
  let palette = palettes[parseInt(evt.target.value)];
  let wells = document.querySelectorAll('.js-miniwell');
  for (let i = 0; i < 5; i++){
    colorButton(wells[i], '#' + palette.colors[i]);
  }
}

class Pen{

}

class Pan{

}

class Rotate{

}

class ZoomIn{

}

class ZoomOut{

}

let tools = {
  pen: new Pen(canvas),
  pan: new Pan(canvas),
  rotate: new Rotate(canvas),
  zoomin: new ZoomIn(canvas),
  zoomout: new ZoomOut(canvas)
}

let currentTool = tools.pen;
let currentStrokeWidth = 1;
let currentDoOnionskin = true;

function selectTool(button){
  let name = button.getAttribute('title').toLowerCase();
  document.querySelector('.js-tool.active').classList.remove('active');
  button.classList.add('active');
  switch(name){
    case 'pen': currentTool = tools.pen; break;
    case 'pan': currentTool = tools.pan; break;
    case 'rotate': currentTool = tools.rotate; break;
    case 'zoom in':  currentTool = tools.zoomin; break;
    case 'zoom out': currentTool = tools.zoomout; break;
    default: console.error('unrecognized tool name: %s', name);
  }
}

let currentColor = '#000000';
let currentFrameDelay = 30; // milliseconds

function setFrameRate(input){
  currentFrameDelay = Math.floor(1000 / Number(input.value));
}

function colorPopup(input){
  let popup = document.querySelector('.popup-colour');
  let colorwell = document.querySelector('.colourwell');
  if (popup.style.display === 'none'){
    colorpicker.setColor(input.value);
    popup.style.display = 'block';
  }else{
    let color = colorpicker.getCurColorHex();
    colorButton(colorwell, color);
    colorButton(input, color);
    currentColor = color;
    popup.style.display = 'none';
  }
}

function colorButton(button, color){
  button.value = color;
  button.style.backgroundColor = color;
  if (hexToValue(color) < 0.5){
    button.style.color = '#FFF';
  }else{
    button.style.color = '#000';
  }
}

function hexToValue(hex){
  return colorpicker.rgbToHsv(colorpicker.hexToRgb(hex)).v;
}

function selectColor(input){
  let popup = document.querySelector('.popup-colour');
  let colorwell = document.querySelector('.colourwell');
  if (popup.style.display === 'block'){
    let color = colorpicker.getCurColorHex();
    colorButton(colorwell, color);
    colorButton(input, color);
    currentColor = color;
    popup.style.display = 'none';
  }else{
    colorButton(colorwell, input.value);
    currentColor = input.value;
  }
}

var drawing = false;
var WIDTH = document.body.clientWidth;
var HEIGHT = document.body.clientHeight;

// Prevent control clicks from passing through to svg
function swallowClicks(evt){
  evt.stopPropagation();
}
document.querySelector('.buttonbar.animation').addEventListener('mousedown', swallowClicks);
document.querySelector('.buttonbar.tools').addEventListener('mousedown', swallowClicks);
document.querySelector('.buttonbar.animation').addEventListener('touchstart', swallowClicks);
document.querySelector('.buttonbar.tools').addEventListener('touchstart', swallowClicks);

function inBounds(x,y){
  return !(x < 0 || x > WIDTH || y < 0 || y > HEIGHT);
}

function getXY(evt){
   if (evt.cancelable) {
      evt.preventDefault();
    }

    const rect = this.canvas.getBoundingClientRect();
    const position = evt.changedTouches && evt.changedTouches[0] || evt;
    let x = position.offsetX;
    let y = position.offsetY;

    if (typeof x === 'undefined') {
      x = position.clientX - rect.left;
    }
    if (typeof y === 'undefined') {
      y = position.clientY - rect.top;
    }
    return {x,y};
}

const startDrawing = evt => {
  let {x,y} = getXY(evt);
  startPath(x,y);
  drawing = true;
};

const draw = evt => {
  if (!drawing) return;
  let {x,y} = getXY(evt);
  if (inBounds(x,y)){
      appendToPath(x,y);
  }
};

const stopDrawing = evt => {
  let {x,y} = getXY(evt);
  if (currentPath){
    dom.simplifyPath(currentPath);
    currentPath = null;
  }
  drawing = false;
}

const toolStart = evt =>
const cancelTool = evt => currentTool.cancel()

document.body.addEventListener('mousedown', startDrawing);
document.body.addEventListener('touchstart', startDrawing);
document.body.addEventListener('mousemove', draw);
document.body.addEventListener('touchmove', draw);
document.body.addEventListener('touchend', stopDrawing);
document.body.addEventListener('mouseup', stopDrawing);
document.body.addEventListener('touchcancel', cancelMove)

function currentFrame(){
  return document.querySelector('.frame.selected');
}

function playingFrame(){
  return document.querySelector('.frame.play-frame');
}

var currentPath = null;

function startPath(x,y){

  currentPath = currentFrame().appendChild(dom.svg('path', {
      d: 'M ' + x + ',' + y,
      stroke: currentColor,
      'stroke-width': currentStrokeWidth
  }));
  file.onChange();
}

function appendToPath(x,y){
  var path = document.querySelector('.selected path:last-child');
  var d = path.getAttribute('d');
  path.setAttribute('d', `${d} L${x} ${y}`);
}

/***************************************
*
*  MANAGE FRAMES
*
***************************************/

function isOnionskinOn(){
  return currentDoOnionskin;
}

function currentOnionskinFrame(){
  return document.querySelector('.frame.onionskin');
}

function updateOnionskin(){
  if (!isOnionskinOn()) return;
  dom.removeClass(currentOnionskinFrame(), 'onionskin');
  dom.addClass(currentFrame().previousElementSibling, 'onionskin');
}

function addFrame(){
  dom.insertAfter(dom.svg('g', {'class': 'frame selected'}), currentFrame());
  currentFrame().classList.remove('selected');
  updateOnionskin();
  updateFrameCount();
  file.onChange();
}

function cloneFrame(){
  dom.insertAfter(currentFrame().cloneNode(true), currentFrame());
  currentFrame().classList.remove('selected');
  updateOnionskin();
  updateFrameCount();
  file.onChange();
}

function deleteFrame(){
  var frameToDelete = currentFrame();
  if (frameToDelete.nextElementSibling){
      incrementFrame();
  }else if (frameToDelete.previousElementSibling){
      decrementFrame();
  }
  if (frameToDelete.parentNode.children.length > 1){
    dom.remove(frameToDelete);
  }else{
    dom.clear(frameToDelete); // don't delete the last frame, just its children
  }
  updateOnionskin();
  updateFrameCount();
  file.onChange();
}

function clear(){
  dom.clear(currentFrame());
}

function toggleOnionskin(){
  if (isOnionskinOn()){
      dom.addClass(currentFrame().previousElementSibling, 'onionskin');
  }else{
      dom.removeClass(currentOnionskinFrame(), 'onionskin');
  }
}

function incrementFrame(){
  var curr = currentFrame();
  if (curr.nextElementSibling){
      curr.classList.remove('selected');
      curr.nextElementSibling.classList.add('selected');
  }
  updateOnionskin();
  updateFrameCount();
}

function decrementFrame(){
  var curr = currentFrame();
  if (curr.previousElementSibling){
      curr.classList.remove('selected');
      curr.previousElementSibling.classList.add('selected');
  }
  updateOnionskin();
  updateFrameCount();
}

function gotoFirstFrame(){
  currentFrame().classList.remove('selected');
  document.querySelector('.frame').classList.add('selected');
  dom.removeClass(currentOnionskinFrame(), 'onionskin');
  updateFrameCount();
}

function gotoLastFrame(){
  currentFrame().classList.remove('selected');
  document.querySelector('.frame:last-child').classList.add('selected');
  dom.removeClass(currentOnionskinFrame(), 'onionskin');
  dom.addClass(currentFrame().previousElementSibling, 'onionskin');
  updateFrameCount();
}

var _lastFrameTime = 0;
var _frameDelay = 0;

function play(){
  document.body.classList.add('playing');
  // turn play button into stop button
  // disable all other controls
  // temporarily turn off onionskin (remember state)
  // start at beginning of document (remember state)
  document.querySelector('.frame').classList.add('play-frame');
  // add SVG SMIL animation
  // Unless looping, call stop() when animation is finished
  // How much of this can I do by adding "playing" class to body?
  setTimeout(function(){
      _frameDelay = currentFrameDelay;
      _lastFrameTime = Date.now();
      requestAnimationFrame(playNextFrame);
  }, 500);
}

function stop(){
  // remove SMIL animation
  // re-enable all controls
  // return to the frame we were on
  // re-enable onionskin if needed
  // turn stop button into play button
  dom.removeClass(playingFrame(), 'play-frame');
  document.body.classList.remove('playing');
}

function playNextFrame(){
  var time = Date.now();
  if ((time - _lastFrameTime) < _frameDelay){
      requestAnimationFrame(playNextFrame);
      return;
  }
  var currFrame = playingFrame();
  _lastFrameTime = time;
  if (currFrame.nextElementSibling){
      currFrame.classList.remove('play-frame');
      currFrame.nextElementSibling.classList.add('play-frame');
      requestAnimationFrame(playNextFrame);
  }else{
      stop();
  }
}

function updateFrameCount(){
  try{
      var frames = currentFrame().parentElement.children.length;
      var index = dom.indexOf(currentFrame());
      document.querySelector('.framecount').textContent = 'Frame ' + (index+1) + ' of ' + frames;
  }catch(e){
      // wait for the file to load, probably
  }
}

function undoLine(){
  dom.remove(currentFrame().lastElementChild);
  file.onChange();
}

function keydownHandler(evt){
  if ((evt.key || evt.keyIdentifier) === 'Control'){
      document.body.classList.add('usefiles');
  }
}

function keyupHandler(evt){
  if ((evt.key || evt.keyIdentifier) === 'Control'){
      document.body.classList.remove('usefiles');
  }
}

window.app = {
  updateFrameCount: updateFrameCount,
  play: play
};

// document.querySelector('#canvas-undo').addEventListener('click', undoLine, false);
// document.querySelector('#canvas-onionskin').addEventListener('change', toggleOnionskin, false);
document.addEventListener('keydown', keydownHandler, false);
document.addEventListener('keyup', keyupHandler, false);

<commit_msg>🚘🎯 Checkpoint ./js/script.js:739936/1609<commit_after>/* globals dom file KellyColorPicker palettes */

// Initialize
const canvas = document.querySelector('#canvas');
canvas.setAttribute('width', document.body.clientWidth + 'px');
canvas.setAttribute('height', document.body.clientHeight + 'px');
const colorpaletteselect = document.querySelector('.colorpalette');
palettes.forEach((p,i) => {
  let opt = document.createElement('option');
  opt.setAttribute('value', i);
  opt.innerText = p.name;
  colorpaletteselect.append(opt);
});
colorpaletteselect.addEventListener('change', setPalette);
// Color picker
const colorpicker = new KellyColorPicker(
  {
    place : document.querySelector('.popup-colour'),
    input : '.js-colour',
    size : 200,
    color : '#ffffff',
    method : 'square',
    input_color : false, // or inputColor (sice v1.15)
    input_format : 'mixed', // or inputFormat (since v1.15)
    alpha : 1,
    alpha_slider : false, // or alphaSlider (since v1.15)
    colorSaver : false,
    resizeWith : true, // auto redraw canvas on resize window
    popupClass: 'popup-colour',
    userEvents : {
      // change : function(self) {
      //   // set background color for 'input' to current color of color picker
      //   if(self.getCurColorHsv().v < 0.5){
      //   self.getInput().style.color = "#FFF";
      // } else {
      //   self.getInput().style.color = "#000";
      // }
      // self.getInput().style.background = self.getCurColorHex();
    // }
  }
  });
setPalette({target: colorpaletteselect});

const mouse = {};

function setPalette(evt){
  let palette = palettes[parseInt(evt.target.value)];
  let wells = document.querySelectorAll('.js-miniwell');
  for (let i = 0; i < 5; i++){
    colorButton(wells[i], '#' + palette.colors[i]);
  }
}

class Pen{
  start(evt){
    let {x,y} = getXY(evt);
    startPath(x,y);
    drawing = true;
  }

  move(evt){
    if (!drawing) return;
    // FIXME: draw a dot if we haven't moved
    let {x,y} = getXY(evt);
    if (inBounds(x,y)){
        appendToPath(x,y);
    }
  }

  const stopDrawing = evt => {
    let {x,y} = getXY(evt);
    if (currentPath){
      dom.simplifyPath(currentPath);
      currentPath = null;
    }
    drawing = false;
  }

}

class Pan{

}

class Rotate{

}

class ZoomIn{

}

class ZoomOut{

}

let tools = {
  pen: new Pen(canvas),
  pan: new Pan(canvas),
  rotate: new Rotate(canvas),
  zoomin: new ZoomIn(canvas),
  zoomout: new ZoomOut(canvas)
}

let currentTool = tools.pen;
let currentStrokeWidth = 1;
let currentDoOnionskin = true;

function selectTool(button){
  let name = button.getAttribute('title').toLowerCase();
  document.querySelector('.js-tool.active').classList.remove('active');
  button.classList.add('active');
  switch(name){
    case 'pen': currentTool = tools.pen; break;
    case 'pan': currentTool = tools.pan; break;
    case 'rotate': currentTool = tools.rotate; break;
    case 'zoom in':  currentTool = tools.zoomin; break;
    case 'zoom out': currentTool = tools.zoomout; break;
    default: console.error('unrecognized tool name: %s', name);
  }
}

let currentColor = '#000000';
let currentFrameDelay = 30; // milliseconds

function setFrameRate(input){
  currentFrameDelay = Math.floor(1000 / Number(input.value));
}

function colorPopup(input){
  let popup = document.querySelector('.popup-colour');
  let colorwell = document.querySelector('.colourwell');
  if (popup.style.display === 'none'){
    colorpicker.setColor(input.value);
    popup.style.display = 'block';
  }else{
    let color = colorpicker.getCurColorHex();
    colorButton(colorwell, color);
    colorButton(input, color);
    currentColor = color;
    popup.style.display = 'none';
  }
}

function colorButton(button, color){
  button.value = color;
  button.style.backgroundColor = color;
  if (hexToValue(color) < 0.5){
    button.style.color = '#FFF';
  }else{
    button.style.color = '#000';
  }
}

function hexToValue(hex){
  return colorpicker.rgbToHsv(colorpicker.hexToRgb(hex)).v;
}

function selectColor(input){
  let popup = document.querySelector('.popup-colour');
  let colorwell = document.querySelector('.colourwell');
  if (popup.style.display === 'block'){
    let color = colorpicker.getCurColorHex();
    colorButton(colorwell, color);
    colorButton(input, color);
    currentColor = color;
    popup.style.display = 'none';
  }else{
    colorButton(colorwell, input.value);
    currentColor = input.value;
  }
}

var drawing = false;
var WIDTH = document.body.clientWidth;
var HEIGHT = document.body.clientHeight;

// Prevent control clicks from passing through to svg
function swallowClicks(evt){
  evt.stopPropagation();
}
document.querySelector('.buttonbar.animation').addEventListener('mousedown', swallowClicks);
document.querySelector('.buttonbar.tools').addEventListener('mousedown', swallowClicks);
document.querySelector('.buttonbar.animation').addEventListener('touchstart', swallowClicks);
document.querySelector('.buttonbar.tools').addEventListener('touchstart', swallowClicks);

function inBounds(x,y){
  return !(x < 0 || x > WIDTH || y < 0 || y > HEIGHT);
}

function getXY(evt){
   if (evt.cancelable) {
      evt.preventDefault();
    }

    const rect = this.canvas.getBoundingClientRect();
    const position = evt.changedTouches && evt.changedTouches[0] || evt;
    let x = position.offsetX;
    let y = position.offsetY;

    if (typeof x === 'undefined') {
      x = position.clientX - rect.left;
    }
    if (typeof y === 'undefined') {
      y = position.clientY - rect.top;
    }
    return {x,y};
}

const toolStart = evt => currentTool.start(evt);
const toolMove = evt => currentTool.move(evt);
const toolStop = evt => currentTool.stop(evt);
const toolCancel = evt => currentTool.cancel();
const escCancel = evt => {
  if (evt.code && evt.code === 'Escape'){
    currentTool.cancel();
  }
}

document.body.addEventListener('mousedown', toolStart);
document.body.addEventListener('touchstart', toolStart);
document.body.addEventListener('mousemove', toolMove);
document.body.addEventListener('touchmove', toolMove);
document.body.addEventListener('touchend', toolStop);
document.body.addEventListener('mouseup', toolStop);
document.body.addEventListener('touchcancel', toolCancel);
document.body.addEventListener('keydown', escCancel);

function currentFrame(){
  return document.querySelector('.frame.selected');
}

function playingFrame(){
  return document.querySelector('.frame.play-frame');
}

var currentPath = null;

function startPath(x,y){

  currentPath = currentFrame().appendChild(dom.svg('path', {
      d: 'M ' + x + ',' + y,
      stroke: currentColor,
      'stroke-width': currentStrokeWidth
  }));
  file.onChange();
}

function appendToPath(x,y){
  var path = document.querySelector('.selected path:last-child');
  var d = path.getAttribute('d');
  path.setAttribute('d', `${d} L${x} ${y}`);
}

/***************************************
*
*  MANAGE FRAMES
*
***************************************/

function isOnionskinOn(){
  return currentDoOnionskin;
}

function currentOnionskinFrame(){
  return document.querySelector('.frame.onionskin');
}

function updateOnionskin(){
  if (!isOnionskinOn()) return;
  dom.removeClass(currentOnionskinFrame(), 'onionskin');
  dom.addClass(currentFrame().previousElementSibling, 'onionskin');
}

function addFrame(){
  dom.insertAfter(dom.svg('g', {'class': 'frame selected'}), currentFrame());
  currentFrame().classList.remove('selected');
  updateOnionskin();
  updateFrameCount();
  file.onChange();
}

function cloneFrame(){
  dom.insertAfter(currentFrame().cloneNode(true), currentFrame());
  currentFrame().classList.remove('selected');
  updateOnionskin();
  updateFrameCount();
  file.onChange();
}

function deleteFrame(){
  var frameToDelete = currentFrame();
  if (frameToDelete.nextElementSibling){
      incrementFrame();
  }else if (frameToDelete.previousElementSibling){
      decrementFrame();
  }
  if (frameToDelete.parentNode.children.length > 1){
    dom.remove(frameToDelete);
  }else{
    dom.clear(frameToDelete); // don't delete the last frame, just its children
  }
  updateOnionskin();
  updateFrameCount();
  file.onChange();
}

function clear(){
  dom.clear(currentFrame());
}

function toggleOnionskin(){
  if (isOnionskinOn()){
      dom.addClass(currentFrame().previousElementSibling, 'onionskin');
  }else{
      dom.removeClass(currentOnionskinFrame(), 'onionskin');
  }
}

function incrementFrame(){
  var curr = currentFrame();
  if (curr.nextElementSibling){
      curr.classList.remove('selected');
      curr.nextElementSibling.classList.add('selected');
  }
  updateOnionskin();
  updateFrameCount();
}

function decrementFrame(){
  var curr = currentFrame();
  if (curr.previousElementSibling){
      curr.classList.remove('selected');
      curr.previousElementSibling.classList.add('selected');
  }
  updateOnionskin();
  updateFrameCount();
}

function gotoFirstFrame(){
  currentFrame().classList.remove('selected');
  document.querySelector('.frame').classList.add('selected');
  dom.removeClass(currentOnionskinFrame(), 'onionskin');
  updateFrameCount();
}

function gotoLastFrame(){
  currentFrame().classList.remove('selected');
  document.querySelector('.frame:last-child').classList.add('selected');
  dom.removeClass(currentOnionskinFrame(), 'onionskin');
  dom.addClass(currentFrame().previousElementSibling, 'onionskin');
  updateFrameCount();
}

var _lastFrameTime = 0;
var _frameDelay = 0;

function play(){
  document.body.classList.add('playing');
  // turn play button into stop button
  // disable all other controls
  // temporarily turn off onionskin (remember state)
  // start at beginning of document (remember state)
  document.querySelector('.frame').classList.add('play-frame');
  // add SVG SMIL animation
  // Unless looping, call stop() when animation is finished
  // How much of this can I do by adding "playing" class to body?
  setTimeout(function(){
      _frameDelay = currentFrameDelay;
      _lastFrameTime = Date.now();
      requestAnimationFrame(playNextFrame);
  }, 500);
}

function stop(){
  // remove SMIL animation
  // re-enable all controls
  // return to the frame we were on
  // re-enable onionskin if needed
  // turn stop button into play button
  dom.removeClass(playingFrame(), 'play-frame');
  document.body.classList.remove('playing');
}

function playNextFrame(){
  var time = Date.now();
  if ((time - _lastFrameTime) < _frameDelay){
      requestAnimationFrame(playNextFrame);
      return;
  }
  var currFrame = playingFrame();
  _lastFrameTime = time;
  if (currFrame.nextElementSibling){
      currFrame.classList.remove('play-frame');
      currFrame.nextElementSibling.classList.add('play-frame');
      requestAnimationFrame(playNextFrame);
  }else{
      stop();
  }
}

function updateFrameCount(){
  try{
      var frames = currentFrame().parentElement.children.length;
      var index = dom.indexOf(currentFrame());
      document.querySelector('.framecount').textContent = 'Frame ' + (index+1) + ' of ' + frames;
  }catch(e){
      // wait for the file to load, probably
  }
}

function undoLine(){
  dom.remove(currentFrame().lastElementChild);
  file.onChange();
}

function keydownHandler(evt){
  if ((evt.key || evt.keyIdentifier) === 'Control'){
      document.body.classList.add('usefiles');
  }
}

function keyupHandler(evt){
  if ((evt.key || evt.keyIdentifier) === 'Control'){
      document.body.classList.remove('usefiles');
  }
}

window.app = {
  updateFrameCount: updateFrameCount,
  play: play
};

// document.querySelector('#canvas-undo').addEventListener('click', undoLine, false);
// document.querySelector('#canvas-onionskin').addEventListener('change', toggleOnionskin, false);
document.addEventListener('keydown', keydownHandler, false);
document.addEventListener('keyup', keyupHandler, false);

<|endoftext|>


<commit_before>'use strict';

var gulp = require('gulp'),
    concat = require('gulp-concat'),
    uglify = require('gulp-uglify'),
    babel = require('gulp-babel'),
    sass = require('gulp-sass'),
    eslint = require('gulp-eslint'),
    minifyCSS = require('gulp-minify-css'),
    rename = require('gulp-rename'),
    devServer = require('gulp-develop-server'),
    browserSync = require('browser-sync'),
    Server = require('karma').Server,
    // Files
    testFiles = ['js/*.min.js', 'spec/*.js'],
    testJsFiles = ['spec/*.js'],
    appFiles = ['app/*.js'],
    sassFiles = ['styles/*.scss'],
    // Develop Server
    options = {
        server: {
            path: 'server.js',
            execArgv: ['--harmony']
        },
        bs: {
            proxy: 'http://localhost:3000'
        }
    };

gulp.task('default', function() {
    'use strict';

    gulp.start([
        'server:start',
        'js',
        'sass',
        'eslint',
        'eslintTestFiles',
        'karma'
    ]);
});

gulp.task('js', function() {
    'use strict';

    gulp.src(appFiles)
        .pipe(concat('app.min.js'))
        .pipe(babel())
        .pipe(uglify())
        .pipe(gulp.dest('js/'));
});

gulp.task('sass', function() {
    'use strict';

    gulp.src(sassFiles)
        .pipe(sass())
        .pipe(minifyCSS({
            keepBreaks: true
        }))
        .pipe(rename('styles.min.css'))
        .pipe(gulp.dest('css'));
});

gulp.task('karma', function() {
    'use strict';

    new Server({
        /*eslint-disable */
        configFile: __dirname + '/karma.conf.js',
        /*eslint-enable */
        singleRun: true
    }).start();
});

gulp.task('eslint', function() {
    'use strict';

    gulp.src(appFiles)
        .pipe(eslint('.eslintrc'))
        .pipe(eslint.format());
});

gulp.task('eslintTestFiles', function() {
    'use strict';

    gulp.src(testJsFiles)
        .pipe(eslint('.eslintrc'))
        .pipe(eslint.format());
});

gulp.task('server:start', function() {
    'use strict';

    devServer.listen(options.server, function(error) {
        if (!error) devServer(options.bs);
    });
});

gulp.task('server:restart', function() {
    'use strict';

    devServer.restart(function(error) {
        if (!error) devServer.reload();
    });
});

gulp.task('watch', function() {
    'use strict';

    gulp.watch(appFiles, function() {
        gulp.start([
            'eslint',
            'server:restart',
            'js'
        ]);
    });

    gulp.watch(sassFiles, function() {
        gulp.start([
            'sass',
            'server:restart'
        ]);
    });

    gulp.watch(testFiles, function() {
        gulp.start([
            'eslintTestFiles',
            'karma'
        ]);
    });
});
<commit_msg>small order change in gulp start tasa<commit_after>'use strict';

var gulp = require('gulp'),
    concat = require('gulp-concat'),
    uglify = require('gulp-uglify'),
    babel = require('gulp-babel'),
    sass = require('gulp-sass'),
    eslint = require('gulp-eslint'),
    minifyCSS = require('gulp-minify-css'),
    rename = require('gulp-rename'),
    devServer = require('gulp-develop-server'),
    browserSync = require('browser-sync'),
    Server = require('karma').Server,
    // Files
    testFiles = ['js/*.min.js', 'spec/*.js'],
    testJsFiles = ['spec/*.js'],
    appFiles = ['app/*.js'],
    sassFiles = ['styles/*.scss'],
    // Develop Server
    options = {
        server: {
            path: 'server.js',
            execArgv: ['--harmony']
        },
        bs: {
            proxy: 'http://localhost:3000'
        }
    };

gulp.task('default', function() {
    'use strict';

    gulp.start([
        'js',
        'sass',
        'eslint',
        'eslintTestFiles',
        'karma',
        'server:start'
    ]);
});

gulp.task('js', function() {
    'use strict';

    gulp.src(appFiles)
        .pipe(concat('app.min.js'))
        .pipe(babel())
        .pipe(uglify())
        .pipe(gulp.dest('js/'));
});

gulp.task('sass', function() {
    'use strict';

    gulp.src(sassFiles)
        .pipe(sass())
        .pipe(minifyCSS({
            keepBreaks: true
        }))
        .pipe(rename('styles.min.css'))
        .pipe(gulp.dest('css'));
});

gulp.task('karma', function() {
    'use strict';

    new Server({
        /*eslint-disable */
        configFile: __dirname + '/karma.conf.js',
        /*eslint-enable */
        singleRun: true
    }).start();
});

gulp.task('eslint', function() {
    'use strict';

    gulp.src(appFiles)
        .pipe(eslint('.eslintrc'))
        .pipe(eslint.format());
});

gulp.task('eslintTestFiles', function() {
    'use strict';

    gulp.src(testJsFiles)
        .pipe(eslint('.eslintrc'))
        .pipe(eslint.format());
});

gulp.task('server:start', function() {
    'use strict';

    devServer.listen(options.server, function(error) {
        if (!error) devServer(options.bs);
    });
});

gulp.task('server:restart', function() {
    'use strict';

    devServer.restart(function(error) {
        if (!error) devServer.reload();
    });
});

gulp.task('watch', function() {
    'use strict';

    gulp.watch(appFiles, function() {
        gulp.start([
            'eslint',
            'server:restart',
            'js'
        ]);
    });

    gulp.watch(sassFiles, function() {
        gulp.start([
            'sass',
            'server:restart'
        ]);
    });

    gulp.watch(testFiles, function() {
        gulp.start([
            'eslintTestFiles',
            'karma'
        ]);
    });
});
<|endoftext|>


<commit_before>(function(window, document, undefined) {
    window.onload = init;
    function init() {
        //get the canvas
        var canvas = document.getElementById("mapcanvas");
        var c = canvas.getContext("2d");
        var width = 512;
        var height = 288;
        var blockSize = 16;

        document.getElementById("startbtn").onclick = paintscreen;

        //paint the screen
        function paintscreen() {
            for(var i = 0; i< 32; i++) {
                for(var j = 0; j < 18; j++) {
                    paintblock(i, j);
                }
            }
        }

        //paint a block
        function paintblock(x, y) {
            for(var i = 0; i < blockSize; i++) {
                for(var j = 0; j< blockSize; j++) {
                    if(i == 0 || i == blockSize -1){
                        c.fillStyle = "#000000";
                        c.fillRect(i*x, j*y, 1, 1);
                    }
                    if(j == 0 || j == blockSize -1){
                        c.fillStyle = "#000000";
                        c.fillRect(i*x, j*y, 1, 1);

                    }

                }
            }
        }
    }
})(window, document, undefined);
<commit_msg>Update script.js<commit_after>(function(window, document, undefined) {
    window.onload = init;
    function init() {
        //get the canvas
        var canvas = document.getElementById("mapcanvas");
        var c = canvas.getContext("2d");
        var width = 512;
        var height = 288;
        var blockSize = 16;

        document.getElementById("startbtn").onclick = paintscreen;

        //paint a block
        function paintblock(x, y) {
            for(var i = 0; i < blockSize; i++) {
                for(var j = 0; j< blockSize; j++) {
                    if(i == 0 || i == blockSize -1){
                        c.fillStyle = "#000000";
                        c.fillRect(i*x, j*y, 1, 1);
                    }
                    if(j == 0 || j == blockSize -1){
                        c.fillStyle = "#000000";
                        c.fillRect(i*x, j*y, 1, 1);

                    }

                }
            }
        }

        //paint the screen
        function paintscreen() {
            for(var i = 0; i< 32; i++) {
                for(var j = 0; j < 18; j++) {
                    paintblock(i, j);
                }
            }
        }

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


<commit_before>import React, { Component, PropTypes } from "react";
import ReactDOM from "react-dom";
import ImgFigure from "../imgFigure";
import config from "../../config";
import "./index.less";

const imagesData = require("../../data/imagesData.json");

(array => {
    array.forEach(item => {
        item.imageUrl = `${config.resourcePrefix}/${item.fileName}`;
    });
})(imagesData);

/**
 * 获取区间内的随机值
 * @param  {number} low  区间最小值
 * @param  {number} high 区间最大值
 * @return {number}      区间内的随机数
 */
const getRangeRandom = (low, high) => {
    return Math.ceil(Math.random() * (high - low) + low);
};

class Gallery extends Component {
    constructor() {
        super();
        this.state = {
            imgsArrangeArr: []
        };
        this.constant = {
            centerPos: {
                left: 0,
                right: 0
            },
            hPosRange: {
                leftSecX: [0, 0],
                rightSecX: [0, 0],
                y: [0, 0]
            },
            vPosRange: {
                x: [0, 0],
                topY: [0, 0]
            }
        };
    }
    /**
     * 重新布局所有图片
     * @param  {number} centerIdx 指定居中排布哪个图片
     * @return {null}             无返回
     */
    rearrange(centerIdx) {
        const
            { constant } = this,
            { centerPos, hPosRange, vPosRange } = constant,
            hPosRangeLeftSecX = hPosRange.leftSecX,
            hPosRangeRightSecX = hPosRange.rightSecX,
            hPosRangeY = hPosRange.y,
            vPosRangeTopY = vPosRange.topY,
            vPosRangeX = vPosRange.x,
            topImgNum = Math.ceil(Math.random() * 2);
        let
            { imgsArrangeArr } = this.state,
            imgsArrangeTopArr = [],
            topImgSpliceIdx = 0,
            imgsArrangeCenterArr = imgsArrangeArr.splice(centerIdx, 1),
            i, j, k,
            hPosRangeLORX;
        // 首先居中 centerIdx 的图片
        imgsArrangeCenterArr[0].pos = centerPos;
        // 取出要布局上侧的图片的状态信息
        topImgSpliceIdx = Math.ceil(Math.random() * (imgsArrangeArr.length - topImgNum));
        imgsArrangeTopArr = imgsArrangeArr.splice(topImgSpliceIdx, topImgNum);
        // 布局位于上侧的图片
        imgsArrangeTopArr.forEach((item, idx) => {
            imgsArrangeTopArr[idx].pos = {
                top: getRangeRandom(vPosRangeTopY[0], vPosRangeTopY[0]),
                left: getRangeRandom(vPosRangeX[0], vPosRangeX[0])
            };
        });
        // 布局左右两侧的图片
        for (i = 0, j = imgsArrangeArr.length, k = j / 2; i < j; i++) {
            // 前半部分布局在左边，后半部分布局在右边
            hPosRangeLORX = i < k ? hPosRangeLeftSecX : hPosRangeRightSecX;
            imgsArrangeArr[i].pos = {
                top: getRangeRandom(hPosRangeY[0], hPosRangeY[1]),
                left: getRangeRandom(hPosRangeLORX[0], hPosRangeLORX[1])
            }
        }

        if (imgsArrangeTopArr && imgsArrangeTopArr[0]) {
            imgsArrangeArr.splice(topImgSpliceIdx, 0, imgsArrangeTopArr[0]);
        }

        imgsArrangeArr.splice(centerIdx, 0, imgsArrangeCenterArr[0]);

        this.setState({
            imgsArrangeArr: imgsArrangeArr
        });
    }
    componentDidMount() {
        const
            stageDOM = ReactDOM.findDOMNode(this.refs.stage),
            stageW = stageDOM.scrollWidth,
            stageH = stageDOM.scrollHeight,
            halfStageW = Math.ceil(stageW / 2),
            halfStageH = Math.ceil(stageH / 2),
            imgFigureDOM = ReactDOM.findDOMNode(this.refs.imgFigure0),
            imgW = imgFigureDOM.scrollWidth,
            imgH = imgFigureDOM.scrollHeight,
            halfImgW = Math.ceil(imgW / 2),
            halfImgH = Math.ceil(imgH / 2);
        this.constant.centerPos = {
            left: halfStageW - halfImgW,
            top: halfStageH - halfImgH
        };
        // 计算左侧、右侧区域图片排布位置的取值范围
        this.constant.hPosRange.leftSecX = [-halfImgW, halfStageW - halfImgW * 3];
        this.constant.hPosRange.rightSecX = [halfStageW + halfImgW, stageW - halfImgW];
        this.constant.hPosRange.y = [-halfImgH, stageH - halfImgH];
        // 计算上侧区域图片排布位置的取值范围
        this.constant.vPosRange.topY = [-halfImgH, halfStageH - halfImgH * 3];
        this.constant.vPosRange.x = [halfImgW - imgW, halfImgW];

        this.rearrange(0);
    }
    render() {
        let controllerUnits = [],
            imgFigures = [];
        imagesData.forEach((item, idx) => {
            if (!this.state.imgsArrangeArr[idx]) {
                this.state.imgsArrangeArr[idx] = {
                    pos: {
                        left: 0,
                        top: 0
                    }
                };
            }
            imgFigures.push(<ImgFigure key={idx} data={item} ref={"imgFigure" + idx} arrange={this.state.imgsArrangeArr[idx]} />);
        });
        return (

                    {imgFigures}

                    {controllerUnits}

        )
    }
}

export default Gallery;<commit_msg>fix top image bug<commit_after>import React, { Component, PropTypes } from "react";
import ReactDOM from "react-dom";
import ImgFigure from "../imgFigure";
import config from "../../config";
import "./index.less";

const imagesData = require("../../data/imagesData.json");

(array => {
    array.forEach(item => {
        item.imageUrl = `${config.resourcePrefix}/${item.fileName}`;
    });
})(imagesData);

/**
 * 获取区间内的随机值
 * @param  {number} low  区间最小值
 * @param  {number} high 区间最大值
 * @return {number}      区间内的随机数
 */
const getRangeRandom = (low, high) => {
    return Math.ceil(Math.random() * (high - low) + low);
};

class Gallery extends Component {
    constructor() {
        super();
        this.state = {
            imgsArrangeArr: []
        };
        this.constant = {
            centerPos: {
                left: 0,
                right: 0
            },
            hPosRange: {
                leftSecX: [0, 0],
                rightSecX: [0, 0],
                y: [0, 0]
            },
            vPosRange: {
                x: [0, 0],
                topY: [0, 0]
            }
        };
    }
    /**
     * 重新布局所有图片
     * @param  {number} centerIdx 指定居中排布哪个图片
     * @return {null}             无返回
     */
    rearrange(centerIdx) {
        const
            { constant } = this,
            { centerPos, hPosRange, vPosRange } = constant,
            hPosRangeLeftSecX = hPosRange.leftSecX,
            hPosRangeRightSecX = hPosRange.rightSecX,
            hPosRangeY = hPosRange.y,
            vPosRangeTopY = vPosRange.topY,
            vPosRangeX = vPosRange.x,
            topImgNum = Math.ceil(Math.random() * 2);
        let
            { imgsArrangeArr } = this.state,
            imgsArrangeTopArr = [],
            topImgSpliceIdx = 0,
            imgsArrangeCenterArr = imgsArrangeArr.splice(centerIdx, 1),
            i, j, k,
            hPosRangeLORX;
        // 首先居中 centerIdx 的图片
        imgsArrangeCenterArr[0].pos = centerPos;
        // 取出要布局上侧的图片的状态信息
        topImgSpliceIdx = Math.ceil(Math.random() * (imgsArrangeArr.length - topImgNum));
        imgsArrangeTopArr = imgsArrangeArr.splice(topImgSpliceIdx, topImgNum);
        // 布局位于上侧的图片
        imgsArrangeTopArr.forEach((item, idx) => {
            imgsArrangeTopArr[idx].pos = {
                top: getRangeRandom(vPosRangeTopY[0], vPosRangeTopY[0]),
                left: getRangeRandom(vPosRangeX[0], vPosRangeX[0])
            };
        });
        // 布局左右两侧的图片
        for (i = 0, j = imgsArrangeArr.length, k = j / 2; i < j; i++) {
            // 前半部分布局在左边，后半部分布局在右边
            hPosRangeLORX = i < k ? hPosRangeLeftSecX : hPosRangeRightSecX;
            imgsArrangeArr[i].pos = {
                top: getRangeRandom(hPosRangeY[0], hPosRangeY[1]),
                left: getRangeRandom(hPosRangeLORX[0], hPosRangeLORX[1])
            }
        }

        if (imgsArrangeTopArr && imgsArrangeTopArr[0]) {
            imgsArrangeArr.splice(topImgSpliceIdx, 0, imgsArrangeTopArr[0]);
        }

        imgsArrangeArr.splice(centerIdx, 0, imgsArrangeCenterArr[0]);

        this.setState({
            imgsArrangeArr: imgsArrangeArr
        });
    }
    componentDidMount() {
        const
            stageDOM = ReactDOM.findDOMNode(this.refs.stage),
            stageW = stageDOM.scrollWidth,
            stageH = stageDOM.scrollHeight,
            halfStageW = Math.ceil(stageW / 2),
            halfStageH = Math.ceil(stageH / 2),
            imgFigureDOM = ReactDOM.findDOMNode(this.refs.imgFigure0),
            imgW = imgFigureDOM.scrollWidth,
            imgH = imgFigureDOM.scrollHeight,
            halfImgW = Math.ceil(imgW / 2),
            halfImgH = Math.ceil(imgH / 2);
        this.constant.centerPos = {
            left: halfStageW - halfImgW,
            top: halfStageH - halfImgH
        };
        // 计算左侧、右侧区域图片排布位置的取值范围
        this.constant.hPosRange.leftSecX = [-halfImgW, halfStageW - halfImgW * 3];
        this.constant.hPosRange.rightSecX = [halfStageW + halfImgW, stageW - halfImgW];
        this.constant.hPosRange.y = [-halfImgH, stageH - halfImgH];
        // 计算上侧区域图片排布位置的取值范围
        this.constant.vPosRange.topY = [-halfImgH, halfStageH - halfImgH * 3];
        this.constant.vPosRange.x = [halfStageW - imgW, halfStageW];

        this.rearrange(0);
    }
    render() {
        let controllerUnits = [],
            imgFigures = [];
        imagesData.forEach((item, idx) => {
            if (!this.state.imgsArrangeArr[idx]) {
                this.state.imgsArrangeArr[idx] = {
                    pos: {
                        left: 0,
                        top: 0
                    }
                };
            }
            imgFigures.push(<ImgFigure key={idx} data={item} ref={"imgFigure" + idx} arrange={this.state.imgsArrangeArr[idx]} />);
        });
        return (

                    {imgFigures}

                    {controllerUnits}

        )
    }
}

export default Gallery;<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015, Marco Grätsch <magdev3.0@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

var webhook = require('express-ifttt-webhook'),
    User = require('./user'),
    Parser = require('./ifttt/parser'),
    types = require('../config/elasticsearch/types.json'),
    debug = require('debug')('ifttt-elasticsearch:ifttt'),

    generateRequest = function(json, config) {
        return {
            index: (config.index.name || 'ifttt'),
            type: (json.type || config.index.type || 'common'),
            body: json
        }
    };

module.exports = function(app, config, es) {
    var parser = new Parser(types, config);

    app.use(webhook(User.verify, function(json, done) {
        es.index(generateRequest(parser.parse(json), config), function(error, response) {
            if (error) {
                return done(error, response);
            }
            return done();
        });
    }));
};<commit_msg>wrap user verification<commit_after>/**
 * Copyright (c) 2015, Marco Grätsch <magdev3.0@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

var webhook = require('express-ifttt-webhook'),
    User = require('./user'),
    Parser = require('./ifttt/parser'),
    types = require('../config/elasticsearch/types.json'),
    debug = require('debug')('ifttt-elasticsearch:ifttt'),

    generateRequest = function(json, config) {
        return {
            index: (config.index.name || 'ifttt'),
            type: (json.type || config.index.type || 'common'),
            body: json
        }
    },

    verifyUser = function(username, password, done) {
        return User.verify(username, password, done);
    };

module.exports = function(app, config, es) {
    var parser = new Parser(types, config);

    app.use(webhook(verifyUser, function(json, done) {
        es.index(generateRequest(parser.parse(json), config), function(error, response) {
            if (error) {
                return done(error, response);
            }
            return done();
        });
    }));
};<|endoftext|>


<commit_before>require('dotenv').config();
var util = require('util');

module.exports = function (context, req) {

    var statusCode = 400;
    var responseBody = "Invalid request object";

    if (typeof req.body != 'undefined' && typeof req.body == 'object') {

        statusCode = 201;
        //context.bindings.outTable = req.body;
        var myReq = req.body;
        var myToken = new oAccessToken(myReq.userid,myReq.email,guid());

        context.log('------>' + myToken.email);
        context.log('------>' + myToken.userid);
        context.log('------>' + myToken.accesstoken);
        context.log('------>' + myToken.expires);

        //save to document db
        context.bindings.out = myToken;

        //send mail
        sendMail(myToken.userid,myToken.email,myToken.accesstoken);

        responseBody = "Access Token Created, Email Sent";
    }

    context.res = {
        status: statusCode,
        body: responseBody
    };

    context.done();
}

function sendMail(userid,email,token) {

    console.log('Sending Notification');

    var toEmail = email;
    var userId = userid
    var userToken = token;
    var profileUrl = util.format("%s%s?access_token=%s",process.env.DashboardProfileUrl, userId, userToken);

    console.log('------>' + profileUrl);

    var msgContent = util.format("Please view the profile here: %s", profileUrl);

    var helper = require('sendgrid').mail;

    from_email = new helper.Email(process.env.NotifyEmailFrom);
    to_email = new helper.Email(toEmail);
    subject = "Missing Children of Canada Alert";
    content = new helper.Content("text/plain", msgContent);
    mail = new helper.Mail(from_email, subject, to_email, content);

    // Set to high importance
    header = new helper.Header("Priority", "Urgent");
    mail.addHeader(header);
    header = new helper.Header("Importance", "high");
    mail.addHeader(header);

    var sg = require('sendgrid')(process.env.SendGridAPIKey);

    var requestBody = mail.toJSON();
    var emptyRequest = require('sendgrid-rest').request;
    var requestPost = JSON.parse(JSON.stringify(emptyRequest));
    requestPost.method = 'POST';
    requestPost.path = '/v3/mail/send';
    requestPost.body = requestBody;
    sg.API(requestPost, function (error, response) {
        console.log(response.statusCode);
        // console.log(response.body);
        // console.log(response.headers);
    })

}

function storeToken(userId, access_token) {
    //store id / token to the db
}

function oAccessToken(userid,email,accesstoken) {
    this.userid = userid;
    this.email = email;
    this.accesstoken = accesstoken;
    this.expires = getCurrentDate();
}

function getCurrentDate() {
    var dateTime = require('node-datetime');
    var dt = dateTime.create();
    dt.offsetInDays(1);
    var formatted = dt.format('Y-m-d H:M:S');
    return formatted;
}

function guid() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000)
      .toString(16)
      .substring(1);
  }
  return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
    s4() + '-' + s4() + s4() + s4();
}

<commit_msg>Removed logging<commit_after>require('dotenv').config();
var util = require('util');

module.exports = function (context, req) {

    var statusCode = 400;
    var responseBody = "Invalid request object";

    if (typeof req.body != 'undefined' && typeof req.body == 'object') {

        statusCode = 201;
        //context.bindings.outTable = req.body;
        var myReq = req.body;
        var myToken = new oAccessToken(myReq.userid,myReq.email,guid());

        //save to document db
        context.bindings.out = myToken;

        //send mail
        sendMail(myToken.userid,myToken.email,myToken.accesstoken);

        responseBody = "Access Token Created, Email Sent";
    }

    context.res = {
        status: statusCode,
        body: responseBody
    };

    context.done();
}

function sendMail(userid,email,token) {

    console.log('Sending Notification');

    var toEmail = email;
    var userId = userid
    var userToken = token;
    var profileUrl = util.format("%s%s?access_token=%s",process.env.DashboardProfileUrl, userId, userToken);

    //console.log('------>' + profileUrl);

    var msgContent = util.format("Please view the profile here: %s", profileUrl);

    var helper = require('sendgrid').mail;

    from_email = new helper.Email(process.env.NotifyEmailFrom);
    to_email = new helper.Email(toEmail);
    subject = "Missing Children of Canada Alert";
    content = new helper.Content("text/plain", msgContent);
    mail = new helper.Mail(from_email, subject, to_email, content);

    // Set to high importance
    header = new helper.Header("Priority", "Urgent");
    mail.addHeader(header);
    header = new helper.Header("Importance", "high");
    mail.addHeader(header);

    var sg = require('sendgrid')(process.env.SendGridAPIKey);

    var requestBody = mail.toJSON();
    var emptyRequest = require('sendgrid-rest').request;
    var requestPost = JSON.parse(JSON.stringify(emptyRequest));
    requestPost.method = 'POST';
    requestPost.path = '/v3/mail/send';
    requestPost.body = requestBody;
    sg.API(requestPost, function (error, response) {
        //console.log(response.statusCode);
        // console.log(response.body);
        // console.log(response.headers);
    })

}

function storeToken(userId, access_token) {
    //store id / token to the db
}

function oAccessToken(userid,email,accesstoken) {
    this.userid = userid;
    this.email = email;
    this.accesstoken = accesstoken;
    this.expires = getCurrentDate();
}

function getCurrentDate() {
    var dateTime = require('node-datetime');
    var dt = dateTime.create();
    dt.offsetInDays(1);
    var formatted = dt.format('Y-m-d H:M:S');
    return formatted;
}

function guid() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000)
      .toString(16)
      .substring(1);
  }
  return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
    s4() + '-' + s4() + s4() + s4();
}

<|endoftext|>


<commit_before>/*!
 * Start Bootstrap - Grayscale Bootstrap Theme (http://startbootstrap.com)
 * Code licensed under the Apache License v2.0.
 * For details, see http://www.apache.org/licenses/LICENSE-2.0.
 */

// jQuery to collapse the navbar on scroll
$(window).scroll(function() {
    if ($(".navbar").offset().top > 50) {
        $(".navbar-fixed-top").addClass("top-nav-collapse");
    } else {
        $(".navbar-fixed-top").removeClass("top-nav-collapse");
    }
});

// jQuery for page scrolling feature - requires jQuery Easing plugin
$(function() {
    $('a.page-scroll').bind('click', function(event) {
        var $anchor = $(this);
        $('html, body').stop().animate({
            scrollTop: $($anchor.attr('href')).offset().top
        }, 1500, 'easeInOutExpo');
        event.preventDefault();
    });
});

// Closes the Responsive Menu on Menu Item Click
$('.navbar-collapse ul li a').click(function() {
    $('.navbar-toggle:visible').click();
});

$('.expand-image').magnificPopup({
    type:'image',
    verticalFit: true,
    closeOnContentClick: true,
    closeBtnInside: true
});

$("img.ajmint-unveil").unveil($(window).height()*2, function() {
    $(this).load(function() {
        this.style.opacity = 1;
    });
});

<commit_msg>track completion<commit_after>/*!
 * Start Bootstrap - Grayscale Bootstrap Theme (http://startbootstrap.com)
 * Code licensed under the Apache License v2.0.
 * For details, see http://www.apache.org/licenses/LICENSE-2.0.
 */

var BIGREAD = BIGREAD || {}
BIGREAD.PageScrolled = {
  "25": false,
  "50": false,
  "75": false,
  "100": false
}

function debounce(fn, delay) {
  var timer = null;
  return function () {
    var context = this, args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function () {
      fn.apply(context, args);
    }, delay);
  };
}

function trackScroll() {
  var scrollTop = $('body').scrollTop();
  var height = $('#content-container').height();
  var percentScrolled = scrollTop / height;

  if (!BIGREAD.PageScrolled['25']) {
    if (percentScrolled >= 0.25 && percentScrolled < 0.5) {
      BigreadAnalytics.completed('25%');
      BIGREAD.PageScrolled['25'] = true;
    }
  }

  if (!BIGREAD.PageScrolled['50']) {
    if (percentScrolled >= 0.5 && percentScrolled < 0.75) {
      BigreadAnalytics.completed('50%');
      BIGREAD.PageScrolled['50'] = true;
    }
  }

  if (!BIGREAD.PageScrolled['75']) {
    if (percentScrolled >= 0.75 && percentScrolled < 1) {
      BigreadAnalytics.completed('75%');
      BIGREAD.PageScrolled['75'] = true;
    }
  }

  if (!BIGREAD.PageScrolled['100']) {
    if (percentScrolled >= 0.95) {
      BigreadAnalytics.completed('100%');
      BIGREAD.PageScrolled['100'] = true;
    }
  }

}

// jQuery to collapse the navbar on scroll
$(window).scroll(function() {
    if ($(".navbar").offset().top > 50) {
        $(".navbar-fixed-top").addClass("top-nav-collapse");
    } else {
        $(".navbar-fixed-top").removeClass("top-nav-collapse");
    }
});

$(window).scroll(debounce(trackScroll, 250));

// jQuery for page scrolling feature - requires jQuery Easing plugin
$(function() {
    $('a.page-scroll').bind('click', function(event) {
        var $anchor = $(this);
        $('html, body').stop().animate({
            scrollTop: $($anchor.attr('href')).offset().top
        }, 1500, 'easeInOutExpo');
        event.preventDefault();
    });
});

// Closes the Responsive Menu on Menu Item Click
$('.navbar-collapse ul li a').click(function() {
    $('.navbar-toggle:visible').click();
});

$('.expand-image').magnificPopup({
    type:'image',
    verticalFit: true,
    closeOnContentClick: true,
    closeBtnInside: true
});

$("img.ajmint-unveil").unveil($(window).height()*2, function() {
    $(this).load(function() {
        this.style.opacity = 1;
    });
});

<|endoftext|>


<commit_before>var base = 'https://api.github.com/users/';
var rData = {},
	uData = {};
var langChart;

// Run on load
$(document).ready(function() {
	$('#username').focus();
	$('#data').hide();
	$('.spinner').hide();
});

//Detect 'Enter' key being pressed
$('#username').keyup(function (e) {
	if (e.keyCode === 13) {
		$('#content').empty();
		$('#orgz').empty();
		$('#top-bar').empty();
		$('#data').hide();
		$('#messages').empty();
        $('#repos').empty();
		$('#API').hide();
		var enteredText = $('#username').val();
		if (enteredText.length === 0) unrecognized(enteredText);
		else {
			if (enteredText == 'git help') showHelp();
			else if (enteredText == 'git info') showInfo();
			else if (enteredText == 'username') showOops();
			else {
				$('.spinner').show();
				getUser(enteredText);
			}
			$('#username').val('');
		}
	}
});

//Get user data using GitHub API
function getUser(userName) {
	$.get(base + userName, function (userData) {
		uData = userData;
		$('#search').fadeOut(750, function () {
			$('#data').fadeIn(500);
			$('#footer').fadeOut();
		});
		//Check that the user has a defined full name or use their username if they don't
		var uName = userName,
			uBlog = uData.blog, uCompany = uData.company, uLocation = uData.location;

		//Check for any required information that is null
		if (uData.name !== null && uData.name !== undefined && uData.name.length) {
            uName = uData.name;
        }

		if (uBlog === null || uBlog === undefined || !uBlog.length) {
			$('#home').hide();
		}

		if (uCompany === null || uCompany === undefined || !uCompany.length) {
			uCompany = 'a secret location';
		}

		if (uLocation === null || uLocation === undefined || !uLocation.length) {
			uLocation = 'a hidden safe house';
		}

		$('#top-bar').append(''+uName+'');
		$('#top-bar').append(' has been committing since '+(uData.created_at).substring(0,10)+'');
		$("#home").wrap('');
		$("#code").wrap('');
		$('#content').append('Since then, they have amassed ');
		$('#content').append(''+uData.public_repos+' public repositories,');
		$('#content').append(''+uData.followers+' followers and');
		$('#content').append(''+uData.public_gists+' gists.
');
		$('#content').append(''+((uName).split(" "))[0]+' currently works at '+uCompany+'');
        $('#content').append(' and lives in '+uLocation+'.');

		var orgCount = 0;
		var oData = {};
		$.get(base + userName+'/orgs', function (orgData) {
			oData = orgData;
			$.each(oData, function(i, orgInf) {
				orgCount++;
			});
			if (orgCount === 0) {
				$('#orgz').hide();
			} else {
				$('#orgz').show();
				$('#orgz').append(''+((uName).split(" "))[0]+' is a member of '+orgCount+' organizations.');
			}
		});
	});
    getRepos(userName);
}

//Get users' organization info using GitHub API
function getOrgs(username, fullName) {

}

//Get users' repo data using GitHub API
function getRepos(user) {
    var repos = [],
		uLang = [],
		langList = [], //To prevent duplicates
		arrInd;

	$.get(base + user + '/repos', function (repoData) {
			rData = repoData;
			$.each(rData, function(i, repoInf) {
				repos.push({info:repoInf});
			});

		//Sort repos by stars
		function sortByStars(a, b) {
				return b.info.stargazers_count - a.info.stargazers_count;
		};

		repos.sort(sortByStars);

		$('#repos').append('

Repo Name	Stars	Forks

'+repos[0].info.name+'	'+repos[0].info.stargazers_count+'	'+repos[0].info.forks_count+'

'+repos[1].info.name+'	'+repos[1].info.stargazers_count+'	'+repos[1].info.forks_count+'

'+repos[2].info.name+'	'+repos[2].info.stargazers_count+'	'+repos[2].info.forks_count+'

'+repos[3].info.name+'	'+repos[3].info.stargazers_count+'	'+repos[3].info.forks_count+'

'+repos[4].info.name+'	'+repos[4].info.stargazers_count+'	'+repos[4].info.forks_count+'

');

		for (var i = 0; i < repos.length; i++) {
			if (repos[i].info.language) {
				if (langList.indexOf(repos[i].info.language) === -1) {
					uLang.push({val:1, label:repos[i].info.language});
					langList[langList.length] = repos[i].info.language;
				} else {
					uLang[langList.indexOf(repos[i].info.language)].val++;
				}
			}
		}

		//Get users' language stats and plot a graph of the data
		var ctx = document.getElementById("lang-chart").getContext("2d");
		var data = [];
		langChart = new Chart(ctx).Doughnut(data, {animateScale: true,animationEasing : "easeOutExpo"});

		for (var i = 0; i < langList.length; i++) {
			langChart.addData({
				value: uLang[i].val,
				color: Please.make_color(),
				label: uLang[i].label
			});
		}
	});
}

//Help message
function showHelp() {
	var help = 'Enter the username of the GitHub member you are looking for.';
	$('#messages').append('
'+help+'
');
	$('#messages').show();
	setTimeout(function() {
        $("#messages").fadeOut("slow", function() {
            $("#messages").hide();
        });
    }, 5000);
}

//Information about Committed
function showInfo() {
	var info = 'Committed is not affiliated with GitHub, it simply uses the GitHub API.
Committed was made with ♥ by Nischaal Cooray.
Check out Committed on GitHub!
Committed is NOT optimized for mobile devices YET!'
	$('#messages').append('
'+info+'
');
	$('#messages').show();
	setTimeout(function() {
        $("#messages").fadeOut("slow", function() {
            $("#messages").hide();
        });
    }, 9000);
}

//Oops
function showOops() {
	var oops = 'Ah! Hello! I see that I didn\'t make myself understandable enough - sorry about that.
What I meant was to enter the username of the user that you are trying to find information about.
Now go get \'em!';
	$('#messages').append('
'+oops+'
');
	$('#messages').show();
	setTimeout(function() {
        $("#messages").fadeOut("slow", function() {
            $("#messages").hide();
        });
    }, 9000);
}
//Error message - not implemented fully yet
function unrecognized(text) {
	var error = '';
	if (text.length == 0) error = 'I ain\'t silly, I know you didn\'t type anything!
Try again!';
	else error = 'Ah shucks... I couldn\'t find that user... Would you give me another chance?';
	$('#messages').append('
'+error+'
');
	$('#messages').show();
	setTimeout(function() {
        $("#messages").fadeOut("slow", function() {
            $("#messages").hide();
        });
    }, 5000);
}

// Take user back to search screen
$( '#go-back' ).click(function() {
		$('#data').fadeOut(500, function () {
			$('#search').fadeIn(500);
			$('#API').fadeIn(500);
			$('.spinner').hide();
			$('#username').focus();
			langChart.destroy();
		});
	$('#home').show();
});
<commit_msg>Update script.js<commit_after>//Global variables
var base = 'https://api.github.com/users/';
var rData = {},
	uData = {};
var langChart;

// Run on load
$(document).ready(function() {
	$('#username').focus();
	$('#data').hide();
	$('.spinner').hide();
});

//Detect 'Enter' key being pressed
$('#username').keyup(function (e) {
	if (e.keyCode === 13) {
		$('#content').empty();
		$('#orgz').empty();
		$('#top-bar').empty();
		$('#data').hide();
		$('#messages').empty();
        $('#repos').empty();
		$('#API').hide();
		var enteredText = $('#username').val();
		if (enteredText.length === 0) unrecognized(enteredText);
		else {
			if (enteredText == 'git help') showHelp();
			else if (enteredText == 'git info') showInfo();
			else if (enteredText == 'username') showOops();
			else {
				$('.spinner').show();
				getUser(enteredText);
			}
			$('#username').val('');
		}
	}
});

//Get user data using GitHub API
function getUser(userName) {
	$.get(base + userName, function (userData) {
		uData = userData;
		$('#search').fadeOut(750, function () {
			$('#data').fadeIn(500);
			$('#footer').fadeOut();
		});
		//Check that the user has a defined full name or use their username if they don't
		var uName = userName,
			uBlog = uData.blog, uCompany = uData.company, uLocation = uData.location;

		//Check for any required information that is null
		if (uData.name !== null && uData.name !== undefined && uData.name.length) {
            uName = uData.name;
        }

		if (uBlog === null || uBlog === undefined || !uBlog.length) {
			$('#home').hide();
		}

		if (uCompany === null || uCompany === undefined || !uCompany.length) {
			uCompany = 'a secret location';
		}

		if (uLocation === null || uLocation === undefined || !uLocation.length) {
			uLocation = 'a hidden safe house';
		}

		document.title = uName + '\'s résumés';

		$('#top-bar').append(''+uName+'');
		$('#top-bar').append(' has been committing since '+(uData.created_at).substring(0,10)+'');
		$("#home").wrap('');
		$("#code").wrap('');
		$('#content').append('Since then, they have amassed ');
		$('#content').append(''+uData.public_repos+' public repositories,');
		$('#content').append(''+uData.followers+' followers and');
		$('#content').append(''+uData.public_gists+' gists.
');
		$('#content').append(''+((uName).split(" "))[0]+' currently works at '+uCompany+'');
        $('#content').append(' and lives in '+uLocation+'.');

		//Get users' organization info
		var orgCount = 0;
		var oData = {};
		var orgs = [];
		$.get(base + userName+'/orgs', function (orgData) {
			oData = orgData;
			$.each(oData, function(i, orgInf) {
				orgCount++;
				orgs.push({info:orgInf});
			});
			if (orgCount === 0) {
				$('#orgz').hide();
			} else {
				$('#orgz').show();
				$('#orgz').append(''+((uName).split(" "))[0]+' is a member of '+orgs[0].info.login+' and ');
				if ((orgCount - 1) === 1) {
					$('#orgz').append(' '+orgs[1].info.login+'.');
				} else {
					$('#orgz').append(' '+(orgCount - 1)+' other organizations.');
				}
			}
		});
	});
	getRepos(userName);
}

//Get users' repo data using GitHub API
function getRepos(user) {
	var repos = [],
		uLang = [],
		langList = [], //To prevent duplicates
		page = 1,
		repoInf;

	var ctx = document.getElementById("lang-chart").getContext("2d");
	var data = [];
	langChart = new Chart(ctx).Doughnut(data, {animateScale: true,animationEasing : "easeOutExpo",segmentStrokeWidth : 2});

	while (page !== 3) {
		$.get(base+user+'/repos?&page='+page, function (repoData) {
			rData = repoData;
			alert(repoData.length);
			if (repoData.length === 0) {
				alert('here');
			}
			else {
				$.each(rData, function(i, repoInf) {
					repos.push({info:repoInf});
				});

				repos.sort(sortByStars);

				$('#repos').append('

Repo Name	Stars	Forks

'+repos[0].info.name+'	'+repos[0].info.stargazers_count+'	'+repos[0].info.forks_count+'

'+repos[1].info.name+'	'+repos[1].info.stargazers_count+'	'+repos[1].info.forks_count+'

'+repos[2].info.name+'	'+repos[2].info.stargazers_count+'	'+repos[2].info.forks_count+'

'+repos[3].info.name+'	'+repos[3].info.stargazers_count+'	'+repos[3].info.forks_count+'

'+repos[4].info.name+'	'+repos[4].info.stargazers_count+'	'+repos[4].info.forks_count+'

');

				for (var i = 0; i < repos.length; i++) {
					if (repos[i].info.language) {
						if (langList.indexOf(repos[i].info.language) === -1) {
							uLang.push({val:1, label:repos[i].info.language});
							langList[langList.length] = repos[i].info.language;
						} else {
							uLang[langList.indexOf(repos[i].info.language)].val++;
						}
					}
				}
				for (var i = 0; i < langList.length; i++) {
					langChart.addData({
						value: uLang[i].val,
						color: Please.make_color(),
						label: uLang[i].label
					});
				}
			}
		});
	page++;
	}
}

//Sort repos by stars
function sortByStars(a, b) {
		return b.info.stargazers_count - a.info.stargazers_count;
}

//Help message
function showHelp() {
	var help = 'Enter the username of the GitHub member you are looking for.';
	$('#messages').append('
'+help+'
');
	$('#messages').show();
	setTimeout(function() {
        $("#messages").fadeOut("slow", function() {
            $("#messages").hide();
        });
    }, 5000);
}

//Information about Committed
function showInfo() {
	var info = 'Committed is not affiliated with GitHub, it simply uses the GitHub API.
Committed was made with ♥ by Nischaal Cooray and is licensed under the MIT license.
Check out Committed on GitHub!
Committed is NOT optimized for mobile devices YET!'
	$('#messages').append('
'+info+'
');
	$('#messages').show();
	setTimeout(function() {
        $("#messages").fadeOut("slow", function() {
            $("#messages").hide();
        });
    }, 9000);
}

//Oops
function showOops() {
	var oops = 'Ah! Hello! I see that I didn\'t make myself understandable enough - sorry about that.
What I meant was to enter the username of the user that you are trying to find information about.
Now go get \'em!';
	$('#messages').append('
'+oops+'
');
	$('#messages').show();
	setTimeout(function() {
        $("#messages").fadeOut("slow", function() {
            $("#messages").hide();
        });
    }, 9000);
}
//Error message - not implemented fully yet
function unrecognized(text) {
	var error = '';
	if (text.length == 0) error = 'I ain\'t silly, I know you didn\'t type anything!
Try again!';
	else error = 'Ah shucks... I couldn\'t find that user... Would you give me another chance?';
	$('#messages').append('
'+error+'
');
	$('#messages').show();
	setTimeout(function() {
        $("#messages").fadeOut("slow", function() {
            $("#messages").hide();
        });
    }, 5000);
}

// Take user back to search screen
$( '#go-back' ).click(function() {
		$('#data').fadeOut(500, function () {
			$('#search').fadeIn(500);
			$('#API').fadeIn(500);
			$('.spinner').hide();
			$('#username').focus();
			langChart.destroy();
		});
	$('#home').show();
	document.title = 'Committed';
});
<|endoftext|>


<commit_before>var gulp = require('gulp');
var es6 = require('gulp-es6-transpiler');
var rename = require('gulp-rename');
var watch = require('gulp-watch');

gulp.task('transpile', function() {
 gulp.src(['*/*.es6.js', '!node_modules/**/*.es6.js'])
    .pipe(es6({
      disallowUnknownReferences: false
    }))
    .pipe(rename(function(path) {
      path.basename = path.basename.replace('.es6', '');
    }))
    .on('error', function(err) {
      console.log(err.message);
      this.end();
    })
    .pipe(gulp.dest('.'));
});

gulp.task('watch', function() {
  gulp.watch('**/*.es6.js', ['transpile']);
});

gulp.task('default', ['transpile', 'watch']);
<commit_msg>Added watch for node_module/sync<commit_after>var gulp = require('gulp');
var es6 = require('gulp-es6-transpiler');
var rename = require('gulp-rename');
var watch = require('gulp-watch');

// Other filders to watch, if any
var watchOthers = ['node_modules/sync/'];

gulp.task('transpile', function() {
 gulp.src(['**/*.es6.js', '!node_modules/**/*.es6.js'])
    .pipe(es6({
      disallowUnknownReferences: false
    }))
    .pipe(rename(function(path) {
      path.basename = path.basename.replace('.es6', '');
    }))
    .on('error', function(err) {
      console.log(err.message);
      this.end();
    })
    .pipe(gulp.dest('.'));
});

gulp.task('watch', function() {
  gulp.watch('**/*.es6.js', ['transpile']);
  watchOthers.forEach(function(otherPath) {
    gulp.watch(otherPath + '**/*.es6.js', ['transpile']);
  });
  gulp.watch('**/*.es6.js', ['transpile']);
});

gulp.task('default', ['transpile', 'watch']);
<|endoftext|>


<commit_before>import Inferno from 'inferno'
import IconArchitecture from '../icons/IconArchitecture'
import IconCompatible from '../icons/IconCompatible'
import IconIsomorphic from '../icons/IconIsomorphic'
import IconModular from '../icons/IconModular'
import IconSize from '../icons/IconSize'
import IconSpeed from '../icons/IconSpeed'

export default function() {
    return

                <IconSize/>

Tiny Size

Inferno is much smaller in size, 9kb vs 45kb gzip. This means inferno is faster to transfer over the network and much faster to parse.

                <IconCompatible/>

React Compatible

React-like API, concepts and component lifecycle events. Switch over easily with inferno-compat.

                <IconSpeed/>

Insane Performance

One the fastest front-end frameworks for rendering UI in the DOM, making 60 FPS on mobile possible.

                <IconArchitecture/>

One-way Architecture

Component driven + One-way data flow architecture. Bindings also supplied for Redux, MobX or Ceberal.

                <IconIsomorphic/>

Isomorphic

Isomorphic rendering on both client and server, along with fast-booting from server-side renders.

                <IconModular/>

Modular

Highly modular with very little opinion of how things should be done, removing bloat and unecessary overhead.

}
<commit_msg>Fix grammar (#33)<commit_after>import Inferno from 'inferno'
import IconArchitecture from '../icons/IconArchitecture'
import IconCompatible from '../icons/IconCompatible'
import IconIsomorphic from '../icons/IconIsomorphic'
import IconModular from '../icons/IconModular'
import IconSize from '../icons/IconSize'
import IconSpeed from '../icons/IconSpeed'

export default function() {
    return

                <IconSize/>

Tiny Size

Inferno is much smaller in size, 9kb vs 45kb gzip. This means inferno is faster to transfer over the network and much faster to parse.

                <IconCompatible/>

React Compatible

React-like API, concepts and component lifecycle events. Switch over easily with inferno-compat.

                <IconSpeed/>

Insane Performance

One of the fastest front-end frameworks for rendering UI in the DOM, making 60 FPS on mobile possible.

                <IconArchitecture/>

One-way Architecture

Component driven + One-way data flow architecture. Bindings also supplied for Redux, MobX or Ceberal.

                <IconIsomorphic/>

Isomorphic

Isomorphic rendering on both client and server, along with fast-booting from server-side renders.

                <IconModular/>

Modular

Highly modular with very little opinion of how things should be done, removing bloat and unecessary overhead.

}
<|endoftext|>


<commit_before>window.onbeforeunload = function () {
  window.scrollTo(0, 0);
}

$(document).ready(function() {

	var logo = $("#logo-container");
	var typed = $(".typed-holder");
	var cartoon = $("#cartoon-cover");
	var bgImage = $("#full-image-style");
	var tl = new TimelineLite();
	var swan = $(".swan");

	/* SWAN ANIMATION */
	var swanTween = tl.to(swan, 15, {y: "100", x: "700", scale: "1.4", ease: Power1.easeIn})
	.to(swan, 1, {rotationY:180})
	.to(swan, 6, {x: "350", ease: Power1.easeInOut}, "toLeft")
	.to(swan, 6, {y: "150", scale: "1.5", ease: Power1.easeInOut}, "toLeft")
	.to(swan, 2, {y: "+=10", yoyo:true, repeat:-1, delay: "0.2"});

/*
tl.to(typed, 0, {autoAlpha: 0},2)
.to(cartoon, 2, {autoAlpha: 0},"image")
.to(bgImage, 2, {display: "block"},"image")
.to(logo, 5, {ease: Expo.easeOut, top: "20%"});
*/

/* SCROLL MAGIC */
var controller = new ScrollMagic.Controller({
	globalSceneOptions: {
		triggerHook: 'onCenter'
	}
});

/* SLIDES
var slides = document.querySelectorAll("section.panel");
for (var i=0; i<2; i++) {
new ScrollMagic.Scene({
triggerElement: slides[i]
})
.setPin(slides[i])
.addIndicators() // add indicators (requires plugin)
.addTo(controller);
}

var cartoonPn = new ScrollMagic.Scene({triggerElement: "#cartoon-cover", duration: 450})
.setPin("#cartoon-cover")
.offset(100)
.addIndicators() // add indicators (requires plugin)
.addTo(controller);
*/

/* TYPED TEXTS PINNED */
var scene = new ScrollMagic.Scene()
.setPin(".typed-holder")
.addTo(controller);

/* TYPED TEXT DISAPEAR */
var scene = new ScrollMagic.Scene({triggerElement: "#cartoon-cover", duration: 350})
.offset(500)
.setTween(".typed-holder", 0.5, {y:"-=100", autoAlpha:0})
.addIndicators({name: "magic"})
.addTo(controller);

/* TYPED TEXTS */
$("#big-typed").typed({
	strings: ["Suomalainen turve"],
	typeSpeed: 130,
	showCursor: false
});
$("#small-typed").typed({
	strings: ["Hyödyt, haitat ja harhaluulot"],
	typeSpeed: 130,
	showCursor: false,
	startDelay: 3500
});

/* FIRST TEXT-HOLDER PINNED */
var scene = new ScrollMagic.Scene()
.setPin("#first-text-holder")
.addTo(controller);

/* FIRST TEXT-HOLDER APPEARING */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 250})
.offset(200)
.setTween("#first-text-holder", 0.5, {y:"-=250", autoAlpha:1})
.addIndicators({name: "water-text"})
.addTo(controller);

/* WATER PINNED */
var scene = new ScrollMagic.Scene()
.setPin(".moving-water")
.addTo(controller);

/* WATER RISING */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 400})
.offset(370)
.setTween(".moving-water", 0.5, {y:"-=500"})
.addIndicators({name: "water-rising"})
.addTo(controller);

/* GROUND PINNED */
var scene = new ScrollMagic.Scene()
.setPin(".water-ground")
.addTo(controller);

/* WATER GROUND RISING */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 400})
.offset(370)
.setTween(".water-ground", 0.5, {y:"-=115"})
.addIndicators({name: "water-rising"})
.addTo(controller);

/* LEFT ROCK PINNED */
var scene = new ScrollMagic.Scene()
.setPin(".left-rock-holder")
.addTo(controller);

/* LEFT ROCK APPEARING */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section"})
.offset(750)
.setTween(".left-rock-holder", 1, {width:"14%", ease: Elastic.easeOut.config(1, 0.3)})
.addIndicators({name: "water-text"})
.addTo(controller);

/* RIGHT ROCK PINNED */
var scene = new ScrollMagic.Scene()
.setPin(".right-rock-holder")
.addTo(controller);

/* RIGHT ROCK APPEARING */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section"})
.offset(800)
.setTween(".right-rock-holder", 1, {width:"10%", ease: Elastic.easeOut.config(1, 0.3)})
.addIndicators({name: "water-text"})
.addTo(controller);

/* LEFT PLANT PINNED */
var scene = new ScrollMagic.Scene()
.setPin(".left-plant")
.addTo(controller);

/* MIDDLE PLANT PINNED */
var scene = new ScrollMagic.Scene()
.setPin(".middle-plant")
.addTo(controller);

/* RIGHT PLANT PINNED */
var scene = new ScrollMagic.Scene()
.setPin(".right-plant")
.addTo(controller);

/* LEFT PLANT GROW */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section"})
.offset(850)
.setTween(".svg-left", 1, {strokeDashoffset:"0px"})
.addIndicators({name: "stroke"})
.addTo(controller);

/* MIDDLE PLANT GROW */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section"})
.offset(880)
.setTween(".svg-middle", 1.3, {strokeDashoffset:"0px"})
.addIndicators({name: "stroke"})
.addTo(controller);

/* RIGHT PLANT GROW */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section"})
.offset(850)
.setTween(".svg-right", 1.2, {strokeDashoffset:"0px"})
.addIndicators({name: "stroke"})
.addTo(controller);

/* TURVE CREATION HOLDER PIN */
var scene = new ScrollMagic.Scene()
.setPin("#turve-creation-holder")
.addTo(controller);

/* TURVE CREATION APPEARANCE */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 50})
.offset(1000)
.setTween("#turve-creation-holder", 0.5, {y:"-=100", autoAlpha:1})
.addIndicators({name: "creation text"})
.addTo(controller);

/* PLANTS INTO PEAT */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 250})
.offset(900)
.setTween("path", {stroke:"#453B31"})
.addIndicators({name: "stroke"})
.addTo(controller);

TweenMax.staggerTo("svg", 2, {y: "+=5", yoyo:true, repeat:-1, delay: "0.2"}, 0.4)

/* WATER AREA DISAPEAR */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 200})
.offset(1200)
.setTween("path, .left-rock-holder, .right-rock-holder, .moving-water, #first-text-holder, #turve-creation-holder", {y: "-=200",autoAlpha:0})
.addIndicators({name: "stroke"})
.addTo(controller);

var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 200})
.offset(1200)
.setTween(".water-ground", {y: "-=200"})
.addIndicators({name: "stroke"})
.addTo(controller);

var scene = new ScrollMagic.Scene({triggerElement: ".water-section"})
.offset(1400)
.setTween(".water-ground", {autoAlpha: 0})
.addIndicators({name: "stroke"})
.addTo(controller);

/* KASA PIN */
var scene = new ScrollMagic.Scene()
.setPin(".kasa-holder")
.addTo(controller);

/* KASA APPEARANCE */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 100})
.offset(1500)
.setTween(".kasa-holder", 0.5, {autoAlpha:1,width:"80%"})
.addIndicators({name: "kasa"})
.addTo(controller);

/* KASA TEXT PIN */
var scene = new ScrollMagic.Scene()
.setPin("#kasa-text-holder")
.addTo(controller);

/* KASA TEXT APPEARANCE */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 100})
.offset(1600)
.setTween("#kasa-text-holder", 0.2, {y: "=-80", autoAlpha:1})
.addIndicators({name: "kasa"})
.addTo(controller);

/* KASA TEXT PIN
var scene = new ScrollMagic.Scene()
.setPin("#kasa-info-holder")
.addTo(controller);	*/

/* TEXT + KASA HOVER */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section"})
.offset(1700)
.setTween("#kasa-text-holder, .kasa-holder", 2, {y: "+=10", yoyo:true, repeat:-1, delay: "0.2"})
.addIndicators({name: "kasaup"})
.addTo(controller);

/* KASA INFO APPEARANCE */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section"})
.offset(2200)
.setTween("#kasa-info-holder", 0.2, {y: "=-80", autoAlpha:1})
.addIndicators({name: "kasa"})
.addTo(controller);

/* KASA INFO PIN */
var scene = new ScrollMagic.Scene()
.setPin("#kasa-info-holder")
.addTo(controller);

/* MURU HOLDER PIN */
var scene = new ScrollMagic.Scene()
.setPin(".muru-holder")
.addTo(controller);

/* MURU APPEARANCE */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section"})
.offset(1800)
.setTween(".muru-holder", 0.1, {autoAlpha:1})
.addIndicators({name: "muru"})
.addTo(controller);

var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 250})
.offset(1900)
.setTween(".muru-holder", 5, {rotation: 100 ,y: "+=280", x: "-=75" ,autoAlpha:1})
.addIndicators({name: "muru"})
.addTo(controller);

});

<commit_msg>better scrolling speed<commit_after>window.onbeforeunload = function () {
  window.scrollTo(0, 0);
}

$(document).ready(function() {

	var logo = $("#logo-container");
	var typed = $(".typed-holder");
	var cartoon = $("#cartoon-cover");
	var bgImage = $("#full-image-style");
	var tl = new TimelineLite();
	var swan = $(".swan");

	/* SWAN ANIMATION */
	var swanTween = tl.to(swan, 15, {y: "100", x: "700", scale: "1.4", ease: Power1.easeIn})
	.to(swan, 1, {rotationY:180})
	.to(swan, 6, {x: "350", ease: Power1.easeInOut}, "toLeft")
	.to(swan, 6, {y: "150", scale: "1.5", ease: Power1.easeInOut}, "toLeft")
	.to(swan, 2, {y: "+=10", yoyo:true, repeat:-1, delay: "0.2"});

/*
tl.to(typed, 0, {autoAlpha: 0},2)
.to(cartoon, 2, {autoAlpha: 0},"image")
.to(bgImage, 2, {display: "block"},"image")
.to(logo, 5, {ease: Expo.easeOut, top: "20%"});
*/

/* SCROLL MAGIC */
var controller = new ScrollMagic.Controller({
	globalSceneOptions: {
		triggerHook: 'onCenter'
	}
});

/* SLIDES
var slides = document.querySelectorAll("section.panel");
for (var i=0; i<2; i++) {
new ScrollMagic.Scene({
triggerElement: slides[i]
})
.setPin(slides[i])
.addIndicators() // add indicators (requires plugin)
.addTo(controller);
}

var cartoonPn = new ScrollMagic.Scene({triggerElement: "#cartoon-cover", duration: 450})
.setPin("#cartoon-cover")
.offset(100)
.addIndicators() // add indicators (requires plugin)
.addTo(controller);
*/

/* TYPED TEXTS PINNED */
var scene = new ScrollMagic.Scene()
.setPin(".typed-holder")
.addTo(controller);

/* TYPED TEXT DISAPEAR */
var scene = new ScrollMagic.Scene({triggerElement: "#cartoon-cover", duration: 350})
.offset(500)
.setTween(".typed-holder", 0.5, {y:"-=100", autoAlpha:0})
.addIndicators({name: "magic"})
.addTo(controller);

/* TYPED TEXTS */
$("#big-typed").typed({
	strings: ["Suomalainen turve"],
	typeSpeed: 130,
	showCursor: false
});
$("#small-typed").typed({
	strings: ["Hyödyt, haitat ja harhaluulot"],
	typeSpeed: 130,
	showCursor: false,
	startDelay: 3500
});

/* FIRST TEXT-HOLDER PINNED */
var scene = new ScrollMagic.Scene()
.setPin("#first-text-holder")
.addTo(controller);

/* FIRST TEXT-HOLDER APPEARING */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 250})
.offset(200)
.setTween("#first-text-holder", 0.5, {y:"-=250", autoAlpha:1})
.addIndicators({name: "water-text"})
.addTo(controller);

/* WATER PINNED */
var scene = new ScrollMagic.Scene()
.setPin(".moving-water")
.addTo(controller);

/* WATER RISING */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 400})
.offset(370)
.setTween(".moving-water", 0.5, {y:"-=500"})
.addIndicators({name: "water-rising"})
.addTo(controller);

/* GROUND PINNED */
var scene = new ScrollMagic.Scene()
.setPin(".water-ground")
.addTo(controller);

/* WATER GROUND RISING */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 400})
.offset(370)
.setTween(".water-ground", 0.5, {y:"-=115"})
.addIndicators({name: "water-rising"})
.addTo(controller);

/* LEFT ROCK PINNED */
var scene = new ScrollMagic.Scene()
.setPin(".left-rock-holder")
.addTo(controller);

/* LEFT ROCK APPEARING */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section"})
.offset(750)
.setTween(".left-rock-holder", 1, {width:"14%", ease: Elastic.easeOut.config(1, 0.3)})
.addIndicators({name: "water-text"})
.addTo(controller);

/* RIGHT ROCK PINNED */
var scene = new ScrollMagic.Scene()
.setPin(".right-rock-holder")
.addTo(controller);

/* RIGHT ROCK APPEARING */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section"})
.offset(800)
.setTween(".right-rock-holder", 1, {width:"10%", ease: Elastic.easeOut.config(1, 0.3)})
.addIndicators({name: "water-text"})
.addTo(controller);

/* LEFT PLANT PINNED */
var scene = new ScrollMagic.Scene()
.setPin(".left-plant")
.addTo(controller);

/* MIDDLE PLANT PINNED */
var scene = new ScrollMagic.Scene()
.setPin(".middle-plant")
.addTo(controller);

/* RIGHT PLANT PINNED */
var scene = new ScrollMagic.Scene()
.setPin(".right-plant")
.addTo(controller);

/* LEFT PLANT GROW */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 200})
.offset(800)
.setTween(".svg-left", 1, {strokeDashoffset:"0px"})
.addIndicators({name: "stroke"})
.addTo(controller);

/* MIDDLE PLANT GROW */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section",  duration: 200})
.offset(840)
.setTween(".svg-middle", 1.3, {strokeDashoffset:"0px"})
.addIndicators({name: "stroke"})
.addTo(controller);

/* RIGHT PLANT GROW */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section",  duration: 200})
.offset(820)
.setTween(".svg-right", 1.2, {strokeDashoffset:"0px"})
.addIndicators({name: "stroke"})
.addTo(controller);

/* TURVE CREATION HOLDER PIN */
var scene = new ScrollMagic.Scene()
.setPin("#turve-creation-holder")
.addTo(controller);

/* TURVE CREATION APPEARANCE */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 100})
.offset(1150)
.setTween("#turve-creation-holder", 0.5, {y:"-=100", autoAlpha:1})
.addIndicators({name: "creation text"})
.addTo(controller);

/* PLANTS INTO PEAT */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 250})
.offset(1100)
.setTween("path", {stroke:"#453B31"})
.addIndicators({name: "stroke"})
.addTo(controller);

TweenMax.staggerTo("svg", 2, {y: "+=5", yoyo:true, repeat:-1, delay: "0.2"}, 0.4)

/* WATER AREA DISAPEAR */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 200})
.offset(1400)
.setTween("path, .left-rock-holder, .right-rock-holder, .moving-water, #first-text-holder, #turve-creation-holder", {y: "-=200",autoAlpha:0})
.addIndicators({name: "stroke"})
.addTo(controller);

var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 200})
.offset(1400)
.setTween(".water-ground", {y: "-=200"})
.addIndicators({name: "stroke"})
.addTo(controller);

var scene = new ScrollMagic.Scene({triggerElement: ".water-section"})
.offset(1600)
.setTween(".water-ground", {autoAlpha: 0})
.addIndicators({name: "stroke"})
.addTo(controller);

/* KASA PIN */
var scene = new ScrollMagic.Scene()
.setPin(".kasa-holder")
.addTo(controller);

/* KASA APPEARANCE */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 200})
.offset(1700)
.setTween(".kasa-holder", 0.5, {autoAlpha:1,width:"80%"})
.addIndicators({name: "kasa"})
.addTo(controller);

/* KASA TEXT PIN */
var scene = new ScrollMagic.Scene()
.setPin("#kasa-text-holder")
.addTo(controller);

/* KASA TEXT APPEARANCE */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 200})
.offset(1800)
.setTween("#kasa-text-holder", 0.2, {y: "=-80", autoAlpha:1})
.addIndicators({name: "kasa"})
.addTo(controller);

/* KASA TEXT PIN
var scene = new ScrollMagic.Scene()
.setPin("#kasa-info-holder")
.addTo(controller);	*/

/* TEXT + KASA HOVER */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section"})
.offset(1900)
.setTween("#kasa-text-holder, .kasa-holder", 2, {y: "+=10", yoyo:true, repeat:-1, delay: "0.2"})
.addIndicators({name: "kasaup"})
.addTo(controller);

/* KASA INFO APPEARANCE */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section"})
.offset(2400)
.setTween("#kasa-info-holder", 0.2, {y: "=-80", autoAlpha:1})
.addIndicators({name: "kasa"})
.addTo(controller);

/* KASA INFO PIN */
var scene = new ScrollMagic.Scene()
.setPin("#kasa-info-holder")
.addTo(controller);

/* MURU HOLDER PIN */
var scene = new ScrollMagic.Scene()
.setPin(".muru-holder")
.addTo(controller);

/* MURU APPEARANCE */
var scene = new ScrollMagic.Scene({triggerElement: ".water-section"})
.offset(2000)
.setTween(".muru-holder", 0.1, {autoAlpha:1})
.addIndicators({name: "muru"})
.addTo(controller);

var scene = new ScrollMagic.Scene({triggerElement: ".water-section", duration: 250})
.offset(2100)
.setTween(".muru-holder", 5, {rotation: 100 ,y: "+=280", x: "-=75" ,autoAlpha:1})
.addIndicators({name: "muru"})
.addTo(controller);

});

<|endoftext|>


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

/**
 * Represents an mage
 * @param {Object} modem docker-modem
 * @param {String} name  Image's name
 */
var Image = function(modem, name) {
  this.modem = modem;
  this.name = name;
};

/**
 * Inspect
 * @param  {Function} callback Callback, if specified Docker will be queried.
 * @return {Object}            Name only if callback isn't specified.
 */
Image.prototype.inspect = function(callback) {
  if (typeof callback === 'function') {
    var opts = {
      path: '/images/' + this.name + '/json',
      method: 'GET',
      statusCodes: {
        200: true,
        404: 'no such image',
        500: 'server error'
      }
    };

    this.modem.dial(opts, function(err, data) {
      callback(err, data);
    });
  } else {
    return JSON.stringify({name: this.name});
  }
};

/**
 * History
 * @param  {Function} callback Callback
 */
Image.prototype.history = function(callback) {
  var opts = {
    path: '/images/' + this.name + '/history',
    method: 'GET',
    statusCodes: {
      200: true,
      404: 'no such image',
      500: 'server error'
    }
  };

  this.modem.dial(opts, function(err, data) {
    callback(err, data);
  });
};

/**
 * Get
 * @param  {Function} callback Callback with data stream.
 */
Image.prototype.get = function(callback) {
  var opts = {
    path: '/images/' + this.name + '/get',
    method: 'GET',
    isStream: true,
    statusCodes: {
      200: true,
      500: 'server error'
    }
  };

  this.modem.dial(opts, function(err, data) {
    callback(err, data);
  });
};

/**
 * Push
 * @param  {Object}   opts     Push options, like 'registry' (optional)
 * @param  {Function} callback Callback with stream.
 * @param  {Object}   auth     Registry authentication
 */
Image.prototype.push = function(opts, callback, auth) {
  var self = this;
  var optsf = {
    path: '/images/' + this.name + '/push?',
    method: 'POST',
    options: opts,
    authconfig: opts.authconfig || auth,
    isStream: true,
    statusCodes: {
      200: true,
      404: 'no such image',
      500: 'server error'
    }
  };

  delete optsf.options.authconfig;

  this.modem.dial(optsf, function(err, data) {
    callback(err, data);
  });
};

/**
 * Tag
 * @param  {Object}   opts     Tag options, like 'repo' (optional)
 * @param  {Function} callback Callback
 */
Image.prototype.tag = function(opts, callback) {
  var self = this;
  var optsf = {
    path: '/images/' + this.name + '/tag?',
    method: 'POST',
    options: opts,
    statusCodes: {
      200: true, // unofficial, but proxies may return it
      201: true,
      400: 'bad parameter',
      404: 'no such image',
      409: 'conflict',
      500: 'server error'
    }
  };

  this.modem.dial(optsf, function(err, data) {
    callback(err, data);
  });
};

/**
 * Removes the image
 * @param  {[Object]}   opts     Remove options (optional)
 * @param  {Function} callback Callback
 */
Image.prototype.remove = function(opts, callback) {
  var args = util.processArgs(opts, callback);

  var optsf = {
    path: '/images/' + this.name + '?',
    method: 'DELETE',
    statusCodes: {
      200: true,
      404: 'no such image',
      409: 'conflict',
      500: 'server error'
    },
    options: args.opts
  };

  this.modem.dial(optsf, function(err, data) {
    args.callback(err, data);
  });
};

module.exports = Image;
<commit_msg>Update image.js<commit_after>var util = require('./util');

/**
 * Represents an image
 * @param {Object} modem docker-modem
 * @param {String} name  Image's name
 */
var Image = function(modem, name) {
  this.modem = modem;
  this.name = name;
};

/**
 * Inspect
 * @param  {Function} callback Callback, if specified Docker will be queried.
 * @return {Object}            Name only if callback isn't specified.
 */
Image.prototype.inspect = function(callback) {
  if (typeof callback === 'function') {
    var opts = {
      path: '/images/' + this.name + '/json',
      method: 'GET',
      statusCodes: {
        200: true,
        404: 'no such image',
        500: 'server error'
      }
    };

    this.modem.dial(opts, function(err, data) {
      callback(err, data);
    });
  } else {
    return JSON.stringify({name: this.name});
  }
};

/**
 * History
 * @param  {Function} callback Callback
 */
Image.prototype.history = function(callback) {
  var opts = {
    path: '/images/' + this.name + '/history',
    method: 'GET',
    statusCodes: {
      200: true,
      404: 'no such image',
      500: 'server error'
    }
  };

  this.modem.dial(opts, function(err, data) {
    callback(err, data);
  });
};

/**
 * Get
 * @param  {Function} callback Callback with data stream.
 */
Image.prototype.get = function(callback) {
  var opts = {
    path: '/images/' + this.name + '/get',
    method: 'GET',
    isStream: true,
    statusCodes: {
      200: true,
      500: 'server error'
    }
  };

  this.modem.dial(opts, function(err, data) {
    callback(err, data);
  });
};

/**
 * Push
 * @param  {Object}   opts     Push options, like 'registry' (optional)
 * @param  {Function} callback Callback with stream.
 * @param  {Object}   auth     Registry authentication
 */
Image.prototype.push = function(opts, callback, auth) {
  var self = this;
  var optsf = {
    path: '/images/' + this.name + '/push?',
    method: 'POST',
    options: opts,
    authconfig: opts.authconfig || auth,
    isStream: true,
    statusCodes: {
      200: true,
      404: 'no such image',
      500: 'server error'
    }
  };

  delete optsf.options.authconfig;

  this.modem.dial(optsf, function(err, data) {
    callback(err, data);
  });
};

/**
 * Tag
 * @param  {Object}   opts     Tag options, like 'repo' (optional)
 * @param  {Function} callback Callback
 */
Image.prototype.tag = function(opts, callback) {
  var self = this;
  var optsf = {
    path: '/images/' + this.name + '/tag?',
    method: 'POST',
    options: opts,
    statusCodes: {
      200: true, // unofficial, but proxies may return it
      201: true,
      400: 'bad parameter',
      404: 'no such image',
      409: 'conflict',
      500: 'server error'
    }
  };

  this.modem.dial(optsf, function(err, data) {
    callback(err, data);
  });
};

/**
 * Removes the image
 * @param  {[Object]}   opts     Remove options (optional)
 * @param  {Function} callback Callback
 */
Image.prototype.remove = function(opts, callback) {
  var args = util.processArgs(opts, callback);

  var optsf = {
    path: '/images/' + this.name + '?',
    method: 'DELETE',
    statusCodes: {
      200: true,
      404: 'no such image',
      409: 'conflict',
      500: 'server error'
    },
    options: args.opts
  };

  this.modem.dial(optsf, function(err, data) {
    args.callback(err, data);
  });
};

module.exports = Image;
<|endoftext|>