<commit_before>import debounce from 'lodash.debounce'
import { select, addClass } from './utils/dom'
import isMobile from './utils/is-mobile'

const bodyEl = select('body')
let previousWidth = 0

function handleResize() {
	const width = bodyEl.offsetWidth
	if (previousWidth !== width) {
		previousWidth = width
		// resize here
	}
}

function init() {
	// add mobile class to body tag
	if (isMobile.any()) addClass(bodyEl, 'is-mobile')
	// setup resize event
	window.addEventListener('resize', debounce(handleResize, 150))
}

init()
<commit_msg>init graphic<commit_after>import debounce from 'lodash.debounce'
import { select, addClass } from './utils/dom'
import isMobile from './utils/is-mobile'
import graphic from './graphic'

const bodyEl = select('body')
let previousWidth = 0

function handleResize() {
	const width = bodyEl.offsetWidth
	if (previousWidth !== width) {
		previousWidth = width
		graphic.resize()
	}
}

function init() {
	// add mobile class to body tag
	if (isMobile.any()) addClass(bodyEl, 'is-mobile')
	// setup resize event
	window.addEventListener('resize', debounce(handleResize, 150))
	// kick off graphic code
	graphic.init()
}

init()
<|endoftext|>


<commit_before>/**
 * Things to do with Phonegap files
 * Mainly wrappers around their async functions to return Promises
 */

 (function (FMS, Backbone, _, $) {
    _.extend(FMS, {
        files: {
            // move  a file at from a uri to a desination directory. maintains file name
            moveURI: function (srcURI, dest ) {

                var fileEntry;
                return getFileFromURI(srcURI)
                    .pipe( function (file) {
                        fileEntry = file;

                        return getFileSystem();
                    })
                    .pipe( function (filesystem) {
                        console.log('Filesystem returned: ' + filesystem);

                        return getDirectory(filesystem.root, CONFIG.FILES_DIR, {create: true});
                    })
                    .pipe( function(directory) {
                        return moveFile( fileEntry, directory );
                    });
            },

            deleteURI: function (uri) {
                console.log('Deleting URI: ' + uri);

                return getFileFromURI(uri)
                    .pipe( function (file) {
                        var deletingFile = $.Deferred();
                        file.remove(deletingFile.resolve, deletingFile.reject);
                        return deletingFile;
                    });

            },

            // Delete a file from the filesystem
            deleteFile: function (path) {

                console.log('Deleting file: ' + path);

                // Turn path into a filename
                var filename = path.split('/').pop();

                return getFileSystem()
                    .pipe(function (filesystem) {
                        return getDirectory(filesystem.root, CONFIG.FILES_DIR);
                    })
                    .pipe(function (directory) {
                        return getFile(directory, filename, {});
                    })
                    .pipe(function (file) {
                        var deletingFile = $.Deferred();
                        file.remove(deletingFile.resolve, deletingFile.reject);
                        return deletingFile;
                    });

            }
        }
    });

    // Wrap the async Phonegap way of getting a filesystem in a promise
    function getFileSystem() {

        console.log('Getting the file system');

        var filesystem = $.Deferred();

        window.requestFileSystem(
            LocalFileSystem.PERSISTENT,
            0,
            filesystem.resolve,
            filesystem.reject );

        return filesystem.promise();
    }

    // Wrap the async Phonegap way of getting a directory in a promise
    function getDirectory (rootDirectory, path, options) {

        console.log('Getting a directory: ' + path);

        var directory = $.Deferred();

        rootDirectory.getDirectory(path, options, directory.resolve, directory.reject);

        return directory.promise();
    }

    // Wrap the async Phonegap way of getting a file in a promise
    function getFile (directory, path, options) {

        console.log('Getting a file with path: ' + path + ' in directory: ' + directory.fullPath);

        var file = $.Deferred();

        directory.getFile(path, options, file.resolve, file.reject);

        return file.promise();
    }

    function moveFile (src, dest, options) {

        console.log( 'moveing file ' + src.fullPath + ' to ' + dest.fullPath );

        var move = $.Deferred();

        src.moveTo( dest, null, move.resolve, move.reject);

        return move.promise();
    }

    function getFileFromURI(uri) {

        console.log( 'getting file from uri ' + uri );

        var file = $.Deferred();

        window.resolveLocalFileSystemURI( uri, file.resolve, file.reject);

        return file.promise();
    }
})(FMS, Backbone, _, $);
<commit_msg>do not try and move photos if the files are the same<commit_after>/**
 * Things to do with Phonegap files
 * Mainly wrappers around their async functions to return Promises
 */

 (function (FMS, Backbone, _, $) {
    _.extend(FMS, {
        files: {
            // move  a file at from a uri to a desination directory. maintains file name
            moveURI: function (srcURI, dest ) {

                var fileEntry;
                return getFileFromURI(srcURI)
                    .pipe( function (file) {
                        fileEntry = file;

                        return getFileSystem();
                    })
                    .pipe( function (filesystem) {
                        console.log('Filesystem returned: ' + filesystem);

                        return getDirectory(filesystem.root, CONFIG.FILES_DIR, {create: true});
                    })
                    .pipe( function(directory) {
                        return moveFile( fileEntry, directory );
                    });
            },

            deleteURI: function (uri) {
                console.log('Deleting URI: ' + uri);

                return getFileFromURI(uri)
                    .pipe( function (file) {
                        var deletingFile = $.Deferred();
                        file.remove(deletingFile.resolve, deletingFile.reject);
                        return deletingFile;
                    });

            },

            // Delete a file from the filesystem
            deleteFile: function (path) {

                console.log('Deleting file: ' + path);

                // Turn path into a filename
                var filename = path.split('/').pop();

                return getFileSystem()
                    .pipe(function (filesystem) {
                        return getDirectory(filesystem.root, CONFIG.FILES_DIR);
                    })
                    .pipe(function (directory) {
                        return getFile(directory, filename, {});
                    })
                    .pipe(function (file) {
                        var deletingFile = $.Deferred();
                        file.remove(deletingFile.resolve, deletingFile.reject);
                        return deletingFile;
                    });

            }
        }
    });

    // Wrap the async Phonegap way of getting a filesystem in a promise
    function getFileSystem() {

        console.log('Getting the file system');

        var filesystem = $.Deferred();

        window.requestFileSystem(
            LocalFileSystem.PERSISTENT,
            0,
            filesystem.resolve,
            filesystem.reject );

        return filesystem.promise();
    }

    // Wrap the async Phonegap way of getting a directory in a promise
    function getDirectory (rootDirectory, path, options) {

        console.log('Getting a directory: ' + path);

        var directory = $.Deferred();

        rootDirectory.getDirectory(path, options, directory.resolve, directory.reject);

        return directory.promise();
    }

    // Wrap the async Phonegap way of getting a file in a promise
    function getFile (directory, path, options) {

        console.log('Getting a file with path: ' + path + ' in directory: ' + directory.fullPath);

        var file = $.Deferred();

        directory.getFile(path, options, file.resolve, file.reject);

        return file.promise();
    }

    function moveFile (src, dest, options) {

        console.log( 'moveing file ' + src.fullPath + ' to ' + dest.fullPath );

        var move = $.Deferred();

        var destPath = dest.fullPath + '/' + src.name;
        var srcPath = src.fullPath + '';
        if ( srcPath === destPath ) {
            console.log('not moving because files are the same');
            move.resolve( src );
        } else {
            console.log('paths differ so moving');
            src.moveTo( dest, null, move.resolve, move.reject);
        }

        return move.promise();
    }

    function getFileFromURI(uri) {

        console.log( 'getting file from uri ' + uri );

        var file = $.Deferred();

        window.resolveLocalFileSystemURI( uri, file.resolve, file.reject);

        return file.promise();
    }
})(FMS, Backbone, _, $);
<|endoftext|>


<commit_before>var m = require('mithril')

function mithrilDeepCopy (obj) {
  var result = Array.isArray(obj) ? [] : {}

  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      var prop = obj[key]

      switch (typeof prop) {
        case 'function':
          // All function should be m.prop instances.
          result[key] = m.prop(prop())
          break
        case 'object':
          result[key] = mithrilDeepCopy(prop)
          break
        default:
          // Simply copy the value.
          result[key] = prop
      }
    }
  }

  return result
}

var viewmodelFuncObj
var viewmodelCounter = 0

function viewmodel (vmDefaults, propName) {
  propName = propName || viewmodelFuncObj.propName.replace('%', viewmodelCounter++)

  if (typeof vmDefaults !== 'object') {
    throw Error('Viewmodel defaults object must be a JS object.')
  }

  return function (model) {
    if (typeof model !== 'object') {
      throw Error('Model must be a JS object.')
    }

    var viewmodelObj = model[propName]

    if (viewmodelObj === undefined) {
      // Create a new viewmodel.
      viewmodelObj = mithrilDeepCopy(vmDefaults)

      // Assign it.
      Object.defineProperty(model, propName, {
        value: viewmodelObj,
        enumerable: false,
        writable: false
      })
    }

    return viewmodelObj
  }
};

viewmodelFuncObj = viewmodel
viewmodel.propName = '__viewmodel_%__'

module.exports = viewmodel

<commit_msg>Object.hasOwnProperty switched to call via prototype.<commit_after>var m = require('mithril')

function mithrilDeepCopy (obj) {
  var result = Array.isArray(obj) ? [] : {}

  for (var key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      var prop = obj[key]

      switch (typeof prop) {
        case 'function':
          // All function should be m.prop instances.
          result[key] = m.prop(prop())
          break
        case 'object':
          result[key] = mithrilDeepCopy(prop)
          break
        default:
          // Simply copy the value.
          result[key] = prop
      }
    }
  }

  return result
}

var viewmodelFuncObj
var viewmodelCounter = 0

function viewmodel (vmDefaults, propName) {
  propName = propName || viewmodelFuncObj.propName.replace('%', viewmodelCounter++)

  if (typeof vmDefaults !== 'object') {
    throw Error('Viewmodel defaults object must be a JS object.')
  }

  return function (model) {
    if (typeof model !== 'object') {
      throw Error('Model must be a JS object.')
    }

    var viewmodelObj = model[propName]

    if (viewmodelObj === undefined) {
      // Create a new viewmodel.
      viewmodelObj = mithrilDeepCopy(vmDefaults)

      // Assign it.
      Object.defineProperty(model, propName, {
        value: viewmodelObj,
        enumerable: false,
        writable: false
      })
    }

    return viewmodelObj
  }
};

viewmodelFuncObj = viewmodel
viewmodel.propName = '__viewmodel_%__'

module.exports = viewmodel

<|endoftext|>


<commit_before>$(document).ready(function () {
  let bpmCounter = new BpmCounter();
});
<commit_msg>Remove unnecessary code<commit_after><|endoftext|>


<commit_before>var Particle = require('./particles'),
    canvas = document.querySelector('#particlesField'),
    ctx = canvas.getContext('2d'),
    width = window.innerWidth,
    height = window.innerHeight,
    piByPi = Math.PI*2,
    particles = [],

    presetDefault = {
        count: 1000,
        size: 1,
        minSpeed: 10,
        maxSpeed: 50,
        startOrigin: {
            x: undefined,
            y: undefined
        }
    },

    presetFast = {
        count: 1000,
        size: 1,
        minSpeed: 20,
        maxSpeed: 100,
        startOrigin: {
            x: undefined,
            y: undefined
        }
    },

    presetCentralExplode = {
        count: 1000,
        size: 1,
        minSpeed: 1,
        maxSpeed: 100,
        startOrigin: {
            x: width/2,
            y: height/2
        }
    },

    presetInsaneRandomSizeFromLeftTop = {
        count: 2000,
        size: function() {
            return Math.random() * 10 + 1;
        },
        minSpeed: 20,
        maxSpeed: 100,
        startOrigin: {
            x: 1,
            y: 1
        }
    },

    presetInsaneRandomSizeFromCenter = {
        count: 2000,
        size: function() {
            return Math.random() * 2 + 0.2;
        },
        minSpeed: 20,
        maxSpeed: 100,
        startOrigin: {
            x: width/2,
            y: height/2
        }
    },

    settings = presetDefault;

window.generateParticles = function(count, size, originX, originY) {

    while(count--) {
        var x = originX || Math.random() * window.innerWidth,
            y = originY || Math.random() * window.innerHeight;
        (function(particle){
            particles.push(particle);
        })(new Particle(x,y,size));
    }

};

/* ======================= */

resize();

window.addEventListener('resize', resize, false);

generateParticles(settings.count, settings.size, settings.startOrigin.x, settings.startOrigin.y);

animate();

/* ======================= */

function resize() {
    width = window.innerWidth;
    height = window.innerHeight;

    if (particles) {

        for(var i = 0 ; i < particles.length; i++) {
            if(particles[i].position.x > width) {
                particles[i].stop();
                particles[i].position.x = width;
            }

            if(particles[i].position.y > height) {
                particles[i].stop();
                particles[i].position.y = height;
            }

        }
    }

}

function renderCanvas() {

    ctx.globalCompositeOperation = 'destination-out';
    ctx.fillStyle = 'rgba(0,0,0,0.1)';

    ctx.fillRect(0,0,width,height);

    ctx.globalCompositeOperation = 'source-over';
    ctx.fillStyle = "rgba(255,255,255,1)";

    if(particles) {
        for(var i = 0; i < particles.length; i++) {
            var ball = particles[i];
            ctx.beginPath();
            ctx.arc(ball.position.x,ball.position.y,ball.radius,0,piByPi,false);
            ctx.closePath();
            ctx.fill();
        }
    }

}

function animate(time) {
    requestAnimationFrame(animate);

    if(width !== canvas.width) {
        canvas.width = width;
    }

    if(height !== canvas.height) {
        canvas.height = height;
    }

    if(particles) {
        for(var i = 0; i < particles.length; i++) {
            var ball = particles[i];
            if(!ball.getPosition(time)) {
                var x = Math.random() * width,
                    y = Math.random() * height,
                    speed = Math.random() * (settings.maxSpeed / 2) + settings.minSpeed;
                ball.move(x,y,speed);
            }
        }
    }

    renderCanvas();
}

<commit_msg>Упростиль добавление частиц в массив (убрал замыкание, поставил particles.push(new Particle(x,y,size));)<commit_after>var Particle = require('./particles'),
    canvas = document.querySelector('#particlesField'),
    ctx = canvas.getContext('2d'),
    width = window.innerWidth,
    height = window.innerHeight,
    piByPi = Math.PI*2,
    particles = [],

    presetDefault = {
        count: 1000,
        size: 1,
        minSpeed: 10,
        maxSpeed: 50,
        startOrigin: {
            x: undefined,
            y: undefined
        }
    },

    presetFast = {
        count: 1000,
        size: 1,
        minSpeed: 20,
        maxSpeed: 100,
        startOrigin: {
            x: undefined,
            y: undefined
        }
    },

    presetCentralExplode = {
        count: 1000,
        size: 1,
        minSpeed: 1,
        maxSpeed: 100,
        startOrigin: {
            x: width/2,
            y: height/2
        }
    },

    presetInsaneRandomSizeFromLeftTop = {
        count: 2000,
        size: function() {
            return Math.random() * 10 + 1;
        },
        minSpeed: 20,
        maxSpeed: 100,
        startOrigin: {
            x: 1,
            y: 1
        }
    },

    presetInsaneRandomSizeFromCenter = {
        count: 2000,
        size: function() {
            return Math.random() * 2 + 0.2;
        },
        minSpeed: 20,
        maxSpeed: 100,
        startOrigin: {
            x: width/2,
            y: height/2
        }
    },

    settings = presetDefault;

window.generateParticles = function(count, size, originX, originY) {

    while(count--) {
        var x = originX || Math.random() * window.innerWidth,
            y = originY || Math.random() * window.innerHeight;

        particles.push(new Particle(x,y,size));
    }

};

/* ======================= */

resize();

window.addEventListener('resize', resize, false);

generateParticles(settings.count, settings.size, settings.startOrigin.x, settings.startOrigin.y);

animate();

/* ======================= */

function resize() {
    width = window.innerWidth;
    height = window.innerHeight;

    if (particles) {

        for(var i = 0 ; i < particles.length; i++) {
            if(particles[i].position.x > width) {
                particles[i].stop();
                particles[i].position.x = width;
            }

            if(particles[i].position.y > height) {
                particles[i].stop();
                particles[i].position.y = height;
            }

        }
    }

}

function renderCanvas() {

    ctx.globalCompositeOperation = 'destination-out';
    ctx.fillStyle = 'rgba(0,0,0,0.1)';

    ctx.fillRect(0,0,width,height);

    ctx.globalCompositeOperation = 'source-over';
    ctx.fillStyle = "rgba(255,255,255,1)";

    if(particles) {
        for(var i = 0; i < particles.length; i++) {
            var ball = particles[i];
            ctx.beginPath();
            ctx.arc(ball.position.x,ball.position.y,ball.radius,0,piByPi,false);
            ctx.closePath();
            ctx.fill();
        }
    }

}

function animate(time) {
    requestAnimationFrame(animate);

    if(width !== canvas.width) {
        canvas.width = width;
    }

    if(height !== canvas.height) {
        canvas.height = height;
    }

    if(particles) {
        for(var i = 0; i < particles.length; i++) {
            var ball = particles[i];
            if(!ball.getPosition(time)) {
                var x = Math.random() * width,
                    y = Math.random() * height,
                    speed = Math.random() * (settings.maxSpeed / 2) + settings.minSpeed;
                ball.move(x,y,speed);
            }
        }
    }

    renderCanvas();
}

<|endoftext|>


<commit_before>/* eslint-disable no-unused-vars */
import React from "react";
/* eslint-enable no-unused-vars */
import ReactDOM from "react-dom";
import { I18nProvider } from "@lingui/react";
import { RequestUtil } from "mesosphere-shared-reactjs";
import { Router, hashHistory } from "react-router";
import { Provider } from "react-redux";
import PluginSDK from "PluginSDK";

import en from "#LOCALE/en/messages.js";
import zh from "#LOCALE/zh/messages.js";

// Load in our CSS.
// TODO - DCOS-6452 - remove component @imports from index.less and
// require them in the component.js
import "../styles/index.less";
import "./utils/MomentJSConfig";
import { CONFIG_ERROR, LANGUAGE_MODAL_CLOSE } from "./constants/EventTypes";
import ApplicationUtil from "./utils/ApplicationUtil";
import appRoutes from "./routes/index";
import ConfigStore from "./stores/ConfigStore";
import UserLanguageStore from "./stores/UserLanguageStore";
import LanguageModalStore from "./stores/LanguageModalStore";
import NavigationServiceUtil from "./utils/NavigationServiceUtil";
import RequestErrorMsg from "./components/RequestErrorMsg";
import RouterUtil from "./utils/RouterUtil";

const domElement = global.document.getElementById("application");
const initialLanguage = UserLanguageStore.get();

// TODO: Implement loader that can concat many sprites into a single one
// We opt to load the sprite after the Javscript files are parsed because it
// is quite expensive for the browser to parse a sprite file. This way we
// don't block the JS execution.
setTimeout(function() {
  var ajax = new XMLHttpRequest();
  ajax.open("GET", "/assets/sprite.svg", true);
  ajax.send();
  ajax.onload = function() {
    var div = global.document.createElement("div");
    div.innerHTML = ajax.responseText;
    div.style.height = 0;
    div.style.overflow = "hidden";
    div.style.width = 0;
    div.style.visibility = "hidden";
    global.document.body.insertBefore(div, global.document.body.childNodes[0]);
  };
});

// Patch json
const oldJSON = RequestUtil.json;
RequestUtil.json = function(options = {}) {
  // Proxy error function so that we can trigger a plugin event
  const oldHandler = options.error;
  options.error = function() {
    if (typeof oldHandler === "function") {
      oldHandler.apply(null, arguments);
    }
    PluginSDK.Hooks.doAction("AJAXRequestError", ...arguments);
  };

  oldJSON(options);
};

(function() {
  function renderApplication() {
    function renderAppToDOM(content) {
      ReactDOM.render(content, domElement, function() {
        PluginSDK.Hooks.doAction("applicationRendered");
      });
    }

    // Allow overriding of application contents
    const contents = PluginSDK.Hooks.applyFilter("applicationContents", null);
    if (contents) {
      renderAppToDOM(contents);
    } else {
      if (PluginSDK.Hooks.applyFilter("delayApplicationLoad", true)) {
        // Let's make sure we get Mesos Summary data before we render app
        // Mesos may unreachable, so we will render even on request failure
        ApplicationUtil.beginTemporaryPolling(function() {
          ApplicationUtil.invokeAfterPageLoad(renderApplicationToDOM);
        });
      } else {
        renderApplicationToDOM();
      }

      function renderApplicationToDOM() {
        const routes = RouterUtil.buildRoutes(appRoutes.getRoutes());
        NavigationServiceUtil.registerRoutesInNavigation(routes[0].childRoutes);

        renderAppToDOM(
          <Provider store={PluginSDK.Store}>
            <I18nProvider
              defaultRender="span"
              language={UserLanguageStore.get()}
              catalogs={{ en, zh }}
            >
              <Router history={hashHistory} routes={routes} />
            </I18nProvider>
          </Provider>
        );

        PluginSDK.Hooks.doAction("routes", routes);
      }
    }
  }

  function onPluginsLoaded() {
    PluginSDK.Hooks.removeAction("pluginsConfigured", onPluginsLoaded);
    ConfigStore.removeChangeListener(CONFIG_ERROR, onConfigurationError);
    renderApplication();
  }

  function onConfigurationError() {
    // Try to find appropriate DOM element or fallback
    const element = global.document.querySelector("#canvas div") || domElement;
    const columnClasses = {
      "column-small-8": false,
      "column-small-offset-2": false,
      "column-medium-6": false,
      "column-medium-offset-3": false
    };

    ReactDOM.render(
      <RequestErrorMsg
        columnClasses={columnClasses}
        header="Error requesting UI Configuration"
      />,
      element
    );
  }

  function handleLanguageChange() {
    if (initialLanguage !== UserLanguageStore.get()) {
      global.location.reload();
    }
  }

  function startApplication() {
    // Plugins events
    PluginSDK.Hooks.addAction("pluginsConfigured", onPluginsLoaded);
    ConfigStore.addChangeListener(CONFIG_ERROR, onConfigurationError);

    // Language change
    LanguageModalStore.addChangeListener(
      LANGUAGE_MODAL_CLOSE,
      handleLanguageChange
    );

    // Load configuration
    ConfigStore.fetchConfig();
  }

  if (!global.Intl) {
    require.ensure(["intl", "intl/locale-data/jsonp/en.js"], function(require) {
      require("intl");
      require("intl/locale-data/jsonp/en.js");

      startApplication();
    });
  } else {
    startApplication();
  }
})();
<commit_msg>fix(index): polyfill Symbol.observable at root<commit_after>/* eslint-disable no-unused-vars */
import React from "react";
/* eslint-enable no-unused-vars */
import ReactDOM from "react-dom";
import { I18nProvider } from "@lingui/react";
import { RequestUtil } from "mesosphere-shared-reactjs";
import { Router, hashHistory } from "react-router";
import { Provider } from "react-redux";
import PluginSDK from "PluginSDK";

// This polyfills Symbol.observable which is required for rxjs to recognize the object received
// from componentFromStream as an Observable, otherwise it throws the TypeError.
// Can be removed if recompose library usage is removed.
import "symbol-observable";

import en from "#LOCALE/en/messages.js";
import zh from "#LOCALE/zh/messages.js";

// Load in our CSS.
// TODO - DCOS-6452 - remove component @imports from index.less and
// require them in the component.js
import "../styles/index.less";
import "./utils/MomentJSConfig";
import { CONFIG_ERROR, LANGUAGE_MODAL_CLOSE } from "./constants/EventTypes";
import ApplicationUtil from "./utils/ApplicationUtil";
import appRoutes from "./routes/index";
import ConfigStore from "./stores/ConfigStore";
import UserLanguageStore from "./stores/UserLanguageStore";
import LanguageModalStore from "./stores/LanguageModalStore";
import NavigationServiceUtil from "./utils/NavigationServiceUtil";
import RequestErrorMsg from "./components/RequestErrorMsg";
import RouterUtil from "./utils/RouterUtil";

const domElement = global.document.getElementById("application");
const initialLanguage = UserLanguageStore.get();

// TODO: Implement loader that can concat many sprites into a single one
// We opt to load the sprite after the Javscript files are parsed because it
// is quite expensive for the browser to parse a sprite file. This way we
// don't block the JS execution.
setTimeout(function() {
  var ajax = new XMLHttpRequest();
  ajax.open("GET", "/assets/sprite.svg", true);
  ajax.send();
  ajax.onload = function() {
    var div = global.document.createElement("div");
    div.innerHTML = ajax.responseText;
    div.style.height = 0;
    div.style.overflow = "hidden";
    div.style.width = 0;
    div.style.visibility = "hidden";
    global.document.body.insertBefore(div, global.document.body.childNodes[0]);
  };
});

// Patch json
const oldJSON = RequestUtil.json;
RequestUtil.json = function(options = {}) {
  // Proxy error function so that we can trigger a plugin event
  const oldHandler = options.error;
  options.error = function() {
    if (typeof oldHandler === "function") {
      oldHandler.apply(null, arguments);
    }
    PluginSDK.Hooks.doAction("AJAXRequestError", ...arguments);
  };

  oldJSON(options);
};

(function() {
  function renderApplication() {
    function renderAppToDOM(content) {
      ReactDOM.render(content, domElement, function() {
        PluginSDK.Hooks.doAction("applicationRendered");
      });
    }

    // Allow overriding of application contents
    const contents = PluginSDK.Hooks.applyFilter("applicationContents", null);
    if (contents) {
      renderAppToDOM(contents);
    } else {
      if (PluginSDK.Hooks.applyFilter("delayApplicationLoad", true)) {
        // Let's make sure we get Mesos Summary data before we render app
        // Mesos may unreachable, so we will render even on request failure
        ApplicationUtil.beginTemporaryPolling(function() {
          ApplicationUtil.invokeAfterPageLoad(renderApplicationToDOM);
        });
      } else {
        renderApplicationToDOM();
      }

      function renderApplicationToDOM() {
        const routes = RouterUtil.buildRoutes(appRoutes.getRoutes());
        NavigationServiceUtil.registerRoutesInNavigation(routes[0].childRoutes);

        renderAppToDOM(
          <Provider store={PluginSDK.Store}>
            <I18nProvider
              defaultRender="span"
              language={UserLanguageStore.get()}
              catalogs={{ en, zh }}
            >
              <Router history={hashHistory} routes={routes} />
            </I18nProvider>
          </Provider>
        );

        PluginSDK.Hooks.doAction("routes", routes);
      }
    }
  }

  function onPluginsLoaded() {
    PluginSDK.Hooks.removeAction("pluginsConfigured", onPluginsLoaded);
    ConfigStore.removeChangeListener(CONFIG_ERROR, onConfigurationError);
    renderApplication();
  }

  function onConfigurationError() {
    // Try to find appropriate DOM element or fallback
    const element = global.document.querySelector("#canvas div") || domElement;
    const columnClasses = {
      "column-small-8": false,
      "column-small-offset-2": false,
      "column-medium-6": false,
      "column-medium-offset-3": false
    };

    ReactDOM.render(
      <RequestErrorMsg
        columnClasses={columnClasses}
        header="Error requesting UI Configuration"
      />,
      element
    );
  }

  function handleLanguageChange() {
    if (initialLanguage !== UserLanguageStore.get()) {
      global.location.reload();
    }
  }

  function startApplication() {
    // Plugins events
    PluginSDK.Hooks.addAction("pluginsConfigured", onPluginsLoaded);
    ConfigStore.addChangeListener(CONFIG_ERROR, onConfigurationError);

    // Language change
    LanguageModalStore.addChangeListener(
      LANGUAGE_MODAL_CLOSE,
      handleLanguageChange
    );

    // Load configuration
    ConfigStore.fetchConfig();
  }

  if (!global.Intl) {
    require.ensure(["intl", "intl/locale-data/jsonp/en.js"], function(require) {
      require("intl");
      require("intl/locale-data/jsonp/en.js");

      startApplication();
    });
  } else {
    startApplication();
  }
})();
<|endoftext|>


<commit_before>'use strict';

var messageKeys = require('message_keys');
var objectToMessageKeys = require('./utils').objectToMessageKeys;
var serialize = require('./lib/serialize');
var Plite = require('plite');

/**
 * @return {void}
 */
var simpleAppMessage = {};

simpleAppMessage._chunkSize = 0;
simpleAppMessage._timeout = 10000;
simpleAppMessage._chunkDelay = 500;
simpleAppMessage._maxNamespaceLenth = 16;

/**
 * @param {string} namespace
 * @param {object} data
 * @param {function} callback
 * @return {void}
 */
simpleAppMessage.send = function(namespace, data, callback) {
  var self = this;
  var requestTimeout;

  var chunkSizeResponseHandler = function(e) {
    var chunkSize = e.payload[messageKeys.SIMPLE_APP_MESSAGE_CHUNK_SIZE];

    // this app message was not meant for us.
    if (typeof chunkSize === 'undefined') {
      return;
    }

    Pebble.removeEventListener('appmessage', chunkSizeResponseHandler);
    clearTimeout(requestTimeout);

    if (!chunkSize || chunkSize <= 0) {
      throw new Error('simpleAppMessage: Fetched chunk size is invalid.');
    }

    self._chunkSize = chunkSize;
    self._sendData(namespace, data, callback);
  };

  if (namespace.length > simpleAppMessage._maxNamespaceLenth) {
    callback({
      error: 'simpleAppMessage: namespace length must not exceed ' +
             simpleAppMessage._maxNamespaceLenth
    });
    return;
  }

  if (!self._chunkSize) {

    // fetch chunk size
    Pebble.addEventListener('appmessage', chunkSizeResponseHandler);

    Pebble.sendAppMessage(
      objectToMessageKeys({SIMPLE_APP_MESSAGE_CHUNK_SIZE: 1}),
      function() {},
      function(error) {
        console.log('simpleAppMessage: Failed to request chunk size.');
        console.log(JSON.stringify(error));
        callback(error);
      }
    );

    requestTimeout = setTimeout(function() {
      Pebble.removeEventListener('appmessage', chunkSizeResponseHandler);
      callback('simpleAppMessage: Request for chunk size timed out.');
    }, self._timeout);
  } else {
    self._sendData(namespace, data, callback);
  }
};

/**
 * @private
 * @param {string} namespace
 * @param {object} data
 * @param {function} callback
 * @return {void}
 */
simpleAppMessage._sendData = function(namespace, data, callback) {
  var self = this;
  var dataSerialized = serialize(data);
  var chunks = [];

  if (!self._chunkSize) {
    throw new Error('simpleAppMessage: Chunk size is invalid');
  }

  while (dataSerialized.length > 0) {
    chunks.push(dataSerialized.splice(0, self._chunkSize));
  }

  var chain = Plite.resolve(true);
  chunks.forEach(function(chunk, index) {
    chain = chain.then(function() {
      var remaining = chunks.length - index - 1;
      return self._sendChunk(namespace, chunk, remaining, chunks.length);
    });
  });

  chain = chain.then(callback);
  chain = chain.catch(callback);
};

/**
 * @private
 * @param {string} namespace
 * @param {object} data
 * @param {number} remaining - remaining chunks
 * @param {number} total - total number of chunks
 * @return {Plite}
 */
simpleAppMessage._sendChunk = function(namespace, data, remaining, total) {
  return Plite(function(resolve, reject) {
    setTimeout(function() {
      Pebble.sendAppMessage(objectToMessageKeys({
        SIMPLE_APP_MESSAGE_CHUNK_DATA: data,
        SIMPLE_APP_MESSAGE_CHUNK_REMAINING: remaining,
        SIMPLE_APP_MESSAGE_CHUNK_TOTAL: total,
        SIMPLE_APP_MESSAGE_CHUNK_NAMESPACE: namespace
      }), resolve, reject);
    }, simpleAppMessage._chunkDelay);
  });
};

module.exports = simpleAppMessage;
<commit_msg>Reduce delay to 100 ms<commit_after>'use strict';

var messageKeys = require('message_keys');
var objectToMessageKeys = require('./utils').objectToMessageKeys;
var serialize = require('./lib/serialize');
var Plite = require('plite');

/**
 * @return {void}
 */
var simpleAppMessage = {};

simpleAppMessage._chunkSize = 0;
simpleAppMessage._timeout = 10000;
simpleAppMessage._chunkDelay = 100;
simpleAppMessage._maxNamespaceLenth = 16;

/**
 * @param {string} namespace
 * @param {object} data
 * @param {function} callback
 * @return {void}
 */
simpleAppMessage.send = function(namespace, data, callback) {
  var self = this;
  var requestTimeout;

  var chunkSizeResponseHandler = function(e) {
    var chunkSize = e.payload[messageKeys.SIMPLE_APP_MESSAGE_CHUNK_SIZE];

    // this app message was not meant for us.
    if (typeof chunkSize === 'undefined') {
      return;
    }

    Pebble.removeEventListener('appmessage', chunkSizeResponseHandler);
    clearTimeout(requestTimeout);

    if (!chunkSize || chunkSize <= 0) {
      throw new Error('simpleAppMessage: Fetched chunk size is invalid.');
    }

    self._chunkSize = chunkSize;
    self._sendData(namespace, data, callback);
  };

  if (namespace.length > simpleAppMessage._maxNamespaceLenth) {
    callback({
      error: 'simpleAppMessage: namespace length must not exceed ' +
             simpleAppMessage._maxNamespaceLenth
    });
    return;
  }

  if (!self._chunkSize) {

    // fetch chunk size
    Pebble.addEventListener('appmessage', chunkSizeResponseHandler);

    Pebble.sendAppMessage(
      objectToMessageKeys({SIMPLE_APP_MESSAGE_CHUNK_SIZE: 1}),
      function() {},
      function(error) {
        console.log('simpleAppMessage: Failed to request chunk size.');
        console.log(JSON.stringify(error));
        callback(error);
      }
    );

    requestTimeout = setTimeout(function() {
      Pebble.removeEventListener('appmessage', chunkSizeResponseHandler);
      callback('simpleAppMessage: Request for chunk size timed out.');
    }, self._timeout);
  } else {
    self._sendData(namespace, data, callback);
  }
};

/**
 * @private
 * @param {string} namespace
 * @param {object} data
 * @param {function} callback
 * @return {void}
 */
simpleAppMessage._sendData = function(namespace, data, callback) {
  var self = this;
  var dataSerialized = serialize(data);
  var chunks = [];

  if (!self._chunkSize) {
    throw new Error('simpleAppMessage: Chunk size is invalid');
  }

  while (dataSerialized.length > 0) {
    chunks.push(dataSerialized.splice(0, self._chunkSize));
  }

  var chain = Plite.resolve(true);
  chunks.forEach(function(chunk, index) {
    chain = chain.then(function() {
      var remaining = chunks.length - index - 1;
      return self._sendChunk(namespace, chunk, remaining, chunks.length);
    });
  });

  chain = chain.then(callback);
  chain = chain.catch(callback);
};

/**
 * @private
 * @param {string} namespace
 * @param {object} data
 * @param {number} remaining - remaining chunks
 * @param {number} total - total number of chunks
 * @return {Plite}
 */
simpleAppMessage._sendChunk = function(namespace, data, remaining, total) {
  return Plite(function(resolve, reject) {
    setTimeout(function() {
      Pebble.sendAppMessage(objectToMessageKeys({
        SIMPLE_APP_MESSAGE_CHUNK_DATA: data,
        SIMPLE_APP_MESSAGE_CHUNK_REMAINING: remaining,
        SIMPLE_APP_MESSAGE_CHUNK_TOTAL: total,
        SIMPLE_APP_MESSAGE_CHUNK_NAMESPACE: namespace
      }), resolve, reject);
    }, simpleAppMessage._chunkDelay);
  });
};

module.exports = simpleAppMessage;
<|endoftext|>


<commit_before>'use strict';

import $ from 'jquery';
import _ from 'lodash';
import Promise from 'bluebird';
import '../../lib/jquery.selection';
import '../../lib/jquery.esarea';
import Ui from './ui';
import Post from './post';
import Esa from './esa';

let ui = new Ui();
let post = new Post();
let esa;

const loadPost = function() {
  post.load(function(post) {
    ui.toggleDisabledSaveButton(post.saved);

    ui.title = post.title;
    ui.body = post.body;
    if (ui.title != '') {
      // Move cursor at previous position
      ui.cursorPosition = post.cursorPosition;
    }
  });
};

const getConfig = function() {
  return new Promise(function(resolve, reject) {
    let defaultConfig = { teamName: '', token: '', teamIcon: '', postId: '' };
    chrome.storage.sync.get(defaultConfig, function(config) {
      if (!config.teamName || !config.token) {
        ui.toggleDisplayOptionLink(true);
        ui.teamName = 'Configuration failed';

        reject('Please configure options (\\( ˘⊖˘)/)');
      } else {
        esa = new Esa(config);

        ui.toggleDisplayOptionLink(false);

        if (config.postId != '') {
          let link = `https://${config.teamName}.esa.io/posts/${config.postId}`;
          ui.savedPostLink = link;
        }

        ui.teamName = config.teamName;
        ui.teamIcon = config.teamIcon;

        resolve(config);
      }
    });
  });
};

const searchPost = function(config) {
  return new Promise(function(resolve, reject) {
    let [category, title] = splitCategory(ui.title);

    let q = `name:${title}`;
    if (category.length != 0) q = `${q} category:${category}`;

    let setConfigFunc = function(response) {
      // nameによる検索は部分一致のため、完全一致させるために検索結果から更に絞り込んでいる
      let hitPost = filterPosts(title, category, response);

      // 記事があった場合は更新するためIDを保存する
      if (hitPost) {
        config.postId = hitPost.number;
      } else {
        config.postId = undefined;
      }
      chrome.storage.sync.set(config, function() {
        resolve(config);
      });
    };

    esa.search(q, setConfigFunc, reject);
  });
};

const splitCategory = function(fullNameAsTitle) {
  if (!hasCategory(fullNameAsTitle)) return ['', fullNameAsTitle];
  else {
    let category = /(.+)\/.+/.exec(fullNameAsTitle)[1];
    let title = /.+\/(.+)/.exec(fullNameAsTitle)[1];

    return [category, title];
  }
};

const filterPosts = function(title, category, response) {
  let filterQuery = { name: title };
  if (category.length == 0) {
    filterQuery.category = null;
  } else {
    filterQuery.category = category;
  }
  return _.find(response.posts, filterQuery);
};

const savePost = function(config) {
  return new Promise(function(resolve, reject) {
    let postData = {
      id: config.postId,
      body_md: ui.body,
      message: 'from tsuibami',
    };

    let [category, title] = splitCategory(ui.title);
    postData.category = category;
    postData.name = title;

    esa.save(postData, resolve, reject);
  });
};

const updateStoredPost = function(response) {
  let newPostId = response.number;

  post.saved = true;
  post.postId = newPostId;
  if (ui.isClearCheckBoxChecked) {
    post.title = '';
    post.body = '';
    post.cursorPosition = 0;
  } else {
    // 保存したタイトルによっては末尾に "(2)" などの表記がesaによってつけられていたり、タイトル無しで保存した場合にカテゴリが変わっている可能性があるため、再度表示し直す
    post.title = response.full_name;
  }

  return new Promise(function(resolve, reject) {
    post.store(
      () => {
        resolve(response);
      },
      () => {
        reject(response);
      },
    );
  });
};

const updateUI = function(response) {
  ui.toggleDisabledSaveButton(true);

  ui.title = post.title;
  ui.body = post.body;

  ui.savedPostLink = response.url;

  let message;
  // 最初の保存の時だけメッセージを変える
  if (response.revision_number == 1) {
    message = 'created!';
  } else {
    message = 'updated!';
  }
  notifySuccess(message);
};

const hasCategory = function(title) {
  return /.+\/.+/.test(title);
};

const notifySuccess = function(msg) {
  showMessage(msg + ' (\\( ⁰⊖⁰)/)', true);
};

const notifyError = function(msg) {
  console.log(msg);
  showMessage(msg);
};

const showMessage = function(message, succeeded) {
  if (succeeded) {
    ui.messageArea.showMessageOnSuccess(message);
  } else {
    ui.messageArea.showMessageOnFailure(message);
  }
};

const storeTitle = function() {
  let title = ui.title;

  if (title != post.title) {
    post.title = title;
    post.saved = false;
    post.store(function() {}, showErrorMessage);
    ui.toggleDisabledSaveButton(false);
  }
};

const storeBody = function() {
  let body = ui.body;

  if (body != post.body) {
    post.body = body;
    post.saved = false;
    ui.toggleDisabledSaveButton(false);
  }

  let cursorPosition = ui.cursorPosition;
  if (cursorPosition != post.cursorPosition) {
    post.cursorPosition = cursorPosition;
  }
  post.store(function() {}, showErrorMessage);
};

const storeCursorPosition = function() {
  let cursorPosition = ui.cursorPosition;
  if (cursorPosition != post.cursorPosition) {
    post.cursorPosition = cursorPosition;
    post.store(function() {}, showErrorMessage);
  }
};

const showErrorMessage = function() {
  let message;
  if (chrome.runtime.lastError === undefined) message = 'unknown error';
  else message = chrome.runtime.lastError.message;

  showMessage('Error: ' + message, false);
};

const runSaveProcess = function() {
  ui.toggleDisabledSaveButton(true);
  ui.toggleSavedStatusMessage(true);
  getConfig()
    .then(searchPost)
    .then(savePost)
    .then(updateStoredPost)
    .then(updateUI)
    .catch(notifyError)
    .finally(function() {
      ui.toggleSavedStatusMessage(false);
    });
};

const runSaveProcessByShortcut = function(event) {
  // Ctrl+s or Cmd+s
  if ((event.metaKey || event.ctrlKey) && event.keyCode == 83) {
    event.preventDefault();
    runSaveProcess();
  }
};

$(function() {
  loadPost();
  getConfig().catch(notifyError);

  ui.titleDom.on('keyup', _.debounce(storeTitle, 200));
  ui.bodyDom.on('keyup', _.debounce(storeBody, 200));
  ui.bodyDom.on('mouseup', storeCursorPosition);

  ui.titleDom.on('keydown', runSaveProcessByShortcut);
  ui.bodyDom.on('keydown', runSaveProcessByShortcut);

  ui.bodyDom.esarea();

  ui.postButtonDom.on('click', runSaveProcess);
});
<commit_msg>Show more meaningfull error messages<commit_after>'use strict';

import $ from 'jquery';
import _ from 'lodash';
import Promise from 'bluebird';
import '../../lib/jquery.selection';
import '../../lib/jquery.esarea';
import Ui from './ui';
import Post from './post';
import Esa from './esa';

let ui = new Ui();
let post = new Post();
let esa;

const loadPost = function() {
  post.load(function(post) {
    ui.toggleDisabledSaveButton(post.saved);

    ui.title = post.title;
    ui.body = post.body;
    if (ui.title != '') {
      // Move cursor at previous position
      ui.cursorPosition = post.cursorPosition;
    }
  });
};

const getConfig = function() {
  return new Promise(function(resolve, reject) {
    let defaultConfig = { teamName: '', token: '', teamIcon: '', postId: '' };
    chrome.storage.sync.get(defaultConfig, function(config) {
      if (!config.teamName || !config.token) {
        ui.toggleDisplayOptionLink(true);
        ui.teamName = 'Configuration failed';

        reject('Please configure options (\\( ˘⊖˘)/)');
      } else {
        esa = new Esa(config);

        ui.toggleDisplayOptionLink(false);

        if (config.postId != '') {
          let link = `https://${config.teamName}.esa.io/posts/${config.postId}`;
          ui.savedPostLink = link;
        }

        ui.teamName = config.teamName;
        ui.teamIcon = config.teamIcon;

        resolve(config);
      }
    });
  });
};

const searchPost = function(config) {
  return new Promise(function(resolve, reject) {
    let [category, title] = splitCategory(ui.title);

    let q = `name:${title}`;
    if (category.length != 0) q = `${q} category:${category}`;

    let setConfigFunc = function(response) {
      // nameによる検索は部分一致のため、完全一致させるために検索結果から更に絞り込んでいる
      let hitPost = filterPosts(title, category, response);

      // 記事があった場合は更新するためIDを保存する
      if (hitPost) {
        config.postId = hitPost.number;
      } else {
        config.postId = undefined;
      }
      chrome.storage.sync.set(config, function() {
        resolve(config);
      });
    };

    esa.search(q, setConfigFunc, reject);
  });
};

const splitCategory = function(fullNameAsTitle) {
  if (!hasCategory(fullNameAsTitle)) return ['', fullNameAsTitle];
  else {
    let category = /(.+)\/.+/.exec(fullNameAsTitle)[1];
    let title = /.+\/(.+)/.exec(fullNameAsTitle)[1];

    return [category, title];
  }
};

const filterPosts = function(title, category, response) {
  let filterQuery = { name: title };
  if (category.length == 0) {
    filterQuery.category = null;
  } else {
    filterQuery.category = category;
  }
  return _.find(response.posts, filterQuery);
};

const savePost = function(config) {
  return new Promise(function(resolve, reject) {
    let postData = {
      id: config.postId,
      body_md: ui.body,
      message: 'from tsuibami',
    };

    let [category, title] = splitCategory(ui.title);
    postData.category = category;
    postData.name = title;

    esa.save(postData, resolve, reject);
  });
};

const updateStoredPost = function(response) {
  let newPostId = response.number;

  post.saved = true;
  post.postId = newPostId;
  if (ui.isClearCheckBoxChecked) {
    post.title = '';
    post.body = '';
    post.cursorPosition = 0;
  } else {
    // 保存したタイトルによっては末尾に "(2)" などの表記がesaによってつけられていたり、タイトル無しで保存した場合にカテゴリが変わっている可能性があるため、再度表示し直す
    post.title = response.full_name;
  }

  return new Promise(function(resolve, reject) {
    post.store(
      () => {
        resolve(response);
      },
      () => {
        reject(response);
      },
    );
  });
};

const updateUI = function(response) {
  ui.toggleDisabledSaveButton(true);

  ui.title = post.title;
  ui.body = post.body;

  ui.savedPostLink = response.url;

  let message;
  // 最初の保存の時だけメッセージを変える
  if (response.revision_number == 1) {
    message = 'created!';
  } else {
    message = 'updated!';
  }
  notifySuccess(message);
};

const hasCategory = function(title) {
  return /.+\/.+/.test(title);
};

const notifySuccess = function(msg) {
  showMessage(msg + ' (\\( ⁰⊖⁰)/)', true);
};

const notifyError = function(msg) {
  console.log(msg);
  let message = msg.hasOwnProperty('statusText') ? msg.statusText : msg;
  message = msg.hasOwnProperty('status')
    ? `${message} (${msg.status})`
    : message;
  showMessage(message);
};

const showMessage = function(message, succeeded) {
  if (succeeded) {
    ui.messageArea.showMessageOnSuccess(message);
  } else {
    ui.messageArea.showMessageOnFailure(message);
  }
};

const storeTitle = function() {
  let title = ui.title;

  if (title != post.title) {
    post.title = title;
    post.saved = false;
    post.store(function() {}, showErrorMessage);
    ui.toggleDisabledSaveButton(false);
  }
};

const storeBody = function() {
  let body = ui.body;

  if (body != post.body) {
    post.body = body;
    post.saved = false;
    ui.toggleDisabledSaveButton(false);
  }

  let cursorPosition = ui.cursorPosition;
  if (cursorPosition != post.cursorPosition) {
    post.cursorPosition = cursorPosition;
  }
  post.store(function() {}, showErrorMessage);
};

const storeCursorPosition = function() {
  let cursorPosition = ui.cursorPosition;
  if (cursorPosition != post.cursorPosition) {
    post.cursorPosition = cursorPosition;
    post.store(function() {}, showErrorMessage);
  }
};

const showErrorMessage = function() {
  let message;
  if (chrome.runtime.lastError === undefined) message = 'unknown error';
  else message = chrome.runtime.lastError.message;

  showMessage('Error: ' + message, false);
};

const runSaveProcess = function() {
  ui.toggleDisabledSaveButton(true);
  ui.toggleSavedStatusMessage(true);
  getConfig()
    .then(searchPost)
    .then(savePost)
    .then(updateStoredPost)
    .then(updateUI)
    .catch(notifyError)
    .finally(function() {
      ui.toggleSavedStatusMessage(false);
    });
};

const runSaveProcessByShortcut = function(event) {
  // Ctrl+s or Cmd+s
  if ((event.metaKey || event.ctrlKey) && event.keyCode == 83) {
    event.preventDefault();
    runSaveProcess();
  }
};

$(function() {
  loadPost();
  getConfig().catch(notifyError);

  ui.titleDom.on('keyup', _.debounce(storeTitle, 200));
  ui.bodyDom.on('keyup', _.debounce(storeBody, 200));
  ui.bodyDom.on('mouseup', storeCursorPosition);

  ui.titleDom.on('keydown', runSaveProcessByShortcut);
  ui.bodyDom.on('keydown', runSaveProcessByShortcut);

  ui.bodyDom.esarea();

  ui.postButtonDom.on('click', runSaveProcess);
});
<|endoftext|>


<commit_before>import 'whatwg-fetch';
import codemirror from 'codemirror';
import 'codemirror/mode/javascript/javascript';
import analytics from './analytics';
import redirectTraffic from './redirect-traffic';
import layoutFunctions from './layoutFunctions';
import clickEvents from './clickEvents';
import drag from './drag';
import examples from './add-examples';
import libraries from './add-libraries';
import $ from './helpers';
import share from './share';
import snackbar from './snackbar';
import frameBridge from './frameBridge';
import MESSAGES from './sandbox/keys';

const codeWrapper = $.getElement('.code-wrapper'),
  fiddleWrapper = $.getElement('.fiddle-wrapper'),
  themeChanger = $.getElement('.change-theme'),
  savedTheme = localStorage.getItem('theme'),
  pathAr = location.pathname.split('/'),
  fiddleId = pathAr[pathAr.length - 2],
  embedded = pathAr[1] === 'embed',
  startFiddle = $.getElement('.star');

analytics.start();
redirectTraffic.register();
window.embedded = embedded;
window.exampleSelector = $.getElement('.examples');
examples.addExamples();

window.librariesSelector = $.getElement('.libraries');
libraries.addLibraries();

// check to see if the share button should be shown
if (fiddleId && !embedded) {
  const shareEl = $.getElement('.share');
  $.addStyleTo(startFiddle, 'display', 'block');
  if (shareEl) { share.shareFiddle(fiddleId); }
} else {
  $.addStyleTo(startFiddle, 'display', 'none');
}

// handle the embedded buttons
if (embedded) {
  const es6Btn = $.getElement('.es6-click-btn');
  const consoleBtn = $.getElement('.console-click-btn');
  $.getElement('.edit-at-es6').href = document.location.href.replace('/embed', '');

  es6Btn.onclick = () => {
    $.getElement('.fiddle').addStyle('display', 'block');
    $.getElement('.result-wrapper').addStyle('display', 'none');
    $.addClass(es6Btn, 'selected');
    $.removeClass(consoleBtn, 'selected');
  };

  consoleBtn.onclick = () => {
    $.getElement('.fiddle').addStyle('display', 'none');
    $.getElement('.result-wrapper').addStyle('display', 'block');
    $.removeClass(es6Btn, 'selected');
    $.addClass(consoleBtn, 'selected');
  };
}

// Change the layout of the page based on the type clicked.
// Save this layout choice in localStorage
// By default this will be vertical
$.getElement('.vertical').onclick = () => {
  layoutFunctions.setVerticalStyle(codeWrapper);
  layoutFunctions.saveLayoutOption('vertical');
};

// Onclick of the horizontal button then make the page visually horizontal
// And save the layout option clicked (in this case horizontal) to localstorage
$.getElement('.horizontal').onclick = () => {
  layoutFunctions.setHorizontalStyle(codeWrapper);
  layoutFunctions.saveLayoutOption('horizontal');
};

// add the fiddle area
const fiddle = codemirror($.getElement('.fiddle'), {
  lineNumbers: !embedded,
  readOnly: embedded ? 'nocursor' : false,
  theme: savedTheme || 'default',
});
fiddle.focus();

// If the user has previously selected to use the horizontal layout then load that
if (localStorage.getItem('es6fiddleLayout') === 'horizontal') {
  layoutFunctions.setHorizontalStyle(codeWrapper);
  // Otherwise make the page the default vertical style
} else {
  layoutFunctions.setVerticalStyle(codeWrapper);
}

// If the user has previously enabled dark mode then open in dark mode
if (localStorage.getItem('es6fiddleDarkMode') === 'true') {
  clickEvents.enableDarkMode();
} else {
  clickEvents.disableDarkMode();
}

// When the dark mode button is clicked, toggle the dark mode setting
$.getElement('.dark-mode').onclick = () => {
  clickEvents.darkModeClick(clickEvents.disableDarkMode, clickEvents.enableDarkMode, fiddle);
};

// Set the saved theme in the theme changer dropdown
if (savedTheme) {
  themeChanger.value = savedTheme;
}

// Add line number to all console.log() statements
function calculateLineNumber(fiddleValue) {
  const lines = fiddleValue.split(/\n/);
  let newLines = '';
  newLines = lines.map((line, index) => {
    const consReg = /(console\.log\()(.*)/;
    //  separate console.log from original string and split it in to
    // "console.log(" and ")"
    const clgLines = line.match(consReg);
    if (clgLines) {
      // Add line no: to console.log and join it with rest of the original line.
      // return line.slice(0, clgLines.index) + clgLines[1] + `'${index+1}: ' , ` +clgLines[2];
      return `${line.slice(0, clgLines.index) + clgLines[1]}'${index + 1}: ' , ${clgLines[2]}`;
    }
    return line;
  });
  return newLines.join('\n');
}

/* eslint-disable */
const runFiddle = () => {
  frameBridge.send(MESSAGES.RUN_SCRIPT, calculateLineNumber(fiddle.getValue()));
};

/* eslint-enable */

const getFiddle = (data) => {
  if (data.fiddle) {
    if (data.value) {
      fiddle.setValue(data.value);
    } else {
      fiddle.setValue('* Sorry, but I could not load your code right now. *');
    }
    if (data.isPrivate) {
      const privateIcon = $.getElement('.fa-globe');
      privateIcon.classList.remove('fa-globe');
      privateIcon.classList.add('fa-lock');
      privateIcon.parentElement.setAttribute('data-balloon', 'Private Fiddle');
    }
  } else {
    $.addStyleTo(startFiddle, 'display', 'none');
    fiddle.setValue(data.message);
  }

  if (embedded) { // go ahead and run the code
    runFiddle();
  }
};

// if fiddleId is define then load up the saved code
if (fiddleId) {
  fetch(`/fiddles/${fiddleId}`, {
    credentials: 'same-origin',
  }).then(resp => resp.json()).then(data => getFiddle(data));
}

// if this is not an embedded fiddle than add extra elements to this
if (!embedded) {
  // run the input
  $.getElement('.run').onclick = runFiddle;

  // lint the result
  $.getElement('.lint').onclick = () => {
    const lint = JSHINT(fiddle.getValue(), {
      esnext: true,
      devel: true,
      browser: true,
    });

    // remove the line error class from all lines
    fiddle.eachLine((line) => {
      fiddle.removeLineClass(line, 'background', 'line-error');
    });

    const lints = [];
    if (!lint) {
      JSHINT.errors.forEach((err) => {
        fiddle.addLineClass(err.line - 1, 'background', 'line-error');
        lints.push(`console.log('Line ' + ${err.line} + ':', '${err.reason.replace(/'/g, '\\\'')}')\n`);
      });
    } else {
      lints.push('console.log(\'Awesome! Your code is lint free!\');');
    }

    frameBridge.send(MESSAGES.RUN_SCRIPT, lints.join('\n'));
  };

  // export to Github gist
  $.getElement('.gist').onclick = () => clickEvents.exportAsGist(fiddle);

  // save the code
  document.querySelector('.save').onclick = () => clickEvents.saveBtn(fiddle);

  // star the code
  $.getElement('.star').onclick = () => {
    const pathArr = window.location.pathname.split('/'),
      fiddleID = pathArr[1].length > 1 ? pathArr[1] : -1;

    if (fiddleID !== -1) {
      fetch(`/star/${fiddleID}`, {
        method: 'POST',
        credentials: 'same-origin',
        headers: new Headers({
          'Content-Type': 'application/json',
        }),
      })
      .then(resp => resp.json())
      .then(data => clickEvents.starFiddle(data));
    }
  };

  // Make fiddle private
  $.getElement('.private').onclick = () => {
    const pathArr = window.location.pathname.split('/'),
      fiddleID = pathArr[1].length > 1 ? pathArr[1] : -1;

    if (fiddleID !== -1) {
      fetch(`/private/${fiddleID}`, {
        method: 'POST',
        credentials: 'same-origin',
        headers: new Headers({
          'Content-Type': 'application/json',
        }),
      })
          .then(resp => resp.json())
          .then(data => clickEvents.privateFiddle(data));
    } else {
      snackbar.showSnackbar('You don\'t appear to have any code or its not saved.');
    }
  };

  themeChanger.onchange = () => {
    const theme = themeChanger.options[themeChanger.selectedIndex].textContent;
    fiddle.setOption('theme', theme);
    localStorage.setItem('theme', theme);
  };

  // load the selected code
  window.exampleSelector.onchange = () => {
    if (window.exampleSelector.value) {
      let code = 'Example Can Not Be Found';

      if (window.es6Example[window.exampleSelector.value]) {
        ({ code } = window.es6Example[window.exampleSelector.value]);
      } else if (window.es7Example[window.exampleSelector.value]) {
        ({ code } = window.es7Example[window.exampleSelector.value]);
      }

      fiddle.setValue(code);
    }
  };

  // load the selected javascript library
  window.librariesSelector.onchange = () => {
    if (window.librariesSelector.value) {
      const script = $.createElement('script');
      script.onload = function onScriptLoad() {
        console.log(`${window.librariesSelector.selectedOptions[0].text} Script loaded`);
      };
      script.src = window.librariesSelector.value;

      document.head.appendChild(script);
    }
  };
} // end not embedded

// Add dragging funcionality
fiddleWrapper.addEventListener('click', function init() {
  fiddleWrapper.removeEventListener('click', init, false);
  $.getElement('.resizer').addEventListener('mousedown', drag.initDrag, false);
}, false);
<commit_msg>Add extra line<commit_after>import 'whatwg-fetch';
import codemirror from 'codemirror';
import 'codemirror/mode/javascript/javascript';
import analytics from './analytics';
import redirectTraffic from './redirect-traffic';
import layoutFunctions from './layoutFunctions';
import clickEvents from './clickEvents';
import drag from './drag';
import examples from './add-examples';
import libraries from './add-libraries';
import $ from './helpers';
import share from './share';
import snackbar from './snackbar';
import frameBridge from './frameBridge';
import MESSAGES from './sandbox/keys';

const codeWrapper = $.getElement('.code-wrapper'),
  fiddleWrapper = $.getElement('.fiddle-wrapper'),
  themeChanger = $.getElement('.change-theme'),
  savedTheme = localStorage.getItem('theme'),
  pathAr = location.pathname.split('/'),
  fiddleId = pathAr[pathAr.length - 2],
  embedded = pathAr[1] === 'embed',
  startFiddle = $.getElement('.star');

analytics.start();
redirectTraffic.register();

window.embedded = embedded;
window.exampleSelector = $.getElement('.examples');
examples.addExamples();

window.librariesSelector = $.getElement('.libraries');
libraries.addLibraries();

// check to see if the share button should be shown
if (fiddleId && !embedded) {
  const shareEl = $.getElement('.share');
  $.addStyleTo(startFiddle, 'display', 'block');
  if (shareEl) { share.shareFiddle(fiddleId); }
} else {
  $.addStyleTo(startFiddle, 'display', 'none');
}

// handle the embedded buttons
if (embedded) {
  const es6Btn = $.getElement('.es6-click-btn');
  const consoleBtn = $.getElement('.console-click-btn');
  $.getElement('.edit-at-es6').href = document.location.href.replace('/embed', '');

  es6Btn.onclick = () => {
    $.getElement('.fiddle').addStyle('display', 'block');
    $.getElement('.result-wrapper').addStyle('display', 'none');
    $.addClass(es6Btn, 'selected');
    $.removeClass(consoleBtn, 'selected');
  };

  consoleBtn.onclick = () => {
    $.getElement('.fiddle').addStyle('display', 'none');
    $.getElement('.result-wrapper').addStyle('display', 'block');
    $.removeClass(es6Btn, 'selected');
    $.addClass(consoleBtn, 'selected');
  };
}

// Change the layout of the page based on the type clicked.
// Save this layout choice in localStorage
// By default this will be vertical
$.getElement('.vertical').onclick = () => {
  layoutFunctions.setVerticalStyle(codeWrapper);
  layoutFunctions.saveLayoutOption('vertical');
};

// Onclick of the horizontal button then make the page visually horizontal
// And save the layout option clicked (in this case horizontal) to localstorage
$.getElement('.horizontal').onclick = () => {
  layoutFunctions.setHorizontalStyle(codeWrapper);
  layoutFunctions.saveLayoutOption('horizontal');
};

// add the fiddle area
const fiddle = codemirror($.getElement('.fiddle'), {
  lineNumbers: !embedded,
  readOnly: embedded ? 'nocursor' : false,
  theme: savedTheme || 'default',
});
fiddle.focus();

// If the user has previously selected to use the horizontal layout then load that
if (localStorage.getItem('es6fiddleLayout') === 'horizontal') {
  layoutFunctions.setHorizontalStyle(codeWrapper);
  // Otherwise make the page the default vertical style
} else {
  layoutFunctions.setVerticalStyle(codeWrapper);
}

// If the user has previously enabled dark mode then open in dark mode
if (localStorage.getItem('es6fiddleDarkMode') === 'true') {
  clickEvents.enableDarkMode();
} else {
  clickEvents.disableDarkMode();
}

// When the dark mode button is clicked, toggle the dark mode setting
$.getElement('.dark-mode').onclick = () => {
  clickEvents.darkModeClick(clickEvents.disableDarkMode, clickEvents.enableDarkMode, fiddle);
};

// Set the saved theme in the theme changer dropdown
if (savedTheme) {
  themeChanger.value = savedTheme;
}

// Add line number to all console.log() statements
function calculateLineNumber(fiddleValue) {
  const lines = fiddleValue.split(/\n/);
  let newLines = '';
  newLines = lines.map((line, index) => {
    const consReg = /(console\.log\()(.*)/;
    //  separate console.log from original string and split it in to
    // "console.log(" and ")"
    const clgLines = line.match(consReg);
    if (clgLines) {
      // Add line no: to console.log and join it with rest of the original line.
      // return line.slice(0, clgLines.index) + clgLines[1] + `'${index+1}: ' , ` +clgLines[2];
      return `${line.slice(0, clgLines.index) + clgLines[1]}'${index + 1}: ' , ${clgLines[2]}`;
    }
    return line;
  });
  return newLines.join('\n');
}

/* eslint-disable */
const runFiddle = () => {
  frameBridge.send(MESSAGES.RUN_SCRIPT, calculateLineNumber(fiddle.getValue()));
};

/* eslint-enable */

const getFiddle = (data) => {
  if (data.fiddle) {
    if (data.value) {
      fiddle.setValue(data.value);
    } else {
      fiddle.setValue('* Sorry, but I could not load your code right now. *');
    }
    if (data.isPrivate) {
      const privateIcon = $.getElement('.fa-globe');
      privateIcon.classList.remove('fa-globe');
      privateIcon.classList.add('fa-lock');
      privateIcon.parentElement.setAttribute('data-balloon', 'Private Fiddle');
    }
  } else {
    $.addStyleTo(startFiddle, 'display', 'none');
    fiddle.setValue(data.message);
  }

  if (embedded) { // go ahead and run the code
    runFiddle();
  }
};

// if fiddleId is define then load up the saved code
if (fiddleId) {
  fetch(`/fiddles/${fiddleId}`, {
    credentials: 'same-origin',
  }).then(resp => resp.json()).then(data => getFiddle(data));
}

// if this is not an embedded fiddle than add extra elements to this
if (!embedded) {
  // run the input
  $.getElement('.run').onclick = runFiddle;

  // lint the result
  $.getElement('.lint').onclick = () => {
    const lint = JSHINT(fiddle.getValue(), {
      esnext: true,
      devel: true,
      browser: true,
    });

    // remove the line error class from all lines
    fiddle.eachLine((line) => {
      fiddle.removeLineClass(line, 'background', 'line-error');
    });

    const lints = [];
    if (!lint) {
      JSHINT.errors.forEach((err) => {
        fiddle.addLineClass(err.line - 1, 'background', 'line-error');
        lints.push(`console.log('Line ' + ${err.line} + ':', '${err.reason.replace(/'/g, '\\\'')}')\n`);
      });
    } else {
      lints.push('console.log(\'Awesome! Your code is lint free!\');');
    }

    frameBridge.send(MESSAGES.RUN_SCRIPT, lints.join('\n'));
  };

  // export to Github gist
  $.getElement('.gist').onclick = () => clickEvents.exportAsGist(fiddle);

  // save the code
  document.querySelector('.save').onclick = () => clickEvents.saveBtn(fiddle);

  // star the code
  $.getElement('.star').onclick = () => {
    const pathArr = window.location.pathname.split('/'),
      fiddleID = pathArr[1].length > 1 ? pathArr[1] : -1;

    if (fiddleID !== -1) {
      fetch(`/star/${fiddleID}`, {
        method: 'POST',
        credentials: 'same-origin',
        headers: new Headers({
          'Content-Type': 'application/json',
        }),
      })
      .then(resp => resp.json())
      .then(data => clickEvents.starFiddle(data));
    }
  };

  // Make fiddle private
  $.getElement('.private').onclick = () => {
    const pathArr = window.location.pathname.split('/'),
      fiddleID = pathArr[1].length > 1 ? pathArr[1] : -1;

    if (fiddleID !== -1) {
      fetch(`/private/${fiddleID}`, {
        method: 'POST',
        credentials: 'same-origin',
        headers: new Headers({
          'Content-Type': 'application/json',
        }),
      })
          .then(resp => resp.json())
          .then(data => clickEvents.privateFiddle(data));
    } else {
      snackbar.showSnackbar('You don\'t appear to have any code or its not saved.');
    }
  };

  themeChanger.onchange = () => {
    const theme = themeChanger.options[themeChanger.selectedIndex].textContent;
    fiddle.setOption('theme', theme);
    localStorage.setItem('theme', theme);
  };

  // load the selected code
  window.exampleSelector.onchange = () => {
    if (window.exampleSelector.value) {
      let code = 'Example Can Not Be Found';

      if (window.es6Example[window.exampleSelector.value]) {
        ({ code } = window.es6Example[window.exampleSelector.value]);
      } else if (window.es7Example[window.exampleSelector.value]) {
        ({ code } = window.es7Example[window.exampleSelector.value]);
      }

      fiddle.setValue(code);
    }
  };

  // load the selected javascript library
  window.librariesSelector.onchange = () => {
    if (window.librariesSelector.value) {
      const script = $.createElement('script');
      script.onload = function onScriptLoad() {
        console.log(`${window.librariesSelector.selectedOptions[0].text} Script loaded`);
      };
      script.src = window.librariesSelector.value;

      document.head.appendChild(script);
    }
  };
} // end not embedded

// Add dragging funcionality
fiddleWrapper.addEventListener('click', function init() {
  fiddleWrapper.removeEventListener('click', init, false);
  $.getElement('.resizer').addEventListener('mousedown', drag.initDrag, false);
}, false);
<|endoftext|>


<commit_before>module.exports = {
  characterImage: (file) => `/images/${file}`,
};
<commit_msg>Making image paths relative.<commit_after>module.exports = {
  characterImage: (file) => `images/${file}`,
};
<|endoftext|>


<commit_before>'use strict';

var Mailgun = require('mailgun-js');
var packageData = require('../package.json');
var pickBy = require('lodash.pickby');
var some = require('lodash.some');

var whitelistExact = [
  'from',
  'to',
  'cc',
  'bcc',
  'subject',
  'text',
  'html',
  'attachment',
  'o:tag',
  'o:campaign',
  'o:dkim',
  'o:deliverytime',
  'o:testmode',
  'o:tracking',
  'o:tracking-clicks',
  'o:tracking-opens',
  'o:require-tls',
  'o:skip-verification'
];
var whitelistPrefix = [
  'h:',
  'v:'
];

module.exports = function (options) {
  return new MailgunTransport(options);
};

function MailgunTransport(options) {
  this.options = options || {};
  this.name = 'Mailgun';
  this.version = packageData.version;

  this.mailgun = Mailgun({
    apiKey: this.options.auth.api_key,
    domain: this.options.auth.domain || ''
  });
  this.messages = this.mailgun.messages();
}

MailgunTransport.prototype.send = function send(mail, callback) {
  var mailData = mail.data;
  // convert nodemailer attachments to mailgun-js attachements
  if(mailData.attachments){
    var a, b, aa = [];
    for(var i in mailData.attachments){
      a = mailData.attachments[i];
      b = new this.mailgun.Attachment({
        data        : a.path || undefined,
        filename    : a.filename || undefined,
        contentType : a.contentType || undefined,
        knownLength : a.knownLength || undefined
      });

      aa.push(b);
    }
    mailData.attachment = aa;
  }

  var options = pickBy(mailData, function (key) {
    if (whitelistExact.indexOf(key) !== -1) {
      return true;
    }

    return some(whitelistPrefix, function (prefix) {
      return key.startsWith(prefix);
    });
  });

  this.messages.send(options, function (err, data) {
    callback(err || null, data);
  });

};

<commit_msg>Fix wrong use mocha.pickBy<commit_after>'use strict';

var Mailgun = require('mailgun-js');
var packageData = require('../package.json');
var pickBy = require('lodash.pickby');
var some = require('lodash.some');

var whitelistExact = [
  'from',
  'to',
  'cc',
  'bcc',
  'subject',
  'text',
  'html',
  'attachment',
  'o:tag',
  'o:campaign',
  'o:dkim',
  'o:deliverytime',
  'o:testmode',
  'o:tracking',
  'o:tracking-clicks',
  'o:tracking-opens',
  'o:require-tls',
  'o:skip-verification'
];
var whitelistPrefix = [
  'h:',
  'v:'
];

module.exports = function (options) {
  return new MailgunTransport(options);
};

function MailgunTransport(options) {
  this.options = options || {};
  this.name = 'Mailgun';
  this.version = packageData.version;

  this.mailgun = Mailgun({
    apiKey: this.options.auth.api_key,
    domain: this.options.auth.domain || ''
  });
  this.messages = this.mailgun.messages();
}

MailgunTransport.prototype.send = function send(mail, callback) {
  var mailData = mail.data;
  // convert nodemailer attachments to mailgun-js attachements
  if(mailData.attachments){
    var a, b, aa = [];
    for(var i in mailData.attachments){
      a = mailData.attachments[i];
      b = new this.mailgun.Attachment({
        data        : a.path || undefined,
        filename    : a.filename || undefined,
        contentType : a.contentType || undefined,
        knownLength : a.knownLength || undefined
      });

      aa.push(b);
    }
    mailData.attachment = aa;
  }

  var options = pickBy(mailData, function (value, key) {
    if (whitelistExact.indexOf(key) !== -1) {
      return true;
    }

    return some(whitelistPrefix, function (prefix) {
      return key.startsWith(prefix);
    });
  });

  this.messages.send(options, function (err, data) {
    callback(err || null, data);
  });

};

<|endoftext|>


<commit_before>
angular.module('aps_snake', [])

  .controller('snakeController', function ($scope, $timeout, $window) {
    var BOARD_SIZE = 30;
    var DIRECTIONS = {
      LEFT: 37,
      UP: 38,
      RIGHT: 39,
      DOWN: 40
    };

    var COLORS = {
      GAME_OVER: '#820303',
      FRUIT: '#79D783',
      SNAKE_HEAD: '#6F6F6F',
      SNAKE_BODY: '#FFFFFF',
      BOARD: '#000000',
	  EGG: '#FFF5C3',
	  BLUEBERRY: '#064FBA',
	  BANANA: '#FFE135',
	  GRAPES: '#421C52',
	  EXTRALIFE: '#E80505',
	  ROTTENFRUIT: '#A0522D'
    };

    var snake = {
      direction: DIRECTIONS.LEFT,
      parts: [{
        x: -1,
        y: -1
      }]
    };

    var fruit = {
      x: -1,
      y: -1
    };

	var egg = {
      x: -1,
      y: -1
    };

	var blueberry = {
		x: -1,
		y: -1
	};

	var banana = {
		x: -1,
		y: -1
	};

	var grapes = {
		x: -1,
		y: -1
	};

	var extraLife = {
		x: -1,
		y: -1
	};

	var rottenFruit = {
		x: -1,
		y: -1
	};

    var interval, tempDirection, isGameOver;
	var  levelAims = [2,3,4,5,6];
	var levelCountdown = [2,4,6,8,10];
    if (document.cookie === undefined) document.cookie = "highscore=0"
    $scope.score = 0;
    $scope.highscore = readHighscore(document.cookie);
	$scope.level =1;
    $scope.fruitCount = 0;
	$scope.levelAim = levelAims[$scope.level - 1];
	$scope.currentCountdown = levelCountdown[0];

    function readHighscore(fromCookie) {
      const regex = new RegExp(/([a-zA-Z=]w*)/g)
      const outputString = fromCookie.replace(regex, (match) => {
        return ""
      })
      const outputInt = parseInt(outputString)
      return outputInt
    }

    $scope.setStyling = function (col, row) {
      if (isGameOver) {
        return COLORS.GAME_OVER;
      } else if (fruit.x == row && fruit.y == col) {
        return COLORS.FRUIT;
      } else if (egg.x == row && egg.y == col) {
        return COLORS.EGG;
      } else if (blueberry.x == row && blueberry.y == col) {
        return COLORS.BLUEBERRY;
      } else if (banana.x == row && banana.y == col) {
        return COLORS.BANANA;
	  } else if (grapes.x == row && grapes.y == col) {
        return COLORS.GRAPES;
	  } else if (extraLife.x == row && extraLife.y == col) {
        return COLORS.EXTRALIFE;
	  } else if (rottenFruit.x == row && rottenFruit.y == col) {
        return COLORS.ROTTENFRUIT;
	  } else if (snake.parts[0].x == row && snake.parts[0].y == col) {
        return COLORS.SNAKE_HEAD;
      } else if ($scope.board[col][row] === true) {
        return COLORS.SNAKE_BODY;
      }
      return COLORS.BOARD;
    };

    function update() {
      var newHead = getNewHead();

      if (boardCollision(newHead) || selfCollision(newHead) || eggCollision(newHead)) {
        return gameOver();
      } else if (fruitCollision(newHead)) {
        eatFruit();
	  } else if (blueberryCollision(newHead)) {
		eatblueberry();
	  } else if (bananaCollision(newHead)) {
		eatBanana();
	  } else if (grapesCollision(newHead)) {
		eatGrapes();
	  } else if (extraLifeCollision(newHead)) {
		eatExtraLife();
	  } else if (rottenFruitCollision(newHead)) {
		eatRottenFruit();
	  }

      // Remove tail
      var oldTail = snake.parts.pop();
      $scope.board[oldTail.y][oldTail.x] = false;

      // Pop tail to head
      snake.parts.unshift(newHead);
      $scope.board[newHead.y][newHead.x] = true;

      // Do it again
      snake.direction = tempDirection;
      $timeout(update, interval);
    }

    function getNewHead() {
      var newHead = angular.copy(snake.parts[0]);

      // Update Location
      if (tempDirection === DIRECTIONS.LEFT) {
        newHead.x -= 1;
      } else if (tempDirection === DIRECTIONS.RIGHT) {
        newHead.x += 1;
      } else if (tempDirection === DIRECTIONS.UP) {
        newHead.y -= 1;
      } else if (tempDirection === DIRECTIONS.DOWN) {
        newHead.y += 1;
      }
      return newHead;
    }

    function boardCollision(part) {
      return part.x === BOARD_SIZE || part.x === -1 || part.y === BOARD_SIZE || part.y === -1;
    }

    function selfCollision(part) {
      return $scope.board[part.y][part.x] === true;
    }

    function fruitCollision(part) {
      return part.x === fruit.x && part.y === fruit.y;
    }

	function eggCollision(part) {
      return part.x === egg.x && part.y === egg.y;
    }

	function blueberryCollision(part) {
      return part.x === blueberry.x && part.y === blueberry.y;
    }

	function bananaCollision(part) {
	  return part.x === banana.x && part.y === banana.y;
	}

	function grapesCollision(part) {
	  return part.x === grapes.x && part.y === grapes.y;
	}

	function extraLifeCollision(part) {
	  return part.x === extraLife.x && part.y === extraLife.y;
	}

	function rottenFruitCollision(part) {
	  return part.x === rottenFruit.x && part.y === rottenFruit.y;
	}

    function resetFruit() {
      var x = Math.floor(Math.random() * BOARD_SIZE);
      var y = Math.floor(Math.random() * BOARD_SIZE);

      if ($scope.board[y][x] === true) {
        return resetFruit();
      }
      fruit = { x: x, y: y };
    }

	function setEgg() {
	  var oldTail = snake.parts.pop()
      $scope.board[oldTail.y][oldTail.x] = false;
	  egg = { x: oldTail.x, y: oldTail.y };
	  var countdownTimer = setInterval(function() {
		  $scope.currentCountdown--;
		  console.log($scope.currentCountdown);
		  if($scope.currentCountdown === 0) {
			  clearInterval(countdownTimer);
			  	$scope.level++;
				$scope.fruitCount = 0;
				$scope.levelAim = levelAims[$scope.level - 1];
				$scope.currentCountdown = levelCountdown[$scope.level - 1];
				setUpSnake();
				egg = { x: -1, y: -1};

		  }
	  },1000);

    }

	function setblueberry() {
	  var x = Math.floor(Math.random() * BOARD_SIZE);
      var y = Math.floor(Math.random() * BOARD_SIZE);

      if ($scope.board[y][x] === true) {
        return setblueberry();
      }
      blueberry = { x: x, y: y };
	  $timeout(function () {
		 blueberry = { x: -1, y: -1 };
	  }, 10000);
	}

	function setBanana() {
	  var x = Math.floor(Math.random() * BOARD_SIZE);
      var y = Math.floor(Math.random() * BOARD_SIZE);

      if ($scope.board[y][x] === true) {
        return setBanana();
      }
      banana = { x: x, y: y };
	  $timeout(function () {
		 banana = { x: -1, y: -1 };
	  }, 9000);
	}

	function setGrapes() {
	  var x = Math.floor(Math.random() * BOARD_SIZE);
      var y = Math.floor(Math.random() * BOARD_SIZE);

      if ($scope.board[y][x] === true) {
        return setGrapes();
      }
      grapes = { x: x, y: y };
	  $timeout(function () {
		 grapes = { x: -1, y: -1 };
	  }, 8000);
	}

	function setExtraLife() {
	  var x = Math.floor(Math.random() * BOARD_SIZE);
      var y = Math.floor(Math.random() * BOARD_SIZE);

      if ($scope.board[y][x] === true) {
        return setExtraLife();
      }
      extraLife = { x: x, y: y };
	  $timeout(function () {
		 extraLife = { x: -1, y: -1 };
	  }, 7000);
	}

	function setRottenFruit() {
	  var x = Math.floor(Math.random() * BOARD_SIZE);
      var y = Math.floor(Math.random() * BOARD_SIZE);

      if ($scope.board[y][x] === true) {
        return setRottenFruit();
      }
      rottenFruit = { x: x, y: y };
	  $timeout(function () {
		 rottenFruit = { x: -1, y: -1 };
	  }, 10000);
	}

	function setUpSnake() {

		// Set up initial snake
			if (egg.x === -1)
				for (var i = 0; i < 5; i++) snake.parts.push({ x: 10 + i, y: 10 });
			else{
				var child = {
				direction: DIRECTIONS.LEFT,
				parts: [{
					x: -1,
					y: -1
				}]
			};

				snake = child;
				for (var i = 0; i < 5; i++) snake.parts.push({ x: 10 + i, y: 10 });
			}

	}

    function eatFruit() {
		$scope.score++;
		$scope.fruitCount++;

		// Grow by 1
		var tail = angular.copy(snake.parts[snake.parts.length - 1]);
		snake.parts.push(tail);
		resetFruit();

		if ($scope.fruitCount % 5 === 0) {
			interval -= 15;
			var x = Math.floor(Math.random() * 5)
			switch (x) {
				case 0:
					setblueberry();
					break;
				case 1:
					setBanana();
					break;
				case 2:
					setGrapes();
					break;
				case 3:
					setExtraLife();
					break;
				case 4:
					setRottenFruit();
					break;
				}
			}
		if ($scope.fruitCount === $scope.levelAim) {
			setEgg();
		}
    }

	function eatblueberry() {
		$scope.score+=3;
		blueberry = { x: -1, y: -1 };
    }

	function eatBanana() {
		$scope.score+=5;
		banana = {x: -1, y: -1 };
	}

	function eatGrapes() {
		$scope.score+=7;
		grapes = {x: -1, y: -1 };
	}

	function eatExtraLife() {
		extraLife = {x: -1, y: -1 };
	}

	function eatRottenFruit() {
		rottenFruit = {x: -1, y: -1 };
	}

    function gameOver() {
      isGameOver = true;
      let currentScore = $scope.score;
      if (currentScore > $scope.highscore) {
        $scope.highscore = currentScore;
        document.cookie = "highscore=" + currentScore;
      }

      $timeout(function () {
        isGameOver = false;
      }, 500);

      setupBoard();
    }

    function setupBoard() {
      $scope.board = [];
      for (var i = 0; i < BOARD_SIZE; i++) {
        $scope.board[i] = [];
        for (var j = 0; j < BOARD_SIZE; j++) {
          $scope.board[i][j] = false;
        }
      }
    }
    setupBoard();

    $window.addEventListener("keyup", function (e) {
      if (e.keyCode == DIRECTIONS.LEFT && snake.direction !== DIRECTIONS.RIGHT) {
        tempDirection = DIRECTIONS.LEFT;
      } else if (e.keyCode == DIRECTIONS.UP && snake.direction !== DIRECTIONS.DOWN) {
        tempDirection = DIRECTIONS.UP;
      } else if (e.keyCode == DIRECTIONS.RIGHT && snake.direction !== DIRECTIONS.LEFT) {
        tempDirection = DIRECTIONS.RIGHT;
      } else if (e.keyCode == DIRECTIONS.DOWN && snake.direction !== DIRECTIONS.UP) {
        tempDirection = DIRECTIONS.DOWN;
      }
    });

    $scope.startGame = function () {
      $scope.score = 0;
	  $scope.fruitCount = 0;
      snake = { direction: DIRECTIONS.LEFT, parts: [] };
      tempDirection = DIRECTIONS.LEFT;
      isGameOver = false;
      interval = 150;
	  setUpSnake();
      resetFruit();
      update();
    };

  });
<commit_msg>Random Bonus Fruit<commit_after>
angular.module('aps_snake', [])

  .controller('snakeController', function ($scope, $timeout, $window) {
    var BOARD_SIZE = 30;
    var DIRECTIONS = {
      LEFT: 37,
      UP: 38,
      RIGHT: 39,
      DOWN: 40
    };

    var COLORS = {
      GAME_OVER: '#820303',
      FRUIT: '#79D783',
      SNAKE_HEAD: '#6F6F6F',
      SNAKE_BODY: '#FFFFFF',
      BOARD: '#000000',
	  EGG: '#FFF5C3',
	  BLUEBERRY: '#064FBA',
	  BANANA: '#FFE135',
	  GRAPES: '#421C52',
	  EXTRALIFE: '#E80505',
	  ROTTENFRUIT: '#A0522D'
    };

    var snake = {
      direction: DIRECTIONS.LEFT,
      parts: [{
        x: -1,
        y: -1
      }]
    };

    var fruit = {
      x: -1,
      y: -1
    };

	var egg = {
      x: -1,
      y: -1
    };

	var blueberry = {
		x: -1,
		y: -1
	};

	var banana = {
		x: -1,
		y: -1
	};

	var grapes = {
		x: -1,
		y: -1
	};

	var extraLife = {
		x: -1,
		y: -1
	};

	var rottenFruit = {
		x: -1,
		y: -1
	};

    var interval, tempDirection, isGameOver;
	var  levelAims = [2,3,4,5,6];
	var levelCountdown = [2,4,6,8,10];
    if (document.cookie === "") document.cookie = "highscore=0"
    $scope.score = 0;
    $scope.highscore = readHighscore(document.cookie);
	$scope.level =1;
    $scope.fruitCount = 0;
	$scope.levelAim = levelAims[$scope.level - 1];
	$scope.currentCountdown = levelCountdown[0];

    function readHighscore(fromCookie) {
      const regex = new RegExp(/([a-zA-Z=]w*)/g)
      const outputString = fromCookie.replace(regex, (match) => {
        return ""
      })
      const outputInt = parseInt(outputString)
      return outputInt
    }

    $scope.setStyling = function (col, row) {
      if (isGameOver) {
        return COLORS.GAME_OVER;
      } else if (fruit.x == row && fruit.y == col) {
        return COLORS.FRUIT;
      } else if (egg.x == row && egg.y == col) {
        return COLORS.EGG;
      } else if (blueberry.x == row && blueberry.y == col) {
        return COLORS.BLUEBERRY;
      } else if (banana.x == row && banana.y == col) {
        return COLORS.BANANA;
	  } else if (grapes.x == row && grapes.y == col) {
        return COLORS.GRAPES;
	  } else if (extraLife.x == row && extraLife.y == col) {
        return COLORS.EXTRALIFE;
	  } else if (rottenFruit.x == row && rottenFruit.y == col) {
        return COLORS.ROTTENFRUIT;
	  } else if (snake.parts[0].x == row && snake.parts[0].y == col) {
        return COLORS.SNAKE_HEAD;
      } else if ($scope.board[col][row] === true) {
        return COLORS.SNAKE_BODY;
      }
      return COLORS.BOARD;
    };

    function update() {
      var newHead = getNewHead();

      if (boardCollision(newHead) || selfCollision(newHead) || eggCollision(newHead)) {
        return gameOver();
      } else if (fruitCollision(newHead)) {
        eatFruit();
	  } else if (blueberryCollision(newHead)) {
		eatblueberry();
	  } else if (bananaCollision(newHead)) {
		eatBanana();
	  } else if (grapesCollision(newHead)) {
		eatGrapes();
	  } else if (extraLifeCollision(newHead)) {
		eatExtraLife();
	  } else if (rottenFruitCollision(newHead)) {
		eatRottenFruit();
	  }

      // Remove tail
      var oldTail = snake.parts.pop();
      $scope.board[oldTail.y][oldTail.x] = false;

      // Pop tail to head
      snake.parts.unshift(newHead);
      $scope.board[newHead.y][newHead.x] = true;

      // Do it again
      snake.direction = tempDirection;
      $timeout(update, interval);
    }

    function getNewHead() {
      var newHead = angular.copy(snake.parts[0]);

      // Update Location
      if (tempDirection === DIRECTIONS.LEFT) {
        newHead.x -= 1;
      } else if (tempDirection === DIRECTIONS.RIGHT) {
        newHead.x += 1;
      } else if (tempDirection === DIRECTIONS.UP) {
        newHead.y -= 1;
      } else if (tempDirection === DIRECTIONS.DOWN) {
        newHead.y += 1;
      }
      return newHead;
    }

    function boardCollision(part) {
      return part.x === BOARD_SIZE || part.x === -1 || part.y === BOARD_SIZE || part.y === -1;
    }

    function selfCollision(part) {
      return $scope.board[part.y][part.x] === true;
    }

    function fruitCollision(part) {
      return part.x === fruit.x && part.y === fruit.y;
    }

	function eggCollision(part) {
      return part.x === egg.x && part.y === egg.y;
    }

	function blueberryCollision(part) {
      return part.x === blueberry.x && part.y === blueberry.y;
    }

	function bananaCollision(part) {
	  return part.x === banana.x && part.y === banana.y;
	}

	function grapesCollision(part) {
	  return part.x === grapes.x && part.y === grapes.y;
	}

	function extraLifeCollision(part) {
	  return part.x === extraLife.x && part.y === extraLife.y;
	}

	function rottenFruitCollision(part) {
	  return part.x === rottenFruit.x && part.y === rottenFruit.y;
	}

    function resetFruit() {
      var x = Math.floor(Math.random() * BOARD_SIZE);
      var y = Math.floor(Math.random() * BOARD_SIZE);

      if ($scope.board[y][x] === true) {
        return resetFruit();
      }
      fruit = { x: x, y: y };
    }

	function setEgg() {
	  var oldTail = snake.parts.pop()
      $scope.board[oldTail.y][oldTail.x] = false;
	  egg = { x: oldTail.x, y: oldTail.y };
	  var countdownTimer = setInterval(function() {
		  $scope.currentCountdown--;
		  console.log($scope.currentCountdown);
		  if($scope.currentCountdown === 0) {
			  clearInterval(countdownTimer);
			  	$scope.level++;
				$scope.fruitCount = 0;
				$scope.levelAim = levelAims[$scope.level - 1];
				$scope.currentCountdown = levelCountdown[$scope.level - 1];
				setUpSnake();
				egg = { x: -1, y: -1};

		  }
	  },1000);

    }

	function setblueberry() {
	  var x = Math.floor(Math.random() * BOARD_SIZE);
      var y = Math.floor(Math.random() * BOARD_SIZE);

      if ($scope.board[y][x] === true) {
        return setblueberry();
      }
      blueberry = { x: x, y: y };
	  $timeout(function () {
		 blueberry = { x: -1, y: -1 };
	  }, 10000);
	}

	function setBanana() {
	  var x = Math.floor(Math.random() * BOARD_SIZE);
      var y = Math.floor(Math.random() * BOARD_SIZE);

      if ($scope.board[y][x] === true) {
        return setBanana();
      }
      banana = { x: x, y: y };
	  $timeout(function () {
		 banana = { x: -1, y: -1 };
	  }, 9000);
	}

	function setGrapes() {
	  var x = Math.floor(Math.random() * BOARD_SIZE);
      var y = Math.floor(Math.random() * BOARD_SIZE);

      if ($scope.board[y][x] === true) {
        return setGrapes();
      }
      grapes = { x: x, y: y };
	  $timeout(function () {
		 grapes = { x: -1, y: -1 };
	  }, 8000);
	}

	function setExtraLife() {
	  var x = Math.floor(Math.random() * BOARD_SIZE);
      var y = Math.floor(Math.random() * BOARD_SIZE);

      if ($scope.board[y][x] === true) {
        return setExtraLife();
      }
      extraLife = { x: x, y: y };
	  $timeout(function () {
		 extraLife = { x: -1, y: -1 };
	  }, 7000);
	}

	function setRottenFruit() {
	  var x = Math.floor(Math.random() * BOARD_SIZE);
      var y = Math.floor(Math.random() * BOARD_SIZE);

      if ($scope.board[y][x] === true) {
        return setRottenFruit();
      }
      rottenFruit = { x: x, y: y };
	  $timeout(function () {
		 rottenFruit = { x: -1, y: -1 };
	  }, 10000);
	}

	function setUpSnake() {

		// Set up initial snake
			if (egg.x === -1)
				for (var i = 0; i < 5; i++) snake.parts.push({ x: 10 + i, y: 10 });
			else{
				var child = {
				direction: DIRECTIONS.LEFT,
				parts: [{
					x: -1,
					y: -1
				}]
			};

				snake = child;
				for (var i = 0; i < 5; i++) snake.parts.push({ x: 10 + i, y: 10 });
			}

	}

    function eatFruit() {
		$scope.score++;
		$scope.fruitCount++;

		// Grow by 1
		var tail = angular.copy(snake.parts[snake.parts.length - 1]);
		snake.parts.push(tail);
		resetFruit();

		if ($scope.fruitCount % 5 === 0) {
			interval -= 15;
			var x = Math.floor(Math.random() * 5)
			switch (x) {
				case 0:
					setblueberry();
					break;
				case 1:
					setBanana();
					break;
				case 2:
					setGrapes();
					break;
				case 3:
					setExtraLife();
					break;
				case 4:
					setRottenFruit();
					break;
				}
			}
		if ($scope.fruitCount === $scope.levelAim) {
			setEgg();
		}
    }

	function eatblueberry() {
		$scope.score+=3;
		blueberry = { x: -1, y: -1 };
    }

	function eatBanana() {
		$scope.score+=5;
		banana = {x: -1, y: -1 };
	}

	function eatGrapes() {
		$scope.score+=7;
		grapes = {x: -1, y: -1 };
	}

	function eatExtraLife() {
		extraLife = {x: -1, y: -1 };
	}

	function eatRottenFruit() {
		rottenFruit = {x: -1, y: -1 };
	}

    function gameOver() {
      isGameOver = true;
      let currentScore = $scope.score;
      if (currentScore > $scope.highscore) {
        $scope.highscore = currentScore;
        document.cookie = "highscore=" + currentScore;
      }

      $timeout(function () {
        isGameOver = false;
      }, 500);

      setupBoard();
    }

    function setupBoard() {
      $scope.board = [];
      for (var i = 0; i < BOARD_SIZE; i++) {
        $scope.board[i] = [];
        for (var j = 0; j < BOARD_SIZE; j++) {
          $scope.board[i][j] = false;
        }
      }
    }
    setupBoard();

    $window.addEventListener("keyup", function (e) {
      if (e.keyCode == DIRECTIONS.LEFT && snake.direction !== DIRECTIONS.RIGHT) {
        tempDirection = DIRECTIONS.LEFT;
      } else if (e.keyCode == DIRECTIONS.UP && snake.direction !== DIRECTIONS.DOWN) {
        tempDirection = DIRECTIONS.UP;
      } else if (e.keyCode == DIRECTIONS.RIGHT && snake.direction !== DIRECTIONS.LEFT) {
        tempDirection = DIRECTIONS.RIGHT;
      } else if (e.keyCode == DIRECTIONS.DOWN && snake.direction !== DIRECTIONS.UP) {
        tempDirection = DIRECTIONS.DOWN;
      }
    });

    $scope.startGame = function () {
      $scope.score = 0;
	  $scope.fruitCount = 0;
      snake = { direction: DIRECTIONS.LEFT, parts: [] };
      tempDirection = DIRECTIONS.LEFT;
      isGameOver = false;
      interval = 150;
	  setUpSnake();
      resetFruit();
      update();
    };

  });
<|endoftext|>