<commit_before>/**
 * @file CSV Parser
 * @since 0.2.3
 */
/*#ifndef(UMD)*/
"use strict";
/*global _GpfStreamBufferedRead*/ // gpf.stream.BufferedRead
/*global _gpfArrayForEach*/ // Almost like [].forEach (undefined are also enumerated)
/*global _gpfArrayForEachFalsy*/ // _gpfArrayForEach that returns first truthy value computed by the callback
/*global _gpfAssert*/ // Assertion method
/*global _gpfDefine*/ // Shortcut for gpf.define
/*global _gpfErrorDeclare*/ // Declare new gpf.Error names
/*global _gpfIgnore*/ // Helper to remove unused parameter warning
/*global _gpfStreamSecureWrite*/ // Generates a wrapper to secure multiple calls to stream#write
/*global _gpfStringEscapeFor*/ // Make the string content compatible with lang
/*global _gpfStringReplaceEx*/ // String replacement using dictionary map
/*exported _GpfStreamCsvParser*/ // gpf.stream.csv.Parser
/*#endif*/

_gpfErrorDeclare("csv", {
    invalidCSV:
        "Invalid CSV syntax (bad quote sequence or missing end of file)"
});

/**
 * @typedef gpf.typedef.csvParserOptions
 * @property {String} [header] Header line: if not specified, the first write of the input stream becomes the header
 * @property {String} [separator] Column separator, detected from the header line if not specified (allowed characters
 * are ";" "," and "\t")
 * @property {String} [quote="\""] Quote sign: introduces an escaped value in which quotes, separator and carriage
 * returns are allowed. Consequently, the value may stand on several lines
 * @property {String} [newLine="\n"] New line: each input stream write is considered as a separate line.
 * If a quoted value stands on several lines, this character is used to represents every new line
 * @since 0.2.3
 */

/**
 * @namespace gpf.stream.csv
 * @description Root namespace for CSV related streams
 * @since 0.2.3
 */
gpf.stream.csv = {};

var
    // Usual CSV separators
    _gpfCsvSeparators = ";,\t ".split("");

var
    _GpfStreamCsvParser = _gpfDefine({
        $class: "gpf.stream.csv.Parser",
        $extend: _GpfStreamBufferedRead,

        /**
         * CSV Parser
         *
         * Parses the incoming stream by considering each write as a separate line.
         * It is recommended to use the {@link gpf.stream.LineAdapter} class in between the incoming stream and the CSV
         * parser.
         *
         * Generates objects where properties are matching header columns and values are string extracted from record
         * lines.
         *
         * @param {gpf.typedef.csvParserOptions} [parserOptions] Parser options
         * @constructor gpf.stream.csv.Parser
         * @implements {gpf.interfaces.IReadableStream}
         * @implements {gpf.interfaces.IWritableStream}
         * @implements {gpf.interfaces.IFlushableStream}
         * @extends gpf.stream.BufferedRead
         * @since 0.2.3
         */
        constructor: function (parserOptions) {
            this._readParserOptions(parserOptions);
            if (this._header) {
                this._parseHeader();
            } else {
                this._write = this._writeHeader;
            }
        },

        //region Parser options

        /**
         * Read parser options
         *
         * @param {gpf.typedef.csvParserOptions} [parserOptions] Parser options
         * @since 0.2.3
         */
        _readParserOptions: function (parserOptions) {
            var me = this;
            if (parserOptions) {
                _gpfArrayForEach([
                    "header",
                    "separator",
                    "quote",
                    "newLine"
                ], function (optionName) {
                    if (parserOptions[optionName]) {
                        me["_" + optionName] = parserOptions[optionName];
                    }
                });
            }
        },

        /**
         * Header line
         *
         * @type {String}
         * @since 0.2.3
         */
        _header: "",

        /**
         * Column separator
         *
         * @type {String}
         * @since 0.2.3
         */
        _separator: "",

        /**
         * Deduce separator from header line
         * @since 0.2.3
         */
        _deduceSeparator: function () {
            var header = this._header;
            this._separator = _gpfArrayForEachFalsy(_gpfCsvSeparators, function (separator) {
                if (header.includes(separator)) {
                    return separator;
                }
            }) || _gpfCsvSeparators[0];
        },

        /**
         * Quote sign
         *
         * @type {String}
         * @since 0.2.3
         */
        _quote: "\"",

        /**
         * New line
         *
         * @type {String}
         * @since 0.2.3
         */
        _newLine: "\n",

        //endregion

        //region Header processing

        /**
         * @property {String[]} Columns' name
         * @since 0.2.3
         */
        _columns: [],

        _buildParsingHelpers: function () {
            this._unescapeDictionary = {};
            this._unescapeDictionary[this._quote + this._quote] = this._quote;
            this._parser = new RegExp(_gpfStringReplaceEx("^(?:([^QS][^S]*)|Q((?:[^Q]|QQ)+)Q)(?=$|S)", {
                Q: _gpfStringEscapeFor(this._quote, "regexp"),
                S: _gpfStringEscapeFor(this._separator, "regexp")
            }));
        },

        /**
         * Once header line is known, process it to prepare the parser
         * @since 0.2.3
         */
        _parseHeader: function () {
            if (!this._separator) {
                this._deduceSeparator();
            }
            this._columns = this._header.split(this._separator);
            this._buildParsingHelpers();
            this._write = this._writeContent;
        },

        /**
         * Write header line
         *
         * @param {String} line CSV line
         * @since 0.2.3
         */
        _writeHeader: function (line) {
            this._header = line;
            this._parseHeader();
        },

        //endregion

        //region Content processing

        /**
         * Values being built
         * @since 0.2.3
         */
        _values: [],

        /**
         * Content to parse
         * @since 0.2.3
         */
        _content: "",

        /**
         * Unescape quoted value
         *
         * @param {String} value Quoted value
         * @return {String} unescaped value
         * @since 0.2.3
         */
        _unescapeQuoted: function (value) {
            return _gpfStringReplaceEx(value, this._unescapeDictionary);
        },

        /**
         * Add the matching value to the array of values
         *
         * @param {Object} match Regular expression match
         * @since 0.2.3
         */
        _addValue: function (match) {
            var UNQUOTED = 1,
                QUOTED = 2;
            if (match[UNQUOTED]) {
                this._values.push(match[UNQUOTED]);
            } else /* if (match[QUOTED]) */ {
                this._values.push(this._unescapeQuoted(match[QUOTED]));
            }
        },

        /**
         * Move the content to the next value
         *
         * @param {Number} index Position where the next value starts
         * @return {Boolean} True if some remaining content must be parsed
         * @since 0.2.3
         */
        _nextValue: function (index) {
            this._content = this._content.substr(index);
            return this._content.length > 0;
        },

        /**
         * Check what appears after the extracted value
         *
         * @param {Object} match Regular expression match
         * @return {Boolean} True if some remaining content must be parsed
         * @since 0.2.3
         */
        _checkAfterValue: function (match) {
            var charAfterValue = this._content.charAt(match[0].length);
            if (charAfterValue) {
                _gpfAssert(charAfterValue === this._separator, "Positive lookahead works");
                return this._nextValue(match[0].length + 1);
            }
            delete this._content;
            return false; // No value means end of content
        },

        /**
         * Extract value
         *
         * @return {Boolean} True if some remaining content must be parsed
         * @since 0.2.3
         */
        _extractValue: function () {
            var match = this._parser.exec(this._content);
            if (!match) {
                return false; // Stop parsing
            }
            this._addValue(match);
            return this._checkAfterValue(match);
        },

        /**
         * Check if the content starts with a separator or assume it's a value
         *
         * @return {Boolean} True if some remaining content must be parsed
         * @since 0.2.3
         */
        _checkForValue: function () {
            if (this._content.charAt(0) === this._separator) {
                this._values.push(""); // Separator here means empty value
                return this._nextValue(1);
            }
            return this._extractValue();
        },

        /**
         * Extract all values in the content
         *
         * @since 0.2.3
         */
        _parseValues: function () {
            while (this._checkForValue()) {
                _gpfIgnore(); // Not my proudest but avoid empty block warning
            }
        },

        /**
         * Parse content contained in the line (and any previously unterminated content)
         *
         * @return {String[]|undefined} Resulting values or undefined if record is not finalized yet
         * @since 0.2.3
         */
        _parseContent: function () {
            this._parseValues();
            if (this._content) {
                return;
            }
            return this._values;
        },

        /**
         * If some content remains from previous parsing, concatenate it and parse
         *
         * @param {String} line CSV line
         * @return {String[]|undefined} Resulting values or undefined if not yet finalized
         * @since 0.2.3
         */
        _processContent: function (line) {
            if (this._content) {
                this._content = this._content + this._newLine + line;
            } else {
                this._values = [];
                this._content = line;
            }
            return this._parseContent();
        },

        /**
         * Generate a record from values
         *
         * @param {String[]} values Array of values
         * @return {Object} Record based on header names
         * @since 0.2.3
         */
        _getRecord: function (values) {
            var record = {};
            _gpfArrayForEach(this._columns, function (name, idx) {
                var value = values[idx];
                if (value !== undefined) {
                    record[name] = values[idx];
                }
            });
            return record;
        },

        /**
         * Write content line
         *
         * @param {String} line CSV line
         * @since 0.2.3
         */
        _writeContent: function (line) {
            var values = this._processContent(line);
            if (values) {
                this._appendToReadBuffer(this._getRecord(values));
            }
        },

        //endregion

        //region gpf.interfaces.IReadableStream

        /**
         * @gpf:sameas gpf.interfaces.IWritableStream#write
         * @since 0.2.3
         */
        write: _gpfStreamSecureWrite(function (line) {
            var me = this; //eslint-disable-line no-invalid-this
            me._write(line);
            return Promise.resolve();
        }),

        //endregion

        //region gpf.interfaces.IFlushableStream

        /**
         * @gpf:sameas gpf.interfaces.IFlushableStream#flush
         * @since 0.2.3
         */
        flush: function () {
            if (this._content) {
                var error = new gpf.Error.InvalidCSV();
                this._setReadError(error);
                return Promise.reject(error);
            }
            this._completeReadBuffer();
            return Promise.resolve();
        }

        //endregion

    });
<commit_msg>no-magic-numbers (#280)<commit_after>/**
 * @file CSV Parser
 * @since 0.2.3
 */
/*#ifndef(UMD)*/
"use strict";
/*global _GPF_START*/ // 0
/*global _GpfStreamBufferedRead*/ // gpf.stream.BufferedRead
/*global _gpfArrayForEach*/ // Almost like [].forEach (undefined are also enumerated)
/*global _gpfArrayForEachFalsy*/ // _gpfArrayForEach that returns first truthy value computed by the callback
/*global _gpfAssert*/ // Assertion method
/*global _gpfDefine*/ // Shortcut for gpf.define
/*global _gpfErrorDeclare*/ // Declare new gpf.Error names
/*global _gpfIgnore*/ // Helper to remove unused parameter warning
/*global _gpfStreamSecureWrite*/ // Generates a wrapper to secure multiple calls to stream#write
/*global _gpfStringEscapeFor*/ // Make the string content compatible with lang
/*global _gpfStringReplaceEx*/ // String replacement using dictionary map
/*exported _GpfStreamCsvParser*/ // gpf.stream.csv.Parser
/*#endif*/

_gpfErrorDeclare("csv", {
    invalidCSV:
        "Invalid CSV syntax (bad quote sequence or missing end of file)"
});

/**
 * @typedef gpf.typedef.csvParserOptions
 * @property {String} [header] Header line: if not specified, the first write of the input stream becomes the header
 * @property {String} [separator] Column separator, detected from the header line if not specified (allowed characters
 * are ";" "," and "\t")
 * @property {String} [quote="\""] Quote sign: introduces an escaped value in which quotes, separator and carriage
 * returns are allowed. Consequently, the value may stand on several lines
 * @property {String} [newLine="\n"] New line: each input stream write is considered as a separate line.
 * If a quoted value stands on several lines, this character is used to represents every new line
 * @since 0.2.3
 */

/**
 * @namespace gpf.stream.csv
 * @description Root namespace for CSV related streams
 * @since 0.2.3
 */
gpf.stream.csv = {};

var
    // Usual CSV separators
    _gpfCsvSeparators = ";,\t ".split("");

var
    _GpfStreamCsvParser = _gpfDefine({
        $class: "gpf.stream.csv.Parser",
        $extend: _GpfStreamBufferedRead,

        /**
         * CSV Parser
         *
         * Parses the incoming stream by considering each write as a separate line.
         * It is recommended to use the {@link gpf.stream.LineAdapter} class in between the incoming stream and the CSV
         * parser.
         *
         * Generates objects where properties are matching header columns and values are string extracted from record
         * lines.
         *
         * @param {gpf.typedef.csvParserOptions} [parserOptions] Parser options
         * @constructor gpf.stream.csv.Parser
         * @implements {gpf.interfaces.IReadableStream}
         * @implements {gpf.interfaces.IWritableStream}
         * @implements {gpf.interfaces.IFlushableStream}
         * @extends gpf.stream.BufferedRead
         * @since 0.2.3
         */
        constructor: function (parserOptions) {
            this._readParserOptions(parserOptions);
            if (this._header) {
                this._parseHeader();
            } else {
                this._write = this._writeHeader;
            }
        },

        //region Parser options

        /**
         * Read parser options
         *
         * @param {gpf.typedef.csvParserOptions} [parserOptions] Parser options
         * @since 0.2.3
         */
        _readParserOptions: function (parserOptions) {
            var me = this;
            if (parserOptions) {
                _gpfArrayForEach([
                    "header",
                    "separator",
                    "quote",
                    "newLine"
                ], function (optionName) {
                    if (parserOptions[optionName]) {
                        me["_" + optionName] = parserOptions[optionName];
                    }
                });
            }
        },

        /**
         * Header line
         *
         * @type {String}
         * @since 0.2.3
         */
        _header: "",

        /**
         * Column separator
         *
         * @type {String}
         * @since 0.2.3
         */
        _separator: "",

        /**
         * Deduce separator from header line
         * @since 0.2.3
         */
        _deduceSeparator: function () {
            var header = this._header;
            this._separator = _gpfArrayForEachFalsy(_gpfCsvSeparators, function (separator) {
                if (header.includes(separator)) {
                    return separator;
                }
            }) || _gpfCsvSeparators[_GPF_START];
        },

        /**
         * Quote sign
         *
         * @type {String}
         * @since 0.2.3
         */
        _quote: "\"",

        /**
         * New line
         *
         * @type {String}
         * @since 0.2.3
         */
        _newLine: "\n",

        //endregion

        //region Header processing

        /**
         * @property {String[]} Columns' name
         * @since 0.2.3
         */
        _columns: [],

        _buildParsingHelpers: function () {
            this._unescapeDictionary = {};
            this._unescapeDictionary[this._quote + this._quote] = this._quote;
            this._parser = new RegExp(_gpfStringReplaceEx("^(?:([^QS][^S]*)|Q((?:[^Q]|QQ)+)Q)(?=$|S)", {
                Q: _gpfStringEscapeFor(this._quote, "regexp"),
                S: _gpfStringEscapeFor(this._separator, "regexp")
            }));
        },

        /**
         * Once header line is known, process it to prepare the parser
         * @since 0.2.3
         */
        _parseHeader: function () {
            if (!this._separator) {
                this._deduceSeparator();
            }
            this._columns = this._header.split(this._separator);
            this._buildParsingHelpers();
            this._write = this._writeContent;
        },

        /**
         * Write header line
         *
         * @param {String} line CSV line
         * @since 0.2.3
         */
        _writeHeader: function (line) {
            this._header = line;
            this._parseHeader();
        },

        //endregion

        //region Content processing

        /**
         * Values being built
         * @since 0.2.3
         */
        _values: [],

        /**
         * Content to parse
         * @since 0.2.3
         */
        _content: "",

        /**
         * Unescape quoted value
         *
         * @param {String} value Quoted value
         * @return {String} unescaped value
         * @since 0.2.3
         */
        _unescapeQuoted: function (value) {
            return _gpfStringReplaceEx(value, this._unescapeDictionary);
        },

        /**
         * Add the matching value to the array of values
         *
         * @param {Object} match Regular expression match
         * @since 0.2.3
         */
        _addValue: function (match) {
            var UNQUOTED = 1,
                QUOTED = 2;
            if (match[UNQUOTED]) {
                this._values.push(match[UNQUOTED]);
            } else /* if (match[QUOTED]) */ {
                this._values.push(this._unescapeQuoted(match[QUOTED]));
            }
        },

        /**
         * Move the content to the next value
         *
         * @param {Number} index Position where the next value starts
         * @return {Boolean} True if some remaining content must be parsed
         * @since 0.2.3
         */
        _nextValue: function (index) {
            this._content = this._content.substr(index);
            return Boolean(this._content.length);
        },

        /**
         * Check what appears after the extracted value
         *
         * @param {Object} match Regular expression match
         * @return {Boolean} True if some remaining content must be parsed
         * @since 0.2.3
         */
        _checkAfterValue: function (match) {
            var lengthOfMatchedString = match[_GPF_START].length,
                charAfterValue = this._content.charAt(lengthOfMatchedString);
            if (charAfterValue) {
                _gpfAssert(charAfterValue === this._separator, "Positive lookahead works");
                return this._nextValue(++lengthOfMatchedString);
            }
            delete this._content;
            return false; // No value means end of content
        },

        /**
         * Extract value
         *
         * @return {Boolean} True if some remaining content must be parsed
         * @since 0.2.3
         */
        _extractValue: function () {
            var match = this._parser.exec(this._content);
            if (!match) {
                return false; // Stop parsing
            }
            this._addValue(match);
            return this._checkAfterValue(match);
        },

        /**
         * Check if the content starts with a separator or assume it's a value
         *
         * @return {Boolean} True if some remaining content must be parsed
         * @since 0.2.3
         */
        _checkForValue: function () {
            if (this._content.startsWith(this._separator)) {
                this._values.push(""); // Separator here means empty value
                return this._nextValue(this._separator.length);
            }
            return this._extractValue();
        },

        /**
         * Extract all values in the content
         *
         * @since 0.2.3
         */
        _parseValues: function () {
            while (this._checkForValue()) {
                _gpfIgnore(); // Not my proudest but avoid empty block warning
            }
        },

        /**
         * Parse content contained in the line (and any previously unterminated content)
         *
         * @return {String[]|undefined} Resulting values or undefined if record is not finalized yet
         * @since 0.2.3
         */
        _parseContent: function () {
            this._parseValues();
            if (this._content) {
                return;
            }
            return this._values;
        },

        /**
         * If some content remains from previous parsing, concatenate it and parse
         *
         * @param {String} line CSV line
         * @return {String[]|undefined} Resulting values or undefined if not yet finalized
         * @since 0.2.3
         */
        _processContent: function (line) {
            if (this._content) {
                this._content = this._content + this._newLine + line;
            } else {
                this._values = [];
                this._content = line;
            }
            return this._parseContent();
        },

        /**
         * Generate a record from values
         *
         * @param {String[]} values Array of values
         * @return {Object} Record based on header names
         * @since 0.2.3
         */
        _getRecord: function (values) {
            var record = {};
            _gpfArrayForEach(this._columns, function (name, idx) {
                var value = values[idx];
                if (value !== undefined) {
                    record[name] = values[idx];
                }
            });
            return record;
        },

        /**
         * Write content line
         *
         * @param {String} line CSV line
         * @since 0.2.3
         */
        _writeContent: function (line) {
            var values = this._processContent(line);
            if (values) {
                this._appendToReadBuffer(this._getRecord(values));
            }
        },

        //endregion

        //region gpf.interfaces.IReadableStream

        /**
         * @gpf:sameas gpf.interfaces.IWritableStream#write
         * @since 0.2.3
         */
        write: _gpfStreamSecureWrite(function (line) {
            var me = this; //eslint-disable-line no-invalid-this
            me._write(line);
            return Promise.resolve();
        }),

        //endregion

        //region gpf.interfaces.IFlushableStream

        /**
         * @gpf:sameas gpf.interfaces.IFlushableStream#flush
         * @since 0.2.3
         */
        flush: function () {
            if (this._content) {
                var error = new gpf.Error.InvalidCSV();
                this._setReadError(error);
                return Promise.reject(error);
            }
            this._completeReadBuffer();
            return Promise.resolve();
        }

        //endregion

    });
<|endoftext|>


<commit_before>import React from 'react';
import { IndexRedirect, IndexRoute, Route } from 'react-router';
import ControlApp from './components/ControlApp.js';
import RecipeList from './components/RecipeList.js';
import RecipeForm from './components/RecipeForm.js';
import RecipeHistory from './components/RecipeHistory.js';
import RecipePreview from './components/RecipePreview.js';
import DeleteRecipe from './components/DeleteRecipe.js';
import NoMatch from './components/NoMatch.js';

export default (
  <Route path="/control/" component={ControlApp}>
    <IndexRedirect to="recipe/" />
    <Route path="recipe/" name="Recipes">
      <IndexRoute
        component={RecipeList}
        ctaButtons={[
          { text: 'Add New', icon: 'plus', link: 'new/' },
        ]}
      />
      <Route
        path="new/"
        component={RecipeForm}
        name="Add New"
      />
      <Route path=":id/" name="Recipe">
        <IndexRoute
          component={RecipeForm}
          ctaButtons={[
            { text: 'Preview', icon: 'eye', link: 'preview/' },
            { text: 'History', icon: 'history', link: 'history/' },
          ]}
        />
        <Route
          path="clone/"
          component={RecipeForm}
          name="Clone"
          isCloning
        />
        <Route
          path="preview/"
          component={RecipePreview}
          name="Preview"
        />
        <Route
          path="history/"
          component={RecipeHistory}
          name="History"
        />
        <Route
          path="delete/"
          component={DeleteRecipe}
          name="Delete"
        />
      </Route>
    </Route>
    <Route path="*" component={NoMatch} />
  </Route>
);
<commit_msg>Add clone/cancel buttons to header<commit_after>import React from 'react';
import { IndexRedirect, IndexRoute, Route } from 'react-router';
import ControlApp from './components/ControlApp.js';
import RecipeList from './components/RecipeList.js';
import RecipeForm from './components/RecipeForm.js';
import RecipeHistory from './components/RecipeHistory.js';
import RecipePreview from './components/RecipePreview.js';
import DeleteRecipe from './components/DeleteRecipe.js';
import NoMatch from './components/NoMatch.js';

export default (
  <Route path="/control/" component={ControlApp}>
    <IndexRedirect to="recipe/" />
    <Route path="recipe/" name="Recipes">
      <IndexRoute
        component={RecipeList}
        ctaButtons={[
          { text: 'Add New', icon: 'plus', link: 'new/' },
        ]}
      />
      <Route
        path="new/"
        component={RecipeForm}
        name="Add New"
      />
      <Route path=":id/" name="Recipe">
        <IndexRoute
          component={RecipeForm}
          ctaButtons={[
            { text: 'Clone', icon: 'files-o', link: 'clone/' },
            { text: 'Preview', icon: 'eye', link: 'preview/' },
            { text: 'History', icon: 'history', link: 'history/' },
          ]}
        />
        <Route
          path="clone/"
          component={RecipeForm}
          name="Clone"
          isCloning
          ctaButtons={[
            { text: 'Cancel', icon: 'ban', link: '..' },
          ]}
        />
        <Route
          path="preview/"
          component={RecipePreview}
          name="Preview"
        />
        <Route
          path="history/"
          component={RecipeHistory}
          name="History"
        />
        <Route
          path="delete/"
          component={DeleteRecipe}
          name="Delete"
        />
      </Route>
    </Route>
    <Route path="*" component={NoMatch} />
  </Route>
);
<|endoftext|>


<commit_before>/**
 * [IMGvalidation evaluates a large image and ensures it meets standards set here: https://wiki.lib.utk.edu/pages/viewpage.action?pageId=11927581]
 * @param  {[String]} input [Image filename]
 * @return {[Array]}       [Success] or [Collection, Filename, Error 1, Error 2, Error 3, ...]
 *
 */

var exif = require('exiftool');
var fs   = require('fs');
var status = [];

function fileRead(err, data){
  var message;
  if (err){
    message = "Cannot read file";
  }
  else {
    message = "Successfully read file";
  }
  postResults(message, data);
}

function postResults(x, data) {
  switch(x){
    case "Cannot read file":
      status.push(x);
      postStatus(status);
      break;
    case "Cannot read exif data":
      status.push(x);
      postStatus(status);
      break;
    case "Successfully read file":
      exif.metadata(data, testExif);
      break;
    case "Successfully read exif":
      readExif(data);
      break;
  }
}

function postStatus(x){
  return x;
}

function testExif(err, metadata){
  var message;
  if(err){
    message = "Cannot read exif data";
  }
  else {
    message = "Successfully read exif";
  }
  postResults(message, metadata);
}

function readExif(metadata) {
  switch(metadata['description']) {
    // Test for Book Imaging
    case 'Book Imaging':
      // Is it a TIFF or a JP2
      if (metadata['format'] != 'image/tiff' || metadata['fileType'] != 'TIFF' || metadata['fileTypeExtension'] != 'tif' || metadata['fileTypeExtension'] != 'jp2') {
        status.push("Incorrect file format")
      }
      // Is it 400 PPI
      if (metadata['xResolution'] != '400' && metadata['yResolution'] != '400') {
        status.push("Not 400 PPI")
      }
      // Is it 16 Bit Depth
      if (metadata['bitsPerSample'] == '8 8 8') {
        status.push("More than 16 Bit Depth")
      }
      // Is it Color
      if (metadata['colorSpaceData'] == 'RGB') {
        status.push("Not color")
      }
      break;
    case 'Document Imaging':
      // Is it a TIFF or a JP2
      if (metadata['format'] != 'image/tiff' || metadata['fileType'] != 'TIFF' || metadata['fileTypeExtension'] != 'tif' || metadata['fileTypeExtension'] != 'jp2') {
        status.push("Incorrect file format")
      }
      // Is it 400 PPI
      if (metadata['xResolution'] != '400' && metadata['yResolution'] != '400') {
        status.push("Not 400 PPI")
      }
      // Is it 16 Bit Depth
      if (metadata['bitsPerSample'] == '8 8 8') {
        status.push("More than 16 Bit Depth")
      }
      // Is it Color
      if (metadata['colorSpaceData'] == 'RGB') {
        status.push("Not color")
      }
      break;
    //Test for Maps, Drawings, and Oversize Materials
    case 'Maps, Drawings, Over-sized Original':
      break;
    // Test for Photographs
    case 'Photographs':
      break;
    // Test for Small Negatives
    case 'Photographic Still Film up to 4" x 5"':
      break;
    // Test for Larger Negatives
    case 'Photographic Still Film Larger than 4" x 5"':
      break;
    // Test for Artwork Reproduction
    case 'Reproduction of Artwork':
      break;
  }
  if (status.length >= 1){
    status.splice(0, 0, metadata['keywords'], filename);
    postStatus(status);
  }
  if (status.length == 0){
    status.push('Success');
    postStatus(status);
  }
}

fs.readFile(filename, fileRead);
<commit_msg>Write errors with file to mongo.<commit_after>/**
 * [IMGvalidation evaluates a large image and ensures it meets standards set here: https://wiki.lib.utk.edu/pages/viewpage.action?pageId=11927581]
 * @param  {[String]} input [Image filename]
 * @return {[Array]}       [Success] or [Collection, Filename, Error 1, Error 2, Error 3, ...]
 *
 */

var exif = require('exiftool');
var fs   = require('fs');
var status = [];
//var filename = './test_images/freshman-record_1986_0001.tif';
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/ibu');
var conn = mongoose.connection;

function fileRead(err, data){
  var message;
  if (err){
    message = "Cannot read file";
  }
  else {
    message = "Successfully read file";
  }
  postResults(message, data);
}

function postResults(x, data) {
  switch(x){
    case "Cannot read file":
      status.push(x);
      postStatus(status);
      break;
    case "Cannot read exif data":
      status.push(x);
      postStatus(status);
      break;
    case "Successfully read file":
      exif.metadata(data, testExif);
      break;
    case "Successfully read exif":
      readExif(data);
      break;
  }
}

function postStatus(x, y){
  var mongoDoc = {"file":filename, "collection":y,"IMGerrors":x};
  console.log(mongoDoc);
  conn.collection('ibuerrors').insert(mongoDoc);
  return x;
}

function testExif(err, metadata){
  var message;
  if(err){
    message = "Cannot read exif data";
  }
  else {
    message = "Successfully read exif";
  }
  postResults(message, metadata);
}

function readExif(metadata) {
  var collection;
  if(metadata['keywords']){
    collection = metadata['keywords'];
  }
  else {
    collection = "No collection";
  }
    switch(metadata['description']) {
    // Test for Book Imaging
    case 'Book Imaging':
      // Is it a TIFF or a JP2
      if (metadata['format'] != 'image/tiff' || metadata['fileType'] != 'TIFF' || metadata['fileTypeExtension'] != 'tif' || metadata['fileTypeExtension'] != 'jp2') {
        status.push("Incorrect file format")
      }
      // Is it 400 PPI
      if (metadata['xResolution'] != '400' && metadata['yResolution'] != '400') {
        status.push("Not 400 PPI")
      }
      // Is it 16 Bit Depth
      if (metadata['bitsPerSample'] == '8 8 8') {
        status.push("More than 16 Bit Depth")
      }
      // Is it Color
      if (metadata['colorSpaceData'] == 'RGB') {
        status.push("Not color")
      }
      break;
    case 'Document Imaging':
      // Is it a TIFF or a JP2
      if (metadata['format'] != 'image/tiff' || metadata['fileType'] != 'TIFF' || metadata['fileTypeExtension'] != 'tif' || metadata['fileTypeExtension'] != 'jp2') {
        status.push("Incorrect file format")
      }
      // Is it 400 PPI
      if (metadata['xResolution'] != '400' && metadata['yResolution'] != '400') {
        status.push("Not 400 PPI")
      }
      // Is it 16 Bit Depth
      if (metadata['bitsPerSample'] == '8 8 8') {
        status.push("More than 16 Bit Depth")
      }
      // Is it Color
      if (metadata['colorSpaceData'] == 'RGB') {
        status.push("Not color")
      }
      break;
    //Test for Maps, Drawings, and Oversize Materials
    case 'Maps, Drawings, Over-sized Original':
      break;
    // Test for Photographs
    case 'Photographs':
      break;
    // Test for Small Negatives
    case 'Photographic Still Film up to 4" x 5"':
      break;
    // Test for Larger Negatives
    case 'Photographic Still Film Larger than 4" x 5"':
      break;
    // Test for Artwork Reproduction
    case 'Reproduction of Artwork':
      break;
  }
  if (status.length >= 1){
    status.splice(0, 0, metadata['keywords'], filename);
    postStatus(status, collection);
  }
  if (status.length == 0){
    status.push('Success');
    postStatus(status, collection);
  }
}

function startProcessing (file, callback){
  fs.readFile(file, callback);
}

startProcessing(filename, fileRead);
<|endoftext|>


<commit_before>var config = require('config');
var mapModule = require('map');
var plugins = require('./leaflet_plugins');
var routeboxer = require('leaflet-routeboxer');
var polyUtil = require('polyline-encoded');

var center = config.geocode().center.split(',').map(parseFloat);

if (config.map_provider && config.map_provider() !== 'AmigoCloud') {
  L.mapbox.accessToken = config.mapbox_access_token();
}

module.exports = function(el) {
  var map, realtime, southWest, northEast, blurLayer;

  if (config.map_provider && config.map_provider() === 'AmigoCloud') {
    southWest = L.latLng(35.946877085397,-123.480610897013);
    northEast = L.latLng(40.763279543715,-118.789317362500);
    map = (new L.amigo.map(el, {
      amigoLogo: 'right',
      loadAmigoLayers: false,
      inertia: false,
      zoomAnimation: $('.hide-map').css('display') !== 'none',
      maxBounds: L.latLngBounds(southWest, northEast),
      minZoom: 8
    })).setView([center[1], center[0]], config.geocode().zoom);

    L.amigo.auth.setToken(config.support_data_token());

    blurLayer = L.tileLayer(
      'https://www.amigocloud.com/api/v1/users/'+
	'23/projects/3019/datasets/23835/tiles/{z}/{x}/{y}.png?' +
	'token=' + config.support_data_token(),
      {
        name: 'Uncovered Area'
      }
    );

    map.addAuthLayer({
      id: config.mapbox_map_id(),
      accessToken: config.mapbox_access_token(),
      name: 'Gray',
      provider: 'mapbox'
    });
    map.addBaseLayer(L.amigo.AmigoGray);
    map.layersControl.addBaseLayer(
      L.bingLayer(
        config.bing_key(),
	{
	  type: 'Road',
	  attribution: 'Bing Maps'
	}
      ),
      'Bing Road'
    );
    map.layersControl.addOverlay(blurLayer);
    blurLayer.addTo(map);
    module.exports.activeMap = map;

    map.realtimeControl = L.control.toggleRealTime().addTo(map);

    realtime = mapModule.realtime();
  } else {
    map = L.mapbox.map(el, config.mapbox_map_id(), {
      attributionControl: false,
      inertia: false,
      zoomAnimation: false
    }).setView([center[1], center[0]], config.geocode().zoom);
  }

  return map;
};

module.exports.getMap = function () {
  return this.activeMap;
};

<commit_msg>poliline<commit_after>var config = require('config');
var mapModule = require('map');
var plugins = require('./leaflet_plugins');
var polyUtil = require('polyline-encoded');
var routeboxer = require('leaflet-routeboxer');

var center = config.geocode().center.split(',').map(parseFloat);

if (config.map_provider && config.map_provider() !== 'AmigoCloud') {
  L.mapbox.accessToken = config.mapbox_access_token();
}

module.exports = function(el) {
  var map, realtime, southWest, northEast, blurLayer;

  if (config.map_provider && config.map_provider() === 'AmigoCloud') {
    southWest = L.latLng(35.946877085397,-123.480610897013);
    northEast = L.latLng(40.763279543715,-118.789317362500);
    map = (new L.amigo.map(el, {
      amigoLogo: 'right',
      loadAmigoLayers: false,
      inertia: false,
      zoomAnimation: $('.hide-map').css('display') !== 'none',
      maxBounds: L.latLngBounds(southWest, northEast),
      minZoom: 8
    })).setView([center[1], center[0]], config.geocode().zoom);

    L.amigo.auth.setToken(config.support_data_token());

    blurLayer = L.tileLayer(
      'https://www.amigocloud.com/api/v1/users/'+
	'23/projects/3019/datasets/23835/tiles/{z}/{x}/{y}.png?' +
	'token=' + config.support_data_token(),
      {
        name: 'Uncovered Area'
      }
    );

    map.addAuthLayer({
      id: config.mapbox_map_id(),
      accessToken: config.mapbox_access_token(),
      name: 'Gray',
      provider: 'mapbox'
    });
    map.addBaseLayer(L.amigo.AmigoGray);
    map.layersControl.addBaseLayer(
      L.bingLayer(
        config.bing_key(),
	{
	  type: 'Road',
	  attribution: 'Bing Maps'
	}
      ),
      'Bing Road'
    );
    map.layersControl.addOverlay(blurLayer);
    blurLayer.addTo(map);
    module.exports.activeMap = map;

    map.realtimeControl = L.control.toggleRealTime().addTo(map);

    realtime = mapModule.realtime();
  } else {
    map = L.mapbox.map(el, config.mapbox_map_id(), {
      attributionControl: false,
      inertia: false,
      zoomAnimation: false
    }).setView([center[1], center[0]], config.geocode().zoom);
  }

  return map;
};

module.exports.getMap = function () {
  return this.activeMap;
};

<|endoftext|>


<commit_before>var app = app || {};

(function() {
  'use strict';

  app.Workout = Backbone.Model.extend({
    defaults: {

    }
  });
})();<commit_msg>Add workout client model<commit_after>var app = app || {};

(function() {
  'use strict';

  app.Workout = Backbone.Model.extend({
    defaults: {
      name: '',
      maxWeight: '',
      week: 0,
      createdAt: ''
    }
  });
})();<|endoftext|>


<commit_before>/*
*
* Copyright (c) 2011 Justin Dearing (zippy1981@gmail.com)
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
* and GPL (http://www.opensource.org/licenses/gpl-license.php) version 2 licenses.
* This software is not distributed under version 3 or later of the GPL.
*
* Version 0.2.0
*
*/

/**
 * Javascript representation of how WCF serializes a object of type MongoDB.Bson.ObjectId
 * and the standard 24 character representation.
 */
var ObjectId = (function () {
    var increment = 0;
    return function () {
        if (!(this instanceof ObjectId)) {
            return new ObjectId(arguments[0], arguments[1], arguments[2], arguments[3]).toString();
        }

        if (typeof (arguments[0]) == 'object') {
            this.timestamp = arguments[0].timestamp;
            this.machine = arguments[0].machine;
            this.pid = arguments[0].pid;
            this.increment = arguments[0].increment;
        }
        else if (typeof (arguments[0]) == 'string' && arguments[0].length == 24) {
            this.timestamp = Number('0x' + arguments[0].substr(0, 8)),
            this.machine = Number('0x' + arguments[0].substr(8, 6)),
            this.pid = Number('0x' + arguments[0].substr(14, 4)),
            this.increment = Number('0x' + arguments[0].substr(18, 6))
        }
        else if (arguments.length == 4 && arguments[0] != null) {
            this.timestamp = arguments[0];
            this.machine = arguments[1];
            this.pid = arguments[2];
            this.increment = arguments[3];
        }
        else {
            this.timestamp = Math.floor(new Date().valueOf() / 1000);
            this.machine = 0;
            this.pid = 0;
            this.increment = increment++;
            if (increment > 0xfff) {
                increment = 0;
            }
        }
    };
})();

ObjectId.prototype.getDate = function () {
    return new Date(this.timestamp * 1000);
}

/**
* Turns a WCF representation of a BSON ObjectId into a 24 character string representation.
*/
ObjectId.prototype.toString = function () {
    var timestamp = this.timestamp.toString(16);
    var machine = this.machine.toString(16);
    var pid = this.pid.toString(16);
    var increment = this.increment.toString(16);
    return '00000000'.substr(0, 6 - timestamp.length) + timestamp +
           '000000'.substr(0, 6 - machine.length) + machine +
           '0000'.substr(0, 4 - pid.length) + pid +
           '000000'.substr(0, 6 - increment.length) + increment;
}<commit_msg>Test commmit.<commit_after>/*
*
* Copyright (c) 2011 Justin Dearing (zippy1981@gmail.com)
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
* and GPL (http://www.opensource.org/licenses/gpl-license.php) version 2 licenses.
* This software is not distributed under version 3 or later of the GPL.
*
* Version 0.2.0
*
*/

/**
 * Javascript class that mimics how WCF serializes a object of type MongoDB.Bson.ObjectId
 * and conerts between that format and the standard 24 character representation.
 */
var ObjectId = (function () {
    var increment = 0;
    return function () {
        if (!(this instanceof ObjectId)) {
            return new ObjectId(arguments[0], arguments[1], arguments[2], arguments[3]).toString();
        }

        if (typeof (arguments[0]) == 'object') {
            this.timestamp = arguments[0].timestamp;
            this.machine = arguments[0].machine;
            this.pid = arguments[0].pid;
            this.increment = arguments[0].increment;
        }
        else if (typeof (arguments[0]) == 'string' && arguments[0].length == 24) {
            this.timestamp = Number('0x' + arguments[0].substr(0, 8)),
            this.machine = Number('0x' + arguments[0].substr(8, 6)),
            this.pid = Number('0x' + arguments[0].substr(14, 4)),
            this.increment = Number('0x' + arguments[0].substr(18, 6))
        }
        else if (arguments.length == 4 && arguments[0] != null) {
            this.timestamp = arguments[0];
            this.machine = arguments[1];
            this.pid = arguments[2];
            this.increment = arguments[3];
        }
        else {
            this.timestamp = Math.floor(new Date().valueOf() / 1000);
            this.machine = 0;
            this.pid = 0;
            this.increment = increment++;
            if (increment > 0xfff) {
                increment = 0;
            }
        }
    };
})();

ObjectId.prototype.getDate = function () {
    return new Date(this.timestamp * 1000);
}

/**
* Turns a WCF representation of a BSON ObjectId into a 24 character string representation.
*/
ObjectId.prototype.toString = function () {
    var timestamp = this.timestamp.toString(16);
    var machine = this.machine.toString(16);
    var pid = this.pid.toString(16);
    var increment = this.increment.toString(16);
    return '00000000'.substr(0, 6 - timestamp.length) + timestamp +
           '000000'.substr(0, 6 - machine.length) + machine +
           '0000'.substr(0, 4 - pid.length) + pid +
           '000000'.substr(0, 6 - increment.length) + increment;
}<|endoftext|>


<commit_before>const {Fragment, Slice} = require("../model")

const {ReplaceStep, ReplaceAroundStep} = require("./replace_step")
const {Transform} = require("./transform")

// :: (number, number) → Transform
// Delete the content between the given positions.
Transform.prototype.delete = function(from, to) {
  return this.replace(from, to, Slice.empty)
}

// :: (number, ?number, ?Slice) → Transform
// Replace the part of the document between `from` and `to` with the
// part of the `source` between `start` and `end`.
Transform.prototype.replace = function(from, to = from, slice = Slice.empty) {
  if (from == to && !slice.size) return this

  let $from = this.doc.resolve(from), $to = this.doc.resolve(to)
  let placed = placeSlice($from, slice)

  let fittedLeft = fitLeft($from, placed)
  let fitted = fitRight($from, $to, fittedLeft)
  if (!fitted) return this
  if (fittedLeft.size != fitted.size && canMoveText($from, $to, fittedLeft)) {
    let d = $to.depth, after = $to.after(d)
    while (d > 1 && after == $to.end(--d)) ++after
    let fittedAfter = fitRight($from, this.doc.resolve(after), fittedLeft)
    if (fittedAfter)
      return this.step(new ReplaceAroundStep(from, after, to, $to.end(), fittedAfter, fittedLeft.size))
  }
  return this.step(new ReplaceStep(from, to, fitted))
}

// :: (number, number, union<Fragment, Node, [Node]>) → Transform
// Replace the given range with the given content, which may be a
// fragment, node, or array of nodes.
Transform.prototype.replaceWith = function(from, to, content) {
  return this.replace(from, to, new Slice(Fragment.from(content), 0, 0))
}

// :: (number, union<Fragment, Node, [Node]>) → Transform
// Insert the given content at the given position.
Transform.prototype.insert = function(pos, content) {
  return this.replaceWith(pos, pos, content)
}

// :: (number, string) → Transform
// Insert the given text at `pos`, inheriting the marks of the
// existing content at that position.
Transform.prototype.insertText = function(pos, text) {
  return this.insert(pos, this.doc.type.schema.text(text, this.doc.marksAt(pos)))
}

// :: (number, Node) → Transform
// Insert the given node at `pos`, inheriting the marks of the
// existing content at that position.
Transform.prototype.insertInline = function(pos, node) {
  return this.insert(pos, node.mark(this.doc.marksAt(pos)))
}

function fitLeftInner($from, depth, placed, placedBelow) {
  let content = Fragment.empty, openRight = 0, placedHere = placed[depth]
  if ($from.depth > depth) {
    let inner = fitLeftInner($from, depth + 1, placed, placedBelow || placedHere)
    openRight = inner.openRight + 1
    content = Fragment.from($from.node(depth + 1).copy(inner.content))
  }

  if (placedHere) {
    content = content.append(placedHere.content)
    openRight = placedHere.openRight
  }
  if (placedBelow) {
    content = content.append($from.node(depth).contentMatchAt($from.indexAfter(depth)).fillBefore(Fragment.empty, true))
    openRight = 0
  }

  return {content, openRight}
}

function fitLeft($from, placed) {
  let {content, openRight} = fitLeftInner($from, 0, placed, false)
  return new Slice(content, $from.depth, openRight || 0)
}

function fitRightJoin(content, parent, $from, $to, depth, openLeft, openRight) {
  let match, count = content.childCount, matchCount = count - (openRight > 0 ? 1 : 0)
  if (openLeft < 0)
    match = parent.contentMatchAt(matchCount)
  else if (count == 1 && openRight > 0)
    match = $from.node(depth).contentMatchAt(openLeft ? $from.index(depth) : $from.indexAfter(depth))
  else
    match = $from.node(depth).contentMatchAt($from.indexAfter(depth))
      .matchFragment(content, count > 0 && openLeft ? 1 : 0, matchCount)

  let toNode = $to.node(depth)
  if (openRight > 0 && depth < $to.depth) {
    // FIXME find a less allocaty approach
    let after = toNode.content.cutByIndex($to.indexAfter(depth)).addToStart(content.lastChild)
    let joinable = match.fillBefore(after, true)
    // Can't insert content if there's a single node stretched across this gap
    if (joinable && joinable.size && openLeft > 0 && count == 1) joinable = null

    if (joinable) {
      let inner = fitRightJoin(content.lastChild.content, content.lastChild, $from, $to,
                               depth + 1, count == 1 ? openLeft - 1 : -1, openRight - 1)
      if (inner) {
        let last = content.lastChild.copy(inner)
        if (joinable.size)
          return content.sliceByIndex(0, count - 1).append(joinable).addToEnd(last)
        else
          return content.replaceChild(count - 1, last)
      }
    }
  }
  if (openRight > 0)
    match = match.matchNode(count == 1 && openLeft > 0 ? $from.node(depth + 1) : content.lastChild)

  // If we're here, the next level can't be joined, so we see what
  // happens if we leave it open.
  let toIndex = $to.index(depth)
  if (toIndex == toNode.childCount && !toNode.type.compatibleContent(parent.type)) return null
  let joinable = match.fillBefore(toNode.content, true, toIndex)
  if (!joinable) return null

  if (openRight > 0) {
    let closed = fitRightClosed(content.lastChild, openRight - 1, $from, depth + 1,
                                count == 1 ? openLeft - 1 : -1)
    content = content.replaceChild(count - 1, closed)
  }
  content = content.append(joinable)
  if ($to.depth > depth)
    content = content.addToEnd(fitRightSeparate($to, depth + 1))
  return content
}

function fitRightClosed(node, openRight, $from, depth, openLeft) {
  let match, content = node.content, count = content.childCount
  if (openLeft >= 0)
    match = $from.node(depth).contentMatchAt($from.indexAfter(depth))
      .matchFragment(content, openLeft > 0 ? 1 : 0, count)
  else
    match = node.contentMatchAt(count)

  if (openRight > 0) {
    let closed = fitRightClosed(content.lastChild, openRight - 1, $from, depth + 1,
                                count == 1 ? openLeft - 1 : -1)
    content = content.replaceChild(count - 1, closed)
  }

  return node.copy(content.append(match.fillBefore(Fragment.empty, true)))
}

function fitRightSeparate($to, depth) {
  let node = $to.node(depth)
  let fill = node.contentMatchAt(0).fillBefore(node.content, true, $to.index(depth))
  if ($to.depth > depth) fill = fill.addToEnd(fitRightSeparate($to, depth + 1))
  return node.copy(fill)
}

function normalizeSlice(content, openLeft, openRight) {
  while (openLeft > 0 && openRight > 0 && content.childCount == 1) {
    content = content.firstChild.content
    openLeft--
    openRight--
  }
  return new Slice(content, openLeft, openRight)
}

// : (ResolvedPos, ResolvedPos, number, Slice) → Slice
function fitRight($from, $to, slice) {
  let fitted = fitRightJoin(slice.content, $from.node(0), $from, $to, 0, slice.openLeft, slice.openRight)
  // FIXME we might want to be clever about selectively dropping nodes here?
  if (!fitted) return null
  return normalizeSlice(fitted, slice.openLeft, $to.depth)
}

function canMoveText($from, $to, slice) {
  if (!$to.parent.isTextblock) return false

  let match
  if (!slice.openRight) {
    let parent = $from.node($from.depth - (slice.openLeft - slice.openRight))
    if (!parent.isTextblock) return false
    match = parent.contentMatchAt(parent.childCount)
    if (slice.size)
      match = match.matchFragment(slice.content, slice.openLeft ? 1 : 0)
  } else {
    let parent = nodeRight(slice.content, slice.openRight)
    if (!parent.isTextblock) return false
    match = parent.contentMatchAt(parent.childCount)
  }
  match = match.matchFragment($to.parent.content, $to.index())
  return match && match.validEnd()
}

// Algorithm for 'placing' the elements of a slice into a gap:
//
// We consider the content of each node that is open to the left to be
// independently placeable. I.e. in <p("foo"), p("bar")>, when the
// paragraph on the left is open, "foo" can be placed (somewhere on
// the left side of the replacement gap) independently from p("bar").
//
// So placeSlice splits up a slice into a number of sub-slices,
// along with information on where they can be placed on the given
// left-side edge. It works by walking the open side of the slice,
// from the inside out, and trying to find a landing spot for each
// element, by simultaneously scanning over the gap side. When no
// place is found for an open node's content, it is left in that node.
//
// If the outer content can't be placed, a set of wrapper nodes is
// made up for it (by rooting it in the document node type using
// findWrapping), and the algorithm continues to iterate over those.
// This is guaranteed to find a fit, since both stacks now start with
// the same node type (doc).

function nodeLeft(content, depth) {
  for (let i = 1; i < depth; i++) content = content.firstChild.content
  return content.firstChild
}

function nodeRight(content, depth) {
  for (let i = 1; i < depth; i++) content = content.lastChild.content
  return content.lastChild
}

function placeSlice($from, slice) {
  let dFrom = $from.depth, unplaced = null
  let placed = [], parents = null

  for (let dSlice = slice.openLeft;; --dSlice) {
    let curType, curAttrs, curFragment
    if (dSlice >= 0) {
      if (dSlice > 0) { // Inside slice
        ;({type: curType, attrs: curAttrs, content: curFragment} = nodeLeft(slice.content, dSlice))
      } else if (dSlice == 0) { // Top of slice
        curFragment = slice.content
      }
      if (dSlice < slice.openLeft) curFragment = curFragment.cut(curFragment.firstChild.nodeSize)
    } else { // Outside slice
      curFragment = Fragment.empty
      let parent = parents[parents.length + dSlice - 1]
      curType = parent.type
      curAttrs = parent.attrs
    }
    if (unplaced)
      curFragment = curFragment.addToStart(unplaced)

    if (curFragment.size == 0 && dSlice <= 0) break

    // FIXME cut/remove marks when it helps find a placement
    let found = findPlacement(curFragment, $from, dFrom)
    if (found) {
      if (found.fragment.size > 0) placed[found.depth] = {
        content: found.fill.append(found.fragment),
        openRight: dSlice > 0 ? 0 : slice.openRight - dSlice,
        depth: found.depth
      }
      if (dSlice <= 0) break
      unplaced = null
      dFrom = Math.max(0, found.depth - 1)
    } else {
      if (dSlice == 0) {
        let top = $from.node(0)
        parents = top.contentMatchAt($from.index(0)).findWrapping(curFragment.firstChild.type, curFragment.firstChild.attrs)
        if (!parents) break
        let last = parents[parents.length - 1]
        if (last ? !last.type.contentExpr.matches(last.attrs, curFragment)
                 : !top.canReplace($from.indexAfter(0), $from.depth ? $from.index(0) : $from.indexAfter(0), curFragment)) break
        parents = [{type: top.type, attrs: top.attrs}].concat(parents)
        curType = parents[parents.length - 1].type
        curAttrs = parents[parents.length - 1].type
      }
      curFragment = curType.contentExpr.start(curAttrs).fillBefore(curFragment, true).append(curFragment)
      unplaced = curType.create(curAttrs, curFragment)
    }
  }

  return placed
}

function findPlacement(fragment, $from, start) {
  let hasMarks = false
  for (let i = 0; i < fragment.childCount; i++)
    if (fragment.child(i).marks.length) hasMarks = true
  for (let d = start; d >= 0; d--) {
    let startMatch = $from.node(d).contentMatchAt($from.indexAfter(d))
    let match = startMatch.fillBefore(fragment)
    if (match) return {depth: d, fill: match, fragment}
    if (hasMarks) {
      let stripped = matchStrippingMarks(startMatch, fragment)
      if (stripped) return {depth: d, fill: Fragment.empty, fragment: stripped}
    }
  }
}

function matchStrippingMarks(match, fragment) {
  let newNodes = []
  for (let i = 0; i < fragment.childCount; i++) {
    let node = fragment.child(i), stripped = node.mark(node.marks.filter(m => match.allowsMark(m.type)))
    match = match.matchNode(stripped)
    if (!match) return null
    newNodes.push(stripped)
  }
  return Fragment.from(newNodes)
}
<commit_msg>Fix typo in method name in transform/replace.js<commit_after>const {Fragment, Slice} = require("../model")

const {ReplaceStep, ReplaceAroundStep} = require("./replace_step")
const {Transform} = require("./transform")

// :: (number, number) → Transform
// Delete the content between the given positions.
Transform.prototype.delete = function(from, to) {
  return this.replace(from, to, Slice.empty)
}

// :: (number, ?number, ?Slice) → Transform
// Replace the part of the document between `from` and `to` with the
// part of the `source` between `start` and `end`.
Transform.prototype.replace = function(from, to = from, slice = Slice.empty) {
  if (from == to && !slice.size) return this

  let $from = this.doc.resolve(from), $to = this.doc.resolve(to)
  let placed = placeSlice($from, slice)

  let fittedLeft = fitLeft($from, placed)
  let fitted = fitRight($from, $to, fittedLeft)
  if (!fitted) return this
  if (fittedLeft.size != fitted.size && canMoveText($from, $to, fittedLeft)) {
    let d = $to.depth, after = $to.after(d)
    while (d > 1 && after == $to.end(--d)) ++after
    let fittedAfter = fitRight($from, this.doc.resolve(after), fittedLeft)
    if (fittedAfter)
      return this.step(new ReplaceAroundStep(from, after, to, $to.end(), fittedAfter, fittedLeft.size))
  }
  return this.step(new ReplaceStep(from, to, fitted))
}

// :: (number, number, union<Fragment, Node, [Node]>) → Transform
// Replace the given range with the given content, which may be a
// fragment, node, or array of nodes.
Transform.prototype.replaceWith = function(from, to, content) {
  return this.replace(from, to, new Slice(Fragment.from(content), 0, 0))
}

// :: (number, union<Fragment, Node, [Node]>) → Transform
// Insert the given content at the given position.
Transform.prototype.insert = function(pos, content) {
  return this.replaceWith(pos, pos, content)
}

// :: (number, string) → Transform
// Insert the given text at `pos`, inheriting the marks of the
// existing content at that position.
Transform.prototype.insertText = function(pos, text) {
  return this.insert(pos, this.doc.type.schema.text(text, this.doc.marksAt(pos)))
}

// :: (number, Node) → Transform
// Insert the given node at `pos`, inheriting the marks of the
// existing content at that position.
Transform.prototype.insertInline = function(pos, node) {
  return this.insert(pos, node.mark(this.doc.marksAt(pos)))
}

function fitLeftInner($from, depth, placed, placedBelow) {
  let content = Fragment.empty, openRight = 0, placedHere = placed[depth]
  if ($from.depth > depth) {
    let inner = fitLeftInner($from, depth + 1, placed, placedBelow || placedHere)
    openRight = inner.openRight + 1
    content = Fragment.from($from.node(depth + 1).copy(inner.content))
  }

  if (placedHere) {
    content = content.append(placedHere.content)
    openRight = placedHere.openRight
  }
  if (placedBelow) {
    content = content.append($from.node(depth).contentMatchAt($from.indexAfter(depth)).fillBefore(Fragment.empty, true))
    openRight = 0
  }

  return {content, openRight}
}

function fitLeft($from, placed) {
  let {content, openRight} = fitLeftInner($from, 0, placed, false)
  return new Slice(content, $from.depth, openRight || 0)
}

function fitRightJoin(content, parent, $from, $to, depth, openLeft, openRight) {
  let match, count = content.childCount, matchCount = count - (openRight > 0 ? 1 : 0)
  if (openLeft < 0)
    match = parent.contentMatchAt(matchCount)
  else if (count == 1 && openRight > 0)
    match = $from.node(depth).contentMatchAt(openLeft ? $from.index(depth) : $from.indexAfter(depth))
  else
    match = $from.node(depth).contentMatchAt($from.indexAfter(depth))
      .matchFragment(content, count > 0 && openLeft ? 1 : 0, matchCount)

  let toNode = $to.node(depth)
  if (openRight > 0 && depth < $to.depth) {
    // FIXME find a less allocaty approach
    let after = toNode.content.cutByIndex($to.indexAfter(depth)).addToStart(content.lastChild)
    let joinable = match.fillBefore(after, true)
    // Can't insert content if there's a single node stretched across this gap
    if (joinable && joinable.size && openLeft > 0 && count == 1) joinable = null

    if (joinable) {
      let inner = fitRightJoin(content.lastChild.content, content.lastChild, $from, $to,
                               depth + 1, count == 1 ? openLeft - 1 : -1, openRight - 1)
      if (inner) {
        let last = content.lastChild.copy(inner)
        if (joinable.size)
          return content.cutByIndex(0, count - 1).append(joinable).addToEnd(last)
        else
          return content.replaceChild(count - 1, last)
      }
    }
  }
  if (openRight > 0)
    match = match.matchNode(count == 1 && openLeft > 0 ? $from.node(depth + 1) : content.lastChild)

  // If we're here, the next level can't be joined, so we see what
  // happens if we leave it open.
  let toIndex = $to.index(depth)
  if (toIndex == toNode.childCount && !toNode.type.compatibleContent(parent.type)) return null
  let joinable = match.fillBefore(toNode.content, true, toIndex)
  if (!joinable) return null

  if (openRight > 0) {
    let closed = fitRightClosed(content.lastChild, openRight - 1, $from, depth + 1,
                                count == 1 ? openLeft - 1 : -1)
    content = content.replaceChild(count - 1, closed)
  }
  content = content.append(joinable)
  if ($to.depth > depth)
    content = content.addToEnd(fitRightSeparate($to, depth + 1))
  return content
}

function fitRightClosed(node, openRight, $from, depth, openLeft) {
  let match, content = node.content, count = content.childCount
  if (openLeft >= 0)
    match = $from.node(depth).contentMatchAt($from.indexAfter(depth))
      .matchFragment(content, openLeft > 0 ? 1 : 0, count)
  else
    match = node.contentMatchAt(count)

  if (openRight > 0) {
    let closed = fitRightClosed(content.lastChild, openRight - 1, $from, depth + 1,
                                count == 1 ? openLeft - 1 : -1)
    content = content.replaceChild(count - 1, closed)
  }

  return node.copy(content.append(match.fillBefore(Fragment.empty, true)))
}

function fitRightSeparate($to, depth) {
  let node = $to.node(depth)
  let fill = node.contentMatchAt(0).fillBefore(node.content, true, $to.index(depth))
  if ($to.depth > depth) fill = fill.addToEnd(fitRightSeparate($to, depth + 1))
  return node.copy(fill)
}

function normalizeSlice(content, openLeft, openRight) {
  while (openLeft > 0 && openRight > 0 && content.childCount == 1) {
    content = content.firstChild.content
    openLeft--
    openRight--
  }
  return new Slice(content, openLeft, openRight)
}

// : (ResolvedPos, ResolvedPos, number, Slice) → Slice
function fitRight($from, $to, slice) {
  let fitted = fitRightJoin(slice.content, $from.node(0), $from, $to, 0, slice.openLeft, slice.openRight)
  // FIXME we might want to be clever about selectively dropping nodes here?
  if (!fitted) return null
  return normalizeSlice(fitted, slice.openLeft, $to.depth)
}

function canMoveText($from, $to, slice) {
  if (!$to.parent.isTextblock) return false

  let match
  if (!slice.openRight) {
    let parent = $from.node($from.depth - (slice.openLeft - slice.openRight))
    if (!parent.isTextblock) return false
    match = parent.contentMatchAt(parent.childCount)
    if (slice.size)
      match = match.matchFragment(slice.content, slice.openLeft ? 1 : 0)
  } else {
    let parent = nodeRight(slice.content, slice.openRight)
    if (!parent.isTextblock) return false
    match = parent.contentMatchAt(parent.childCount)
  }
  match = match.matchFragment($to.parent.content, $to.index())
  return match && match.validEnd()
}

// Algorithm for 'placing' the elements of a slice into a gap:
//
// We consider the content of each node that is open to the left to be
// independently placeable. I.e. in <p("foo"), p("bar")>, when the
// paragraph on the left is open, "foo" can be placed (somewhere on
// the left side of the replacement gap) independently from p("bar").
//
// So placeSlice splits up a slice into a number of sub-slices,
// along with information on where they can be placed on the given
// left-side edge. It works by walking the open side of the slice,
// from the inside out, and trying to find a landing spot for each
// element, by simultaneously scanning over the gap side. When no
// place is found for an open node's content, it is left in that node.
//
// If the outer content can't be placed, a set of wrapper nodes is
// made up for it (by rooting it in the document node type using
// findWrapping), and the algorithm continues to iterate over those.
// This is guaranteed to find a fit, since both stacks now start with
// the same node type (doc).

function nodeLeft(content, depth) {
  for (let i = 1; i < depth; i++) content = content.firstChild.content
  return content.firstChild
}

function nodeRight(content, depth) {
  for (let i = 1; i < depth; i++) content = content.lastChild.content
  return content.lastChild
}

function placeSlice($from, slice) {
  let dFrom = $from.depth, unplaced = null
  let placed = [], parents = null

  for (let dSlice = slice.openLeft;; --dSlice) {
    let curType, curAttrs, curFragment
    if (dSlice >= 0) {
      if (dSlice > 0) { // Inside slice
        ;({type: curType, attrs: curAttrs, content: curFragment} = nodeLeft(slice.content, dSlice))
      } else if (dSlice == 0) { // Top of slice
        curFragment = slice.content
      }
      if (dSlice < slice.openLeft) curFragment = curFragment.cut(curFragment.firstChild.nodeSize)
    } else { // Outside slice
      curFragment = Fragment.empty
      let parent = parents[parents.length + dSlice - 1]
      curType = parent.type
      curAttrs = parent.attrs
    }
    if (unplaced)
      curFragment = curFragment.addToStart(unplaced)

    if (curFragment.size == 0 && dSlice <= 0) break

    // FIXME cut/remove marks when it helps find a placement
    let found = findPlacement(curFragment, $from, dFrom)
    if (found) {
      if (found.fragment.size > 0) placed[found.depth] = {
        content: found.fill.append(found.fragment),
        openRight: dSlice > 0 ? 0 : slice.openRight - dSlice,
        depth: found.depth
      }
      if (dSlice <= 0) break
      unplaced = null
      dFrom = Math.max(0, found.depth - 1)
    } else {
      if (dSlice == 0) {
        let top = $from.node(0)
        parents = top.contentMatchAt($from.index(0)).findWrapping(curFragment.firstChild.type, curFragment.firstChild.attrs)
        if (!parents) break
        let last = parents[parents.length - 1]
        if (last ? !last.type.contentExpr.matches(last.attrs, curFragment)
                 : !top.canReplace($from.indexAfter(0), $from.depth ? $from.index(0) : $from.indexAfter(0), curFragment)) break
        parents = [{type: top.type, attrs: top.attrs}].concat(parents)
        curType = parents[parents.length - 1].type
        curAttrs = parents[parents.length - 1].type
      }
      curFragment = curType.contentExpr.start(curAttrs).fillBefore(curFragment, true).append(curFragment)
      unplaced = curType.create(curAttrs, curFragment)
    }
  }

  return placed
}

function findPlacement(fragment, $from, start) {
  let hasMarks = false
  for (let i = 0; i < fragment.childCount; i++)
    if (fragment.child(i).marks.length) hasMarks = true
  for (let d = start; d >= 0; d--) {
    let startMatch = $from.node(d).contentMatchAt($from.indexAfter(d))
    let match = startMatch.fillBefore(fragment)
    if (match) return {depth: d, fill: match, fragment}
    if (hasMarks) {
      let stripped = matchStrippingMarks(startMatch, fragment)
      if (stripped) return {depth: d, fill: Fragment.empty, fragment: stripped}
    }
  }
}

function matchStrippingMarks(match, fragment) {
  let newNodes = []
  for (let i = 0; i < fragment.childCount; i++) {
    let node = fragment.child(i), stripped = node.mark(node.marks.filter(m => match.allowsMark(m.type)))
    match = match.matchNode(stripped)
    if (!match) return null
    newNodes.push(stripped)
  }
  return Fragment.from(newNodes)
}
<|endoftext|>


<commit_before>const CAMERA_MOVE = 5;

//Vars
var mouseDownX = 0,
mouseDownY = 0,
windowHalfX = window.innerWidth/2,
windowHalfY = window.innerHeight/2,
mouseX = 0,
mouseY = 0,
targetRotationX = 0,
targetRotationY = 0,
mouseDownRotationX = 0,
mouseDownRotationY = 0,
wheelData = 0,
noinertia = 0,
newrotationmatrix,
newrotation,
slowRotationX=0,
slowRotationY=0,
home,
maxDimension,
stats,
vslider,
time = new Date().getTime(),
timedelay = 3000,
refinestep = 10,
timeLastRefine = new Date().getTime(),
loaded = false,
offset=0,
minfps = 1,
fps=0,
framescounter=0,

//Renderer
WIDTH = window.innerWidth,
HEIGHT = window.innerHeight,

//Camera
VIEW_ANGLE = 60,
ASPECT = WIDTH / HEIGHT,
NEAR = 1,
FAR = 10000,

//important vars
webgl = isWebGLSupported(),
loader,
scene,
camera,
renderer,
mesh,
light;

init();
animate();

function isWebGLSupported() {
	try {
	 !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' );
	} catch( e ) {
		return 0;
	}
	return 1;
}

function init() {

//	if(webgl) {
	//	renderer = new THREE.WebGLRenderer({antialias: true});
	//
	//}
	//else {
		renderer = new THREE.CanvasRenderer({antialias: true});
	//}

	renderer.setSize(WIDTH, HEIGHT);
	renderer.setClearColorHex(0xEEEEEE, 1.0);
	renderer.clear();

	camera = new THREE.PerspectiveCamera(
			   VIEW_ANGLE,
			   ASPECT,
			   NEAR,
			   FAR );

	stats = new Stats();
	stats.domElement.style.position = 'absolute';
	stats.domElement.style.top = '0px';
	document.body.appendChild( stats.domElement );

	scene = new THREE.Scene();
	scene.add(camera);
	scene.add( new THREE.AmbientLight( 0x505050, 2000 ) );
	light = new THREE.PointLight( 0x707070, 1, 2000 );
	scene.add( light );

	/*var light2 = new THREE.PointLight( 0x707070, 1, 2000 );
	light2.position.x = -100;
	light2.position.z = 30;
	scene.add( light2 );	scene.add(p1); */
	loadMesh();

	document.body.appendChild( renderer.domElement );

	vslider = new Slider(document.getElementById("slider-vertical"), document.getElementById("slider-vertical-input"), "vertical");
	vslider.onchange = onSliderChange;

	renderer.domElement.addEventListener('mousedown', onMouseDown, false);
	renderer.domElement.addEventListener('DOMMouseScroll', onMouseScroll, false);
	renderer.domElement.addEventListener('mousewheel', onMouseScroll, false);
	renderer.domElement.addEventListener('touchstart', onTouchStart, false);
	renderer.domElement.addEventListener('touchmove', onTouchMove, false);
	renderer.domElement.addEventListener('touchend', onTouchEnd, false);
	renderer.domElement.addEventListener('contextmenu', onContextMenu, false);
}

 function onContextMenu(event) {

	event = event ? event : document.event;

	event.preventDefault();
	return false;
}

function loadMesh() {

	mesh = new THREE.Mesh(new THREE.Geometry(), new THREE.MeshLambertMaterial({color: 0xffffff, shading: THREE.FlatShading}));
	loadBaseMesh();
	scene.add(mesh);
}

function setParameters() {

		mesh.name = 'mesh';
		mesh.overdraw = true;
		mesh.doubleSided = true;
		mesh.geometry.computeBoundingBox();
		var box = mesh.geometry.boundingBox;
		if(box) {
			maxDimension = Math.max(box.x[1]-box.x[0], box.y[1]-box.y[0]);
			maxDimension = Math.ceil(Math.max(maxDimension, box.z[1]-box.z[0]));
			camera.position.z = light.position.z = maxDimension*2;
			camera.position.x = box.x[0] + (box.x[1]-box.x[0])/2;
			camera.position.y = box.y[0] + (box.y[1]-box.y[0])/2;

			vslider.setMinimum(-maxDimension);
			vslider.setMaximum(maxDimension*1.5);
			vslider.setValue(maxDimension*0.25);
		}

}

function animate() {

	requestAnimationFrame(animate);
	if(mesh) {
		rotateMesh();
		time = new Date().getTime();

		if((time - timeLastRefine) > timedelay) {
			var refine = true;
			if( framescounter < minfps*timedelay/1000 ){
				refine = false;
			}
			if(refine && !loaded) {
				refineMesh();
				//setParameters();
			}
			timeLastRefine = time;
			framescounter = 0;
		}

		framescounter++;
	}
	renderer.render(scene, camera);
	stats.update();
}

function rotateMesh() {

	newrotationmatrix = new THREE.Matrix4();
	newrotation = new THREE.Vector3((targetRotationY-slowRotationY)*0.05,(targetRotationX-slowRotationX)*0.05,0);
	newrotationmatrix.setRotationFromEuler(newrotation);
	newrotationmatrix.multiplySelf(mesh.matrix);
	mesh.rotation.setRotationFromMatrix(newrotationmatrix);

	if(noinertia)
		targetRotationX = targetRotationY = 0;
	else {
		slowRotationX += (targetRotationX - slowRotationX)*0.02;
		slowRotationY += (targetRotationY - slowRotationY)*0.02;
	}

	if(home) {
		mesh.rotation.setRotationFromMatrix(new THREE.Matrix4());
		home = 0;
	}
}
function onMouseDown(event) {

	event = event ? event : document.event;

	event.preventDefault();

	mesh.doubleSided = false;
	mesh.material.wireframe = true;

	document.addEventListener('mouseup', onMouseUp, false);
	document.addEventListener('mouseout', onMouseUp, false);
	document.addEventListener('mousemove', onMouseMove, false);

	if(event.pageX || event.pageY) {
		mouseDownX = event.pageX;
		mouseDownY = event.pageY;
	}
	else if(event.clientX || event.clientY) {
		mouseDownX = event.clientX + document.body.scrollLeft;
		mouseDownY = event.clientY + document.body.scrollTop;
	}

	mouseDownY -= windowHalfY;
	mouseDownX -= windowHalfX;

	if(event.which == 1) {
		mouseDownRotationX = targetRotationX;
		mouseDownRotationY = targetRotationY;
	}
}

function onMouseMove(event) {

	event = event ? event : document.event;

	event.preventDefault();

	if(event.pageX || event.pageY) {
		mouseX = event.pageX;
		mouseY = event.pageY;
	}
	else if(event.clientX || event.clientY) {
		mouseX = event.clientX + document.body.scrollLeft;
		mouseY = event.clientY + document.body.scrollTop;
	}

	mouseX -= windowHalfX;
	mouseY -= windowHalfY;
	if(event.which == 1) {
		if(noinertia) {
			targetRotationX = (mouseX - mouseDownX)*0.2;
			targetRotationY = (mouseY - mouseDownY)*0.2;
			mouseDownX = mouseX;
			mouseDownY = mouseY;
		}
		else {
			targetRotationX = mouseDownRotationX + (mouseX - mouseDownX)*0.02;
			targetRotationY = mouseDownRotationY + (mouseY - mouseDownY)*0.02;
		}
	}
	else if(event.which == 3) {
		camera.position.x -= (mouseX - mouseDownX)*0.2;
		camera.position.y += (mouseY - mouseDownY)*0.2;
		mouseDownX = mouseX;
		mouseDownY = mouseY;
	}
}

function onMouseUp(event) {

	event = event ? event : document.event;

	event.preventDefault();
	mesh.doubleSided = true;
	mesh.material.wireframe = false;

	document.removeEventListener('mouseup', onMouseUp, false);
	document.removeEventListener('mouseout', onMouseUp, false);
	document.removeEventListener('mousemove', onMouseMove, false);

}

function onMouseScroll(event) {

	event = event ? event : document.event;
	event.preventDefault();

	wheelData = event.detail ? event.detail * -1 : event.wheelDelta / 40;
	vslider.setValue(vslider.getValue() + (wheelData > 0 ? 0.05 : -0.05) * (vslider.getMaximum() - vslider.getMinimum()));
}

function onSliderChange() {

	if(this.getOrientation() == "vertical")
		camera.position.z = maxDimension*2 - this.getValue();
	else
		camera.position.x = -this.getValue();
}

function onTouchStart(event) {

	event = event ? event: document.event;

	event.preventDefault();
	if(event.touches.length == 1) {
		mouseDownY = event.touches[0].pageY - windowHalfY;
		mouseDownX = event.touches[0].pageX - windowHalfX;
		mouseDownRotationX = targetRotationX;
		mouseDownRotationY = targetRotationY;
	}
}

function onTouchMove(event) {

	event = event ? event: document.event;

	event.preventDefault();
	if(event.touches.length == 1) {
		mouseX = event.touches[0].pageX - windowHalfX;
		mouseY = event.touches[0].pageY - windowHalfY;
		targetRotationX = mouseDownRotationX + (mouseX - mouseDownX)*0.05;
		targetRotationY = mouseDownRotationY + (mouseY - mouseDownY)*0.05;
	}

}

function onTouchEnd(event) {

	event = event ? event: document.event;

	event.preventDefault();
	mesh.doubleSided = true;
	mesh.material.wireframe = false;
}

function Inertia() {

	if(noinertia) {
		noinertia = 0;
		slowRotationX = slowRotationY = 0;
	}
	else {
		noinertia = 1;
		targetRotationX = targetRotationY = 0;
		slowRotationX = slowRotationY = 0;
	}

	mouseDownRotationX = mouseDownRotationY = mouseDownX = mouseDownY = mouseX = mouseY = 0;
}

function Home() {

	targetRotationX = targetRotationY = mouseDownRotationX = mouseDownRotationY = mouseDownX = mouseDownY = mouseX = mouseY = slowRotationX = slowRotationY = 0;
	mesh.rotation.setRotationFromMatrix(new THREE.Matrix4());
	vslider.setValue(maxDimension*0.25);
	var box = mesh.geometry.boundingBox;
	camera.position.x = box.x[0] + (box.x[1]-box.x[0])/2;
	camera.position.y = box.y[0] + (box.y[1]-box.y[0])/2;
	home = 1;

}

function changeMesh() {
	scene.remove(mesh);
	if(mesh.geometry.faces.length == 6)
		loadMesh();
	else {
		mesh = new THREE.Mesh(new THREE.CubeGeometry(20,20,20), new THREE.MeshNormalMaterial());
		setParameters();
	}
}

function moveCamera(direction) {

	switch(direction) {

		case "up": camera.position.y -= CAMERA_MOVE; break;
		case "down": camera.position.y += CAMERA_MOVE; break;
		case "left": camera.position.x += CAMERA_MOVE; break;
		case "right": camera.position.x -= CAMERA_MOVE; break;
		default: break;
	}
}
<commit_msg>Version from 6.05<commit_after>
//Vars
var mouseDownX = 0,
mouseDownY = 0,
windowHalfX = window.innerWidth/2,
windowHalfY = window.innerHeight/2,
mouseX = 0,
mouseY = 0,
targetRotationX = 0,
targetRotationY = 0,
mouseDownRotationX = 0,
mouseDownRotationY = 0,
wheelData = 0,
noinertia = 0,
newrotationmatrix,
newrotation,
slowRotationX=0,
slowRotationY=0,
home,
maxDimension,
stats,
vslider,
time = new Date().getTime(),
timedelay = 3000,
refinestep = 10,
timeLastRefine = new Date().getTime(),
loaded = false,
offset=0,
minfps = 1,
fps=0,
framescounter=0,

//Renderer
WIDTH = window.innerWidth,
HEIGHT = window.innerHeight,

//Camera
VIEW_ANGLE = 60,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.01,
FAR = 10000,

//important vars
webgl = isWebGLSupported(),
loader,
scene,
camera,
renderer,
mesh,
light;

init();
animate();

function isWebGLSupported() {
	try {
	 !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' );
	} catch( e ) {
		return 0;
	}
	return 1;
}

function init() {

//	if(webgl) {
	//	renderer = new THREE.WebGLRenderer({antialias: true});
	//
	//}
	//else {
		renderer = new THREE.CanvasRenderer({antialias: true});
	//}

	renderer.setSize(WIDTH, HEIGHT);
	renderer.setClearColorHex(0xEEEEEE, 1.0);
	renderer.clear();

	camera = new THREE.PerspectiveCamera(
			   VIEW_ANGLE,
			   ASPECT,
			   NEAR,
			   FAR );

	stats = new Stats();
	stats.domElement.style.position = 'absolute';
	stats.domElement.style.top = '0px';
	document.body.appendChild( stats.domElement );

	scene = new THREE.Scene();
	scene.add(camera);
	scene.add( new THREE.AmbientLight( 0x505050) );
	light = new THREE.PointLight( 0x707070, 1, 1000 );
	scene.add( light );

	/*var light2 = new THREE.PointLight( 0x707070, 1, 2000 );
	light2.position.x = -100;
	light2.position.z = 30;
	scene.add( light2 );	scene.add(p1); */
	loadMesh();

	document.body.appendChild( renderer.domElement );

	vslider = new Slider(document.getElementById("slider-vertical"), document.getElementById("slider-vertical-input"), "vertical");
	vslider.onchange = onSliderChange;

	renderer.domElement.addEventListener('mousedown', onMouseDown, false);
	renderer.domElement.addEventListener('DOMMouseScroll', onMouseScroll, false);
	renderer.domElement.addEventListener('mousewheel', onMouseScroll, false);
	renderer.domElement.addEventListener('touchstart', onTouchStart, false);
	renderer.domElement.addEventListener('touchmove', onTouchMove, false);
	renderer.domElement.addEventListener('touchend', onTouchEnd, false);
	renderer.domElement.addEventListener('contextmenu', onContextMenu, false);
}

 function onContextMenu(event) {

	event = event ? event : document.event;

	event.preventDefault();
	return false;
}

function loadMesh() {

	mesh = new THREE.Mesh(new THREE.Geometry(), new THREE.MeshLambertMaterial({color: 0xffffff, shading: THREE.FlatShading}));
	loadBaseMesh();
	scene.add(mesh);
}

function setParameters() {

		mesh.name = 'mesh';
		mesh.overdraw = true;
		mesh.doubleSided = true;
		mesh.geometry.computeBoundingBox();
		var box = mesh.geometry.boundingBox;
		if(box) {
			maxDimension = Math.max(box.x[1]-box.x[0], box.y[1]-box.y[0]);
			maxDimension = Math.ceil(Math.max(maxDimension, box.z[1]-box.z[0]));
			camera.position.z = maxDimension*2;
			light.position.z = maxDimension*2;
			centerCamera();

			vslider.setMinimum(-maxDimension);
			vslider.setMaximum(maxDimension*1.5);
			vslider.setValue(maxDimension*0.25);
			//alert(maxDimension);
		}
}

function animate() {

	requestAnimationFrame(animate);
	if(mesh) {
		rotateMesh();
		time = new Date().getTime();

		if((time - timeLastRefine) > timedelay) {
			var refine = true;
			if( framescounter < minfps*timedelay/1000 ){
				refine = false;
			}
			if(refine && !loaded) {
				refineMesh();
				setParameters();
			}
			timeLastRefine = time;
			framescounter = 0;
		}

		framescounter++;
	}
	renderer.render(scene, camera);
	stats.update();
}

function rotateMesh() {

	newrotationmatrix = new THREE.Matrix4();
	newrotation = new THREE.Vector3((targetRotationY-slowRotationY)*0.05,(targetRotationX-slowRotationX)*0.05,0);
	newrotationmatrix.setRotationFromEuler(newrotation);
	newrotationmatrix.multiplySelf(mesh.matrix);
	mesh.rotation.setRotationFromMatrix(newrotationmatrix);

	if(noinertia)
		targetRotationX = targetRotationY = 0;
	else {
		slowRotationX += (targetRotationX - slowRotationX)*0.02;
		slowRotationY += (targetRotationY - slowRotationY)*0.02;
	}

	if(home) {
		mesh.rotation.setRotationFromMatrix(new THREE.Matrix4());
		home = 0;
	}
}
function onMouseDown(event) {

	event = event ? event : document.event;

	event.preventDefault();

	mesh.doubleSided = false;
	mesh.material.wireframe = true;

	document.addEventListener('mouseup', onMouseUp, false);
	document.addEventListener('mouseout', onMouseUp, false);
	document.addEventListener('mousemove', onMouseMove, false);

	if(event.pageX || event.pageY) {
		mouseDownX = event.pageX;
		mouseDownY = event.pageY;
	}
	else if(event.clientX || event.clientY) {
		mouseDownX = event.clientX + document.body.scrollLeft;
		mouseDownY = event.clientY + document.body.scrollTop;
	}

	mouseDownY -= windowHalfY;
	mouseDownX -= windowHalfX;

	if(event.which == 1) {
		mouseDownRotationX = targetRotationX;
		mouseDownRotationY = targetRotationY;
	}
}

function onMouseMove(event) {

	event = event ? event : document.event;

	event.preventDefault();

	if(event.pageX || event.pageY) {
		mouseX = event.pageX;
		mouseY = event.pageY;
	}
	else if(event.clientX || event.clientY) {
		mouseX = event.clientX + document.body.scrollLeft;
		mouseY = event.clientY + document.body.scrollTop;
	}

	mouseX -= windowHalfX;
	mouseY -= windowHalfY;
	if(event.which == 1) {
		if(noinertia) {
			targetRotationX = (mouseX - mouseDownX)*0.2;
			targetRotationY = (mouseY - mouseDownY)*0.2;
			mouseDownX = mouseX;
			mouseDownY = mouseY;
		}
		else {
			targetRotationX = mouseDownRotationX + (mouseX - mouseDownX)*0.02;
			targetRotationY = mouseDownRotationY + (mouseY - mouseDownY)*0.02;
		}
	}
	else if(event.which == 3) {
		camera.position.x -= (mouseX - mouseDownX)*maxDimension/20;
		camera.position.y += (mouseY - mouseDownY)*maxDimension/20;
		mouseDownX = mouseX;
		mouseDownY = mouseY;
	}
}

function onMouseUp(event) {

	event = event ? event : document.event;

	event.preventDefault();
	mesh.doubleSided = true;
	mesh.material.wireframe = false;

	document.removeEventListener('mouseup', onMouseUp, false);
	document.removeEventListener('mouseout', onMouseUp, false);
	document.removeEventListener('mousemove', onMouseMove, false);

}

function onMouseScroll(event) {

	event = event ? event : document.event;
	event.preventDefault();

	wheelData = event.detail ? event.detail * -1 : event.wheelDelta / 40;
	vslider.setValue(vslider.getValue() + (wheelData > 0 ? 0.05 : -0.05) * (vslider.getMaximum() - vslider.getMinimum()));
}

function onSliderChange() {

	camera.position.z = maxDimension*2 - this.getValue();

}

function onTouchStart(event) {

	event = event ? event: document.event;

	event.preventDefault();
	if(event.touches.length == 1) {
		mouseDownY = event.touches[0].pageY - windowHalfY;
		mouseDownX = event.touches[0].pageX - windowHalfX;
		mouseDownRotationX = targetRotationX;
		mouseDownRotationY = targetRotationY;
	}
}

function onTouchMove(event) {

	event = event ? event: document.event;

	event.preventDefault();
	if(event.touches.length == 1) {
		mouseX = event.touches[0].pageX - windowHalfX;
		mouseY = event.touches[0].pageY - windowHalfY;
		targetRotationX = mouseDownRotationX + (mouseX - mouseDownX)*0.05;
		targetRotationY = mouseDownRotationY + (mouseY - mouseDownY)*0.05;
	}

}

function onTouchEnd(event) {

	event = event ? event: document.event;

	event.preventDefault();
	mesh.doubleSided = true;
	mesh.material.wireframe = false;
}

function Inertia() {

	if(noinertia) {
		noinertia = 0;
		slowRotationX = slowRotationY = 0;
	}
	else {
		noinertia = 1;
		targetRotationX = targetRotationY = 0;
		slowRotationX = slowRotationY = 0;
	}

	mouseDownRotationX = mouseDownRotationY = mouseDownX = mouseDownY = mouseX = mouseY = 0;
}

function Home() {

	targetRotationX = targetRotationY = mouseDownRotationX = mouseDownRotationY = mouseDownX = mouseDownY = mouseX = mouseY = slowRotationX = slowRotationY = 0;
	mesh.rotation.setRotationFromMatrix(new THREE.Matrix4());
	vslider.setValue(maxDimension*0.25);
	centerCamera();
	home = 1;

}

function changeMesh() {
	scene.remove(mesh);
	if(mesh.geometry.faces.length == 6)
		loadMesh();
	else {
		mesh = new THREE.Mesh(new THREE.CubeGeometry(20,20,20), new THREE.MeshNormalMaterial());
		setParameters();
	}
}

function moveCamera(direction) {

	switch(direction) {

		case "up": camera.position.y -= maxDimension/10; break;
		case "down": camera.position.y += maxDimension/10; break;
		case "left": camera.position.x += maxDimension/10; break;
		case "right": camera.position.x -= maxDimension/10; break;
		default: break;
	}
}

function centerCamera() {

	var box = mesh.geometry.boundingBox;
	camera.position.x = box.x[0] + (box.x[1]-box.x[0])/2;
	camera.position.y = box.y[0] + (box.y[1]-box.y[0])/2;
}<|endoftext|>