<commit_before>'use strict'

const Model = require('trails-model')

/**
 * @module Project
 * @description Workspace group by users
 */
module.exports = class Project extends Model {

  static config () {
  }

  static schema () {
    return {
      name: {
        type: 'string'
      },
      status: {
        type: 'string'
      },
      user: {
        model: 'User'
      }
    }
  }
}
<commit_msg>Add position and zoom in project<commit_after>'use strict'

const Model = require('trails-model')

/**
 * @module Project
 * @description Workspace group by users
 */
module.exports = class Project extends Model {

  static config () {
  }

  static schema () {
    return {
      name: {
        type: 'string'
      },
      status: {
        type: 'string'
      },
      user: {
        model: 'User'
      },
      latitude: {
        type: 'float'
      },
      longitude: {
        type: 'float'
      },
      zoom: {
        type: 'integer'
      }
    }
  }
}
<|endoftext|>


<commit_before>iD.modes.DrawLine = function(wayId, direction) {
    var mode = {
        button: 'line',
        id: 'draw-line'
    };

    var behavior;

    mode.enter = function() {
        var way = mode.history.graph().entity(wayId),
            index = (direction === 'forward') ? way.nodes.length - 1 : 0,
            headId = (direction === 'forward') ? way.nodes[index - 1] : way.nodes[index + 1],
            tailId = (direction === 'forward') ? way.first() : way.last();

        function addHead() {
            behavior.finish();
        }

        function addTail(node) {
            // connect the way in a loop
            if (way.nodes.length > 2) {
                behavior.addNode(node, 'added to a line', iD.modes.Select(way, true))
            } else {
                behavior.cancel();
            }
        }

        function addNode(node) {
            behavior.addNode(node, 'added to a line');
        }

        function addWay(way, loc, index) {
            behavior.addWay(way, loc, index, 'added to a line');
        }

        function add(loc) {
            behavior.add(loc, 'added to a line');
        }

        behavior = iD.behavior.DrawWay(wayId, headId, tailId, index, mode)
            .on('addHead', addHead)
            .on('addTail', addTail)
            .on('addNode', addNode)
            .on('addWay', addWay)
            .on('add', add);

        mode.map.surface.call(behavior);
        mode.map.tail('Click to add more points to the line. ' +
                      'Click on other lines to connect to them, and double-click to ' +
                      'end the line.', true);
    };

    mode.exit = function() {
        mode.map.surface.call(behavior.off);
    };

    return mode;
};
<commit_msg>Allow for continuing line drawing, also fixes #507<commit_after>iD.modes.DrawLine = function(wayId, direction) {
    var mode = {
        button: 'line',
        id: 'draw-line'
    };

    var behavior;

    mode.enter = function() {
        var way = mode.history.graph().entity(wayId),
            index = (direction === 'forward') ? way.nodes.length - 1 : 0,
            headId = (direction === 'forward') ? way.nodes[index - 1] : way.nodes[index + 1],
            tailId = (direction === 'forward') ? way.first() : way.last();

        function addHead() {
            behavior.finish();
        }

        function addTail(node) {
            // connect the way in a loop
            if (way.nodes.length > 2) {
                behavior.addNode(node, 'added to a line');
            } else {
                behavior.cancel();
            }
        }

        function addNode(node) {
            behavior.addNode(node, 'added to a line');
        }

        function addWay(way, loc, index) {
            behavior.addWay(way, loc, index, 'added to a line');
        }

        function add(loc) {
            behavior.add(loc, 'added to a line');
        }

        behavior = iD.behavior.DrawWay(wayId, headId, tailId, index, mode)
            .on('addHead', addHead)
            .on('addTail', addTail)
            .on('addNode', addNode)
            .on('addWay', addWay)
            .on('add', add);

        mode.map.surface.call(behavior);
        mode.map.tail('Click to add more points to the line. ' +
                      'Click on other lines to connect to them, and double-click to ' +
                      'end the line.', true);
    };

    mode.exit = function() {
        mode.map.surface.call(behavior.off);
    };

    return mode;
};
<|endoftext|>


<commit_before>var BUILD_INFO_PATH = '../public/buildinfo/buildinfo.txt';
var PACKAGES_PATH = '../.meteor/packages';
var BUILD_PATH = '../../build';
var LineByLineReader = require('line-by-line'),
    mkdirp = require('mkdirp'),
	fs = require('fs'),
    lr = new LineByLineReader(BUILD_INFO_PATH);

var firstline = "";

if (process.env.TRAVIS_BUILD_NUMBER)  {

	var transformVersion = function (firstline) {
	 var versions = firstline.split(".");

	 return versions[0] + '.' + versions[1] + '.' + process.env.TRAVIS_BUILD_NUMBER + '\n';
	};

	lr.on('error', function (err) {
    	// 'err' contains error object
	});

	lr.on('line', function (line) {
  		if (firstline == "")
    		firstline = line;

	});

	lr.on('end', function () {

	     var packages = fs.readFileSync(PACKAGES_PATH);
	     var verinfo = transformVersion(firstline);
	     var content = verinfo + packages;
	     mkdirp.sync(BUILD_PATH);
	     fs.writeFileSync(BUILD_PATH + "/version.txt", verinfo);
	     fs.writeFileSync(BUILD_INFO_PATH, content);
             console.log('Version is ' + verinfo);

	});

}
<commit_msg>Fix indentations of setbuildinfo.js<commit_after>var BUILD_INFO_PATH = '../public/buildinfo/buildinfo.txt';
var PACKAGES_PATH = '../.meteor/packages';
var BUILD_PATH = '../../build';
var LineByLineReader = require('line-by-line'),
var mkdirp = require('mkdirp');
var fs = require('fs');
var lr = new LineByLineReader(BUILD_INFO_PATH);

var firstline = "";

if (process.env.TRAVIS_BUILD_NUMBER)  {
	var transformVersion = function (firstline) {
		var versions = firstline.split(".");

		return versions[0] + '.' + versions[1] + '.' + process.env.TRAVIS_BUILD_NUMBER + '\n';
	};

	lr.on('error', function (err) {
		// 'err' contains error object
	});

	lr.on('line', function (line) {
		if (firstline == "") {
			firstline = line;
		}
	});

	lr.on('end', function () {
		var packages = fs.readFileSync(PACKAGES_PATH);
		var verinfo = transformVersion(firstline);
		var content = verinfo + packages;
		mkdirp.sync(BUILD_PATH);
		fs.writeFileSync(BUILD_PATH + "/version.txt", verinfo);
		fs.writeFileSync(BUILD_INFO_PATH, content);
		console.log('Version is ' + verinfo);
	});
}
<|endoftext|>


<commit_before>const React = require('react');
const data = require('./grid-data');

const Grid = React.createClass({
    getInitialState() {
        let filter = '';
        let columns = this.createColumns(this.props.data);
        return {columns, filter};
    },

    createColumns(data) {
        if (!data || data.length === 0) {
            return [];
        }
        let columns = [];
        let obj = data[0];
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                columns.push({key});
            }
        }
        return columns;
    },

    createDataView() {
        let data = this.props.data;
        if (!data || data.length === 0) {
            return [];
        }
        let filter = this.state.filter;
        if (!filter) {
            return data;
        }
        let filters = filter.split(' ');
        return data.filter(obj => {
            for (let i = 0; i < filters.length; i++) {
                let filter = filters[i];
                let found = false;
                for (let key in obj) {
                    if (obj.hasOwnProperty(key)) {
                        let value = String(obj[key]).toLowerCase();
                        if (value.indexOf(filter) >= 0) {
                            found = true;
                            break;
                        }
                    }
                }
                if (!found) {
                    return false;
                }
            }
            return true;
        });
    },

    onFilterChange(filter) {
        filter = filter.toLowerCase();
        filter = filter.trim();
        this.setState({filter});
    },

    render() {
        let columns = this.state.columns;
        let dataView = this.createDataView();
        return (

                <Filter onChange={this.onFilterChange}/>

        )
    }
});

const Filter = React.createClass({
    render() {
        return (

                <input type="text" className="form-control" placeholder="Filter..." onChange={this.handleInput}/>

        )
    },

    handleInput(ev) {
        let term = ev.target.value;
        this.props.onChange(term);
    }
});

const Table = React.createClass({
    render() {
        let dataView = this.props.dataView;
        if (!dataView || dataView.length === 0) {
            return
No data
;
        }
        return (

                {this.renderHead(this.props.columns)}
                {this.renderBody(this.props.columns, this.props.dataView)}

        )
    },

    renderHead(columns) {
        return (

                {columns.map((col, i) => (
                    <th key={`head-${i}`}>{col.key}
                ))}

        )
    },

    renderBody(columns, dataView) {
        return (

            {dataView.map((row, i) =>
                this.renderRow(row, i, columns))}

        )
    },

    renderRow(row, i, columns) {
        return (
            <tr key={`row-${i}`}>
                {columns.map((def, j) => (
                    <td key={`col-${j}`}>
                        {row[def.key]}

                ))}

        )
    }
});

module.exports = {
    name: 'Grid',
    fn: () => <Grid data={data}/>
};<commit_msg>Focus filter input on mount<commit_after>const React = require('react');
const data = require('./grid-data');

const Grid = React.createClass({
    getInitialState() {
        let filter = '';
        let columns = this.createColumns(this.props.data);
        return {columns, filter};
    },

    createColumns(data) {
        if (!data || data.length === 0) {
            return [];
        }
        let columns = [];
        let obj = data[0];
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                columns.push({key});
            }
        }
        return columns;
    },

    createDataView() {
        let data = this.props.data;
        if (!data || data.length === 0) {
            return [];
        }
        let filter = this.state.filter;
        if (!filter) {
            return data;
        }
        let filters = filter.split(' ');
        return data.filter(obj => {
            for (let i = 0; i < filters.length; i++) {
                let filter = filters[i];
                let found = false;
                for (let key in obj) {
                    if (obj.hasOwnProperty(key)) {
                        let value = String(obj[key]).toLowerCase();
                        if (value.indexOf(filter) >= 0) {
                            found = true;
                            break;
                        }
                    }
                }
                if (!found) {
                    return false;
                }
            }
            return true;
        });
    },

    onFilterChange(filter) {
        filter = filter.toLowerCase();
        filter = filter.trim();
        this.setState({filter});
    },

    render() {
        let columns = this.state.columns;
        let dataView = this.createDataView();
        return (

                <Filter onChange={this.onFilterChange}/>

        )
    }
});

const Filter = React.createClass({
    render() {
        return (

                <input ref="input" type="text" className="form-control" placeholder="Filter..." onChange={this.handleInput}/>

        )
    },

    handleInput(ev) {
        let term = ev.target.value;
        this.props.onChange(term);
    },

    componentDidMount() {
        React.findDOMNode(this.refs.input).focus();
    }
});

const Table = React.createClass({
    render() {
        let dataView = this.props.dataView;
        if (!dataView || dataView.length === 0) {
            return
No data
;
        }
        return (

                {this.renderHead(this.props.columns)}
                {this.renderBody(this.props.columns, this.props.dataView)}

        )
    },

    renderHead(columns) {
        return (

                {columns.map((col, i) => (
                    <th key={`head-${i}`}>{col.key}
                ))}

        )
    },

    renderBody(columns, dataView) {
        return (

            {dataView.map((row, i) =>
                this.renderRow(row, i, columns))}

        )
    },

    renderRow(row, i, columns) {
        return (
            <tr key={`row-${i}`}>
                {columns.map((def, j) => (
                    <td key={`col-${j}`}>
                        {row[def.key]}

                ))}

        )
    }
});

module.exports = {
    name: 'Grid',
    fn: () => <Grid data={data}/>
};<|endoftext|>


<commit_before>// (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP
var Grommet = {
  /**
   * Components.  Note that Collapsible and DateTimeDrop are private
   * and shouldn't be exposed here.
   */
  Accordion: require('./components/Accordion'),
  AccordionPanel: require('./components/AccordionPanel'),
  Anchor: require('./components/Anchor'),
  Animate: require('./components/Animate'),
  App: require('./components/App'),
  Article: require('./components/Article'),
  Box: require('./components/Box'),
  Button: require('./components/Button'),
  Card: require('./components/Card'),
  Carousel: require('./components/Carousel'),
  chart: {
    Area: require('./components/chart/Area'),
    Axis: require('./components/chart/Axis'),
    Bar: require('./components/chart/Bar'),
    Base: require('./components/chart/Base'),
    Chart: require('./components/chart/Chart'),
    Grid: require('./components/chart/Grid'),
    HotSpots: require('./components/chart/HotSpots'),
    Layers: require('./components/chart/Layers'),
    Line: require('./components/chart/Line'),
    Marker: require('./components/chart/Marker'),
    MarkerLabel: require('./components/chart/MarkerLabel'),
    Range: require('./components/chart/Range')
  },
  CheckBox: require('./components/CheckBox'),
  Columns: require('./components/Columns'),
  DateTime: require('./components/DateTime'),
  Distribution: require('./components/Distribution'),
  Footer: require('./components/Footer'),
  Form: require('./components/Form'),
  FormattedMessage: require('./components/FormattedMessage'),
  FormField: require('./components/FormField'),
  FormFields: require('./components/FormFields'),
  Grommet: require('./components/Grommet'),
  Header: require('./components/Header'),
  Heading: require('./components/Heading'),
  Headline: require('./components/Headline'),
  Hero: require('./components/Hero'),
  Image: require('./components/Image'),
  Label: require('./components/Label'),
  Layer: require('./components/Layer'),
  Legend: require('./components/Legend'),
  List: require('./components/List'),
  ListItem: require('./components/ListItem'),
  LoginForm: require('./components/LoginForm'),
  Map: require('./components/Map'),
  Markdown: require('./components/Markdown'),
  Menu: require('./components/Menu'),
  Meter: require('./components/Meter'),
  Notification: require('./components/Notification'),
  NumberInput: require('./components/NumberInput'),
  Object: require('./components/Object'),
  Paragraph: require('./components/Paragraph'),
  Quote: require('./components/Quote'),
  RadioButton: require('./components/RadioButton'),
  Search: require('./components/Search'),
  SearchInput: require('./components/SearchInput'),
  Section: require('./components/Section'),
  Select: require('./components/Select'),
  Sidebar: require('./components/Sidebar'),
  SkipLinkAnchor: require('./components/SkipLinkAnchor'),
  SkipLinks: require('./components/SkipLinks'),
  SocialShare: require('./components/SocialShare'),
  Split: require('./components/Split'),
  SunBurst: require('./components/SunBurst'),
  SVGIcon: require('./components/SVGIcon'),
  Tab: require('./components/Tab'),
  Table: require('./components/Table'),
  TableHeader: require('./components/TableHeader'),
  TableRow: require('./components/TableRow'),
  Tabs: require('./components/Tabs'),
  TBD: require('./components/TBD'),
  TextInput: require('./components/TextInput'),
  Tile: require('./components/Tile'),
  Tiles: require('./components/Tiles'),
  Timestamp: require('./components/Timestamp'),
  Tip: require('./components/Tip'),
  Title: require('./components/Title'),
  Toast: require('./components/Toast'),
  Topology: require('./components/Topology'),
  Value: require('./components/Value'),
  Video: require('./components/Video'),
  WorldMap: require('./components/WorldMap'),
  Icons: {
    Grommet: require('./components/icons/Grommet'),
    Pulse: require('./components/icons/Pulse'),
    Spinning: require('./components/icons/Spinning'),
    Status: require('./components/icons/Status'),
    Base: require('./index-icons')
  },
  // Utils
  Cookies: require('./utils/Cookies'),
  DOM: require('./utils/DOM'),
  KeyboardAccelerators: require('./utils/KeyboardAccelerators'),
  Locale: require('./utils/Locale'),
  Rest: require('./utils/Rest'),
  Validator: require('./utils/Validator')
};

module.exports = Grommet;
<commit_msg>Fixed problem with missing index-icons file.<commit_after>// (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP
var Grommet = {
  /**
   * Components.  Note that Collapsible and DateTimeDrop are private
   * and shouldn't be exposed here.
   */
  Accordion: require('./components/Accordion'),
  AccordionPanel: require('./components/AccordionPanel'),
  Anchor: require('./components/Anchor'),
  Animate: require('./components/Animate'),
  App: require('./components/App'),
  Article: require('./components/Article'),
  Box: require('./components/Box'),
  Button: require('./components/Button'),
  Card: require('./components/Card'),
  Carousel: require('./components/Carousel'),
  chart: {
    Area: require('./components/chart/Area'),
    Axis: require('./components/chart/Axis'),
    Bar: require('./components/chart/Bar'),
    Base: require('./components/chart/Base'),
    Chart: require('./components/chart/Chart'),
    Grid: require('./components/chart/Grid'),
    HotSpots: require('./components/chart/HotSpots'),
    Layers: require('./components/chart/Layers'),
    Line: require('./components/chart/Line'),
    Marker: require('./components/chart/Marker'),
    MarkerLabel: require('./components/chart/MarkerLabel'),
    Range: require('./components/chart/Range')
  },
  CheckBox: require('./components/CheckBox'),
  Columns: require('./components/Columns'),
  DateTime: require('./components/DateTime'),
  Distribution: require('./components/Distribution'),
  Footer: require('./components/Footer'),
  Form: require('./components/Form'),
  FormattedMessage: require('./components/FormattedMessage'),
  FormField: require('./components/FormField'),
  FormFields: require('./components/FormFields'),
  Grommet: require('./components/Grommet'),
  Header: require('./components/Header'),
  Heading: require('./components/Heading'),
  Headline: require('./components/Headline'),
  Hero: require('./components/Hero'),
  Image: require('./components/Image'),
  Label: require('./components/Label'),
  Layer: require('./components/Layer'),
  Legend: require('./components/Legend'),
  List: require('./components/List'),
  ListItem: require('./components/ListItem'),
  LoginForm: require('./components/LoginForm'),
  Map: require('./components/Map'),
  Markdown: require('./components/Markdown'),
  Menu: require('./components/Menu'),
  Meter: require('./components/Meter'),
  Notification: require('./components/Notification'),
  NumberInput: require('./components/NumberInput'),
  Object: require('./components/Object'),
  Paragraph: require('./components/Paragraph'),
  Quote: require('./components/Quote'),
  RadioButton: require('./components/RadioButton'),
  Search: require('./components/Search'),
  SearchInput: require('./components/SearchInput'),
  Section: require('./components/Section'),
  Select: require('./components/Select'),
  Sidebar: require('./components/Sidebar'),
  SkipLinkAnchor: require('./components/SkipLinkAnchor'),
  SkipLinks: require('./components/SkipLinks'),
  SocialShare: require('./components/SocialShare'),
  Split: require('./components/Split'),
  SunBurst: require('./components/SunBurst'),
  SVGIcon: require('./components/SVGIcon'),
  Tab: require('./components/Tab'),
  Table: require('./components/Table'),
  TableHeader: require('./components/TableHeader'),
  TableRow: require('./components/TableRow'),
  Tabs: require('./components/Tabs'),
  TBD: require('./components/TBD'),
  TextInput: require('./components/TextInput'),
  Tile: require('./components/Tile'),
  Tiles: require('./components/Tiles'),
  Timestamp: require('./components/Timestamp'),
  Tip: require('./components/Tip'),
  Title: require('./components/Title'),
  Toast: require('./components/Toast'),
  Topology: require('./components/Topology'),
  Value: require('./components/Value'),
  Video: require('./components/Video'),
  WorldMap: require('./components/WorldMap'),
  Icons: {
    Grommet: require('./components/icons/Grommet'),
    Pulse: require('./components/icons/Pulse'),
    Spinning: require('./components/icons/Spinning'),
    Status: require('./components/icons/Status'),
    Base: require('./components/icons/base')
  },
  // Utils
  Cookies: require('./utils/Cookies'),
  DOM: require('./utils/DOM'),
  KeyboardAccelerators: require('./utils/KeyboardAccelerators'),
  Locale: require('./utils/Locale'),
  Rest: require('./utils/Rest'),
  Validator: require('./utils/Validator')
};

module.exports = Grommet;
<|endoftext|>


<commit_before>/**
 * --------------------------------------------------------------------
 * jQuery collapsible plugin
 * Author: Scott Jehl, scott@filamentgroup.com
 * Copyright (c) 2009 Filament Group
 * licensed under MIT (filamentgroup.com/examples/mit-license.txt)
 * --------------------------------------------------------------------
 */
$.fn.collapsible = function(){
	return $(this).each(function(){

		//define
		var collapsibleHeading = $(this);
		var collapsibleContent = collapsibleHeading.next();

		//modify markup & attributes
		collapsibleHeading.addClass('collapsible-heading')
			.prepend('')
			.wrapInner('');

		collapsibleContent.addClass('collapsible-content');

		//events
		collapsibleHeading
			.bind('collapse', function(){
				$(this)
					.addClass('collapsible-heading-collapsed')
					.find('.collapsible-heading-status').text('Show ');

				collapsibleContent.slideUp(function(){
					$(this).addClass('collapsible-content-collapsed').removeAttr('style').attr('aria-hidden',true);
				});
			})
			.bind('expand', function(){
				$(this)
					.removeClass('collapsible-heading-collapsed')
					.find('.collapsible-heading-status').text('Hide ');

				collapsibleContent
					.slideDown(function(){
						$(this).removeClass('collapsible-content-collapsed').removeAttr('style').attr('aria-hidden',false);
					});
			})
			.click(function(){
				if( $(this).is('.collapsible-heading-collapsed') ){
					$(this).trigger('expand');
				}
				else {
					$(this).trigger('collapse');
				}
				return false;
			})
			.trigger('collapse');
	});
};	<commit_msg>Add option to start expanded<commit_after>/**
 * --------------------------------------------------------------------
 * jQuery collapsible plugin
 * Author: Scott Jehl, scott@filamentgroup.com
 * Copyright (c) 2009 Filament Group
 * licensed under MIT (filamentgroup.com/examples/mit-license.txt)
 * --------------------------------------------------------------------
 */
$.fn.collapsible = function(startExpanded){
	return $(this).each(function(){

		//define
		var collapsibleHeading = $(this);
		var collapsibleContent = collapsibleHeading.next();

		//modify markup & attributes
		collapsibleHeading.addClass('collapsible-heading')
			.prepend('')
			.wrapInner('');

		collapsibleContent.addClass('collapsible-content');

		//events
		collapsibleHeading
			.bind('collapse', function(){
				$(this)
					.addClass('collapsible-heading-collapsed')
					.find('.collapsible-heading-status').text('Show ');

				collapsibleContent.slideUp(function(){
					$(this).addClass('collapsible-content-collapsed').removeAttr('style').attr('aria-hidden',true);
				});
			})
			.bind('expand', function(){
				$(this)
					.removeClass('collapsible-heading-collapsed')
					.find('.collapsible-heading-status').text('Hide ');

				collapsibleContent
					.slideDown(function(){
						$(this).removeClass('collapsible-content-collapsed').removeAttr('style').attr('aria-hidden',false);
					});
			})
			.click(function(){
				if( $(this).is('.collapsible-heading-collapsed') ){
					$(this).trigger('expand');
				}
				else {
					$(this).trigger('collapse');
				}
				return false;
			})
			.trigger(startExpanded ? 'expand' : 'collapse');
	});
};	<|endoftext|>


<commit_before>/**
 * @class InvertedIndex
 */
class InvertedIndex {
  /**
   * @constructor
   */
  constructor() {
    this.indices = [];
    this.allBooks = [];
  }

  /**
   * A tokenizer method
   */
  tokenizer(string) {
      return string.replace(/[^a-z\d\s]/ig, ' ').trim().toLowerCase().split(/\s+/);
    }
    /**
     * A createIndex method
     * It takes in the filePath and the contents of the filePath
     * @param {Object} filePath
     * @param {Object} content
     * @returns {Object} Returns object containing index
     */
  createIndex(filePath, content) {
    const result = {};
    if (!filePath) {
      content = this.allBooks;
    }

    content.forEach((book, doc) => {
      for (let key in book) {
        this.tokenizer(book[key]).forEach(word => {
          if (!result.hasOwnProperty(word)) {
            result[word] = [];
          }
          if (result[word].indexOf(doc + 1) > -1) {
            return;
          }
          result[word].push(doc + 1);
        });
      }
    });
    const returnResult = {
      terms: result,
      count: content.length
    };

    if (filePath) {
      this.indices[filePath] = returnResult;
    } else {
      this.fullIndex = returnResult;
    }
  }

  /**
   * GetIndex
   * Gets the index of the files uploaded
   * @param {any} filename
   * @returns {any} void
   */
  getIndex(filePath) {
    return this.indices[filePath];
  }

  /**
   * Search index method
   * @param {String} filePath word(s) or terms to search for
   *  * @param {String} query
   * @returns {Object} Returns result of searched index.
   */
  searchIndex(filePath, query) {
    const result = {};
    let indexedFile;
    if (filePath) {
      indexedFile = this.getIndex(filePath);
    } else {
      indexedFile = this.fullIndex;
    }

    if (!query || !indexedFile) {
      return 'file does not exist';
    }
    this.tokenizer(query).forEach(word => {
      if (indexedFile.terms.hasOwnProperty(word)) {
        result[word] = indexedFile.terms[word];
      }
    });
    const returnResult = {
      terms: result,
      count: indexedFile.count
    };
    return returnResult;
  }

  /**
   * validateFile a method to validate json file
   * @param {Object} content
   * @returns {Array} Returns message in Json format.
   */

  validateFile(content) {
    const fileName = this.indices;
    let status = true;
    if (typeof content !== 'object' || content.length === 0) {

      return false;
    }

    try {
      content.forEach((book) => {
        const bookTitle = Object.hasOwnProperty.call(book, 'title');
        const bookText = Object.hasOwnProperty.call(book, 'text');
        if (!(bookTitle && bookText)) {
          throw new Error("Invalid book");
        }
      });
      return true;
    } catch (err) {
      return false;
    }
  }
}
<commit_msg>add a descriptive comment<commit_after>/**
 * @class InvertedIndex
 */
class InvertedIndex {
  /**
   * @constructor
   */
  constructor() {
    this.indices = [];
    this.allBooks = [];
  }

  /**
   * A tokenizer method
   */
  tokenizer(string) {
      return string.replace(/[^a-z\d\s]/ig, ' ').trim().toLowerCase().split(/\s+/);
    }
    /**
     * A createIndex method
     * It takes in the filePath and the contents of the filePath
     * @param {Object} filePath
     * @param {Object} content
     * @returns {Object} Returns object containing index
     */
  createIndex(filePath, content) {
    const result = {};
    // store all json files uploaded in an array which is this.allBooks
    if (!filePath) {
      content = this.allBooks;
    }

    content.forEach((book, doc) => {
      for (let key in book) {
        this.tokenizer(book[key]).forEach(word => {
          if (!result.hasOwnProperty(word)) {
            result[word] = [];
          }
          if (result[word].indexOf(doc + 1) > -1) {
            return;
          }
          result[word].push(doc + 1);
        });
      }
    });
    const returnResult = {
      terms: result,
      count: content.length
    };

    if (filePath) {
      this.indices[filePath] = returnResult;
    } else {
      this.fullIndex = returnResult;
    }
  }

  /**
   * GetIndex
   * Gets the index of the files uploaded
   * @param {any} filename
   * @returns {any} void
   */
  getIndex(filePath) {
    return this.indices[filePath];
  }

  /**
   * Search index method
   * @param {String} filePath word(s) or terms to search for
   *  * @param {String} query
   * @returns {Object} Returns result of searched index.
   */
  searchIndex(filePath, query) {
    const result = {};
    let indexedFile;
    if (filePath) {
      indexedFile = this.getIndex(filePath);
    } else {
      indexedFile = this.fullIndex;
    }

    if (!query || !indexedFile) {
      return 'file does not exist';
    }
    this.tokenizer(query).forEach(word => {
      if (indexedFile.terms.hasOwnProperty(word)) {
        result[word] = indexedFile.terms[word];
      }
    });
    const returnResult = {
      terms: result,
      count: indexedFile.count
    };
    return returnResult;
  }

  /**
   * validateFile a method to validate json file
   * @param {Object} content
   * @returns {Array} Returns message in Json format.
   */

  validateFile(content) {
    const fileName = this.indices;
    let status = true;
    if (typeof content !== 'object' || content.length === 0) {

      return false;
    }

    try {
      content.forEach((book) => {
        const bookTitle = Object.hasOwnProperty.call(book, 'title');
        const bookText = Object.hasOwnProperty.call(book, 'text');
        if (!(bookTitle && bookText)) {
          throw new Error("Invalid book");
        }
      });
      return true;
    } catch (err) {
      return false;
    }
  }
}
<|endoftext|>


<commit_before>var path = require('path');

module.exports = {
  entry: './src/app.js',
  target: 'node',
  output: {
    path: path.join(__dirname, 'build'),
    filename: 'backend.js'
  }
}
<commit_msg>chore(webpack): prevent webpack to bundle node_modules<commit_after>var path = require('path');
var fs = require('fs');

var nodeModules = fs
  .readdirSync('node_modules')
  .filter(function(x) {
    return ['.bin'].indexOf(x) === -1;
  });

module.exports = {
  entry: './src/app.js',
  target: 'node',
  output: {
    path: path.join(__dirname, 'build'),
    filename: 'backend.js',
    libraryTarget: 'commonjs2'
  },
  externals: nodeModules
}
<|endoftext|>


<commit_before>/*!
 * jQuery Mobile v@VERSION
 * http://jquerymobile.com/
 *
 * Copyright 2010, jQuery Project
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 */

(function( $, window, undefined ) {
	var	$html = $( "html" ),
			$head = $( "head" ),
			$window = $( window );

 	//trigger mobileinit event - useful hook for configuring $.mobile settings before they're used
	$( window.document ).trigger( "mobileinit" );

	//support conditions
	//if device support condition(s) aren't met, leave things as they are -> a basic, usable experience,
	//otherwise, proceed with the enhancements
	if ( !$.mobile.gradeA() ) {
		return;
	}

	//add mobile, initial load "rendering" classes to docEl
	$html.addClass( "ui-mobile ui-mobile-rendering" );

	//define & prepend meta viewport tag, if content is defined
	//NOTE: this is now deprecated. We recommend placing the meta viewport element in
	//the markup from the start.
	$.mobile.metaViewportContent && !$head.find( "meta[name='viewport']" ).length ? $( "<meta>", { name: "viewport", content: $.mobile.metaViewportContent}).prependTo( $head ) : undefined;

	//loading div which appears during Ajax requests
	//will not appear if $.mobile.loadingMessage is false
	var $loader = $.mobile.loadingMessage ?		$( "
" + "" + "
" + $.mobile.loadingMessage + "
" + "
" )	: undefined;

	if(typeof $loader === "undefined"){
		alert($.mobile.loadingMessage);
	}

	$.extend($.mobile, {
		// turn on/off page loading message.
		pageLoading: function ( done ) {
			if ( done ) {
				$html.removeClass( "ui-loading" );
			} else {
				if( $.mobile.loadingMessage ){
					var activeBtn = $( "." + $.mobile.activeBtnClass ).first();

					if(typeof $loader === "undefined"){
						 alert($.mobile.loadingMessage);
					}

					$loader
						.appendTo( $.mobile.pageContainer )
						//position at y center (if scrollTop supported), above the activeBtn (if defined), or just 100px from top
						.css( {
							top: $.support.scrollTop && $(window).scrollTop() + $(window).height() / 2 ||
							activeBtn.length && activeBtn.offset().top || 100
						} );
				}

				$html.addClass( "ui-loading" );
			}
		},

		// find and enhance the pages in the dom and transition to the first page.
		initializePage: function(){
			//find present pages
			var $pages = $( ":jqmData(role='page')" );

			//add dialogs, set data-url attrs
			$pages.add( ":jqmData(role='dialog')" ).each(function(){
				var $this = $(this);

				// unless the data url is already set set it to the id
				if( !$this.jqmData('url') ){
					$this.attr( "data-" + $.mobile.ns + "url", $this.attr( "id" ) );
				}
			});

			//define first page in dom case one backs out to the directory root (not always the first page visited, but defined as fallback)
			$.mobile.firstPage = $pages.first();

			//define page container
			$.mobile.pageContainer = $pages.first().parent().addClass( "ui-mobile-viewport" );

			//cue page loading message
			$.mobile.pageLoading();

			// if hashchange listening is disabled or there's no hash deeplink, change to the first page in the DOM
			if( !$.mobile.hashListeningEnabled || !$.mobile.path.stripHash( location.hash ) ){
				$.mobile.changePage( $.mobile.firstPage, false, true, false, true );
			}
			// otherwise, trigger a hashchange to load a deeplink
			else {
				$window.trigger( "hashchange", [ true ] );
			}
		}
	});

	//dom-ready inits
	$( $.mobile.initializePage );

	//window load event
	//hide iOS browser chrome on load
	$window.load( $.mobile.silentScroll );
})( jQuery, this );
<commit_msg>remove ie debug alert<commit_after>/*!
 * jQuery Mobile v@VERSION
 * http://jquerymobile.com/
 *
 * Copyright 2010, jQuery Project
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 */

(function( $, window, undefined ) {
	var	$html = $( "html" ),
			$head = $( "head" ),
			$window = $( window );

 	//trigger mobileinit event - useful hook for configuring $.mobile settings before they're used
	$( window.document ).trigger( "mobileinit" );

	//support conditions
	//if device support condition(s) aren't met, leave things as they are -> a basic, usable experience,
	//otherwise, proceed with the enhancements
	if ( !$.mobile.gradeA() ) {
		return;
	}

	//add mobile, initial load "rendering" classes to docEl
	$html.addClass( "ui-mobile ui-mobile-rendering" );

	//define & prepend meta viewport tag, if content is defined
	//NOTE: this is now deprecated. We recommend placing the meta viewport element in
	//the markup from the start.
	$.mobile.metaViewportContent && !$head.find( "meta[name='viewport']" ).length ? $( "<meta>", { name: "viewport", content: $.mobile.metaViewportContent}).prependTo( $head ) : undefined;

	//loading div which appears during Ajax requests
	//will not appear if $.mobile.loadingMessage is false
	var $loader = $.mobile.loadingMessage ?		$( "
" + "" + "
" + $.mobile.loadingMessage + "
" + "
" )	: undefined;

	if(typeof $loader === "undefined"){
		alert($.mobile.loadingMessage);
	}

	$.extend($.mobile, {
		// turn on/off page loading message.
		pageLoading: function ( done ) {
			if ( done ) {
				$html.removeClass( "ui-loading" );
			} else {
				if( $.mobile.loadingMessage ){
					var activeBtn = $( "." + $.mobile.activeBtnClass ).first();

					$loader
						.appendTo( $.mobile.pageContainer )
						//position at y center (if scrollTop supported), above the activeBtn (if defined), or just 100px from top
						.css( {
							top: $.support.scrollTop && $(window).scrollTop() + $(window).height() / 2 ||
							activeBtn.length && activeBtn.offset().top || 100
						} );
				}

				$html.addClass( "ui-loading" );
			}
		},

		// find and enhance the pages in the dom and transition to the first page.
		initializePage: function(){
			//find present pages
			var $pages = $( ":jqmData(role='page')" );

			//add dialogs, set data-url attrs
			$pages.add( ":jqmData(role='dialog')" ).each(function(){
				var $this = $(this);

				// unless the data url is already set set it to the id
				if( !$this.jqmData('url') ){
					$this.attr( "data-" + $.mobile.ns + "url", $this.attr( "id" ) );
				}
			});

			//define first page in dom case one backs out to the directory root (not always the first page visited, but defined as fallback)
			$.mobile.firstPage = $pages.first();

			//define page container
			$.mobile.pageContainer = $pages.first().parent().addClass( "ui-mobile-viewport" );

			//cue page loading message
			$.mobile.pageLoading();

			// if hashchange listening is disabled or there's no hash deeplink, change to the first page in the DOM
			if( !$.mobile.hashListeningEnabled || !$.mobile.path.stripHash( location.hash ) ){
				$.mobile.changePage( $.mobile.firstPage, false, true, false, true );
			}
			// otherwise, trigger a hashchange to load a deeplink
			else {
				$window.trigger( "hashchange", [ true ] );
			}
		}
	});

	//dom-ready inits
	$( $.mobile.initializePage );

	//window load event
	//hide iOS browser chrome on load
	$window.load( $.mobile.silentScroll );
})( jQuery, this );
<|endoftext|>


<commit_before>function add_ls(args) {
    var svg = mg_get_svg_child_of(args.target);
    var data = args.data[0];
    var min_x = args.scales.X.ticks(args.xax_count)[0];
    var max_x = args.scales.X.ticks(args.xax_count)[args.scales.X.ticks(args.xax_count).length - 1];

    d3.select(args.target).selectAll('.mg-least-squares-line').remove();

    svg.append('svg:line')
        .attr('x1', args.scales.X(min_x))
        .attr('x2', args.scales.X(max_x))
        .attr('y1', args.scales.Y(args.ls_line.fit(min_x)) )
        .attr('y2', args.scales.Y(args.ls_line.fit(max_x)) )
        .attr('class', 'mg-least-squares-line');
}

MG.add_ls = add_ls;

function add_lowess(args) {
    var svg = d3.select($(args.target).find('svg').get(0));
    var lowess = args.lowess_line;

    var line = d3.svg.line()
        .x(function(d) { return args.scales.X(d.x); })
        .y(function(d) { return args.scales.Y(d.y); })
            .interpolate(args.interpolate);

    svg.append('path')
        .attr('d', line(lowess))
        .attr('class', 'mg-lowess-line');
}

MG.add_lowess = add_lowess;

function lowess_robust(x, y, alpha, inc) {
    // Used http://www.unc.edu/courses/2007spring/biol/145/001/docs/lectures/Oct27.html
    // for the clear explanation of robust lowess.

    // calculate the the first pass.
    var _l;
    var r = [];
    var yhat = d3.mean(y);
    var i;
    for (i = 0; i < x.length; i += 1) { r.push(1); }
    _l = _calculate_lowess_fit(x,y,alpha, inc, r);
    var x_proto = _l.x;
    var y_proto = _l.y;

    // Now, take the fit, recalculate the weights, and re-run LOWESS using r*w instead of w.

    for (i = 0; i < 100; i += 1) {
        r = d3.zip(y_proto, y).map(function(yi) {
            return Math.abs(yi[1] - yi[0]);
        });

        var q = d3.quantile(r.sort(), 0.5);

        r = r.map(function(ri) {
            return _bisquare_weight(ri / (6 * q));
        });

        _l = _calculate_lowess_fit(x,y,alpha,inc, r);
        x_proto = _l.x;
        y_proto = _l.y;
    }

    return d3.zip(x_proto, y_proto).map(function(d) {
        var p = {};
        p.x = d[0];
        p.y = d[1];
        return p;
    });
}

MG.lowess_robust = lowess_robust;

function lowess(x, y, alpha, inc) {
    var r = [];
    for (var i = 0; i < x.length; i += 1) { r.push(1); }
    var _l = _calculate_lowess_fit(x, y, alpha, inc, r);
}

MG.lowess = lowess;

function least_squares(x_, y_) {
    var x, y, xi, yi,
        _x  = 0,
        _y  = 0,
        _xy = 0,
        _xx = 0;

    var n = x_.length;
    if (x_[0] instanceof Date) {
        x = x_.map(function(d) {
            return d.getTime();
        });
    } else {
        x = x_;
    }

    if (y_[0] instanceof Date) {
        y = y_.map(function(d) {
            return d.getTime();
        });
    } else {
        y = y_;
    }

    var xhat = d3.mean(x);
    var yhat = d3.mean(y);
    var numerator = 0, denominator = 0;

    for (var i = 0; i < x.length; i++) {
        xi = x[i];
        yi = y[i];
        numerator += (xi - xhat) * (yi - yhat);
        denominator += (xi - xhat) * (xi - xhat);
    }

    var beta = numerator / denominator;
    var x0 = yhat - beta * xhat;

    return {
        x0: x0,
        beta: beta,
        fit: function(x) {
            return x0 + x * beta;
        }
    };
}

MG.least_squares = least_squares;

function _pow_weight(u, w) {
    if (u >= 0 && u <= 1) {
        return Math.pow(1 - Math.pow(u,w), w);
    } else {
        return 0;
    }
}

function _bisquare_weight(u) {
    return _pow_weight(u, 2);
}

function _tricube_weight(u) {
    return _pow_weight(u, 3);
}

function _neighborhood_width(x0, xis) {
    return Array.max(xis.map(function(xi) {
        return Math.abs(x0 - xi);
    }));
}

function _manhattan(x1,x2) {
    return Math.abs(x1 - x2);
}

function _weighted_means(wxy) {
    var wsum = d3.sum(wxy.map(function(wxyi) { return wxyi.w; }));

    return {
        xbar: d3.sum(wxy.map(function(wxyi) {
            return wxyi.w * wxyi.x;
        })) / wsum,
        ybar:d3.sum(wxy.map(function(wxyi) {
            return wxyi.w * wxyi.y;
        })) / wsum
    };
}

function _weighted_beta(wxy, xbar, ybar) {
    var num = d3.sum(wxy.map(function(wxyi) {
        return Math.pow(wxyi.w, 2) * (wxyi.x - xbar) * (wxyi.y - ybar);
    }));

    var denom = d3.sum(wxy.map(function(wxyi) {
        return Math.pow(wxyi.w, 2) * Math.pow(wxyi.x - xbar, 2);
    }));

    return num / denom;
}

function _weighted_least_squares(wxy) {
    var ybar, xbar, beta_i, x0;

    var _wm = _weighted_means(wxy);

    xbar = _wm.xbar;
    ybar = _wm.ybar;

    var beta = _weighted_beta(wxy, xbar, ybar);

    return {
        beta : beta,
        xbar : xbar,
        ybar : ybar,
        x0   : ybar - beta * xbar

    };
}

function _calculate_lowess_fit(x, y, alpha, inc, residuals) {
    // alpha - smoothing factor. 0 < alpha < 1/
    //
    //
    var k = Math.floor(x.length * alpha);

    var sorted_x = x.slice();

    sorted_x.sort(function(a,b) {
        if (a < b) { return -1; }
        else if (a > b) { return 1; }

        return 0;
    });

    var x_max = d3.quantile(sorted_x, 0.98);
    var x_min = d3.quantile(sorted_x, 0.02);

    var xy = d3.zip(x, y, residuals).sort();

    var size = Math.abs(x_max - x_min) / inc;

    var smallest = x_min;
    var largest = x_max;
    var x_proto = d3.range(smallest, largest, size);

    var xi_neighbors;
    var x_i, beta_i, x0_i, delta_i, xbar, ybar;

    // for each prototype, find its fit.
    var y_proto = [];

    for (var i = 0; i < x_proto.length; i += 1) {
        x_i = x_proto[i];

        // get k closest neighbors.
        xi_neighbors = xy.map(function(xyi) {
            return [
                Math.abs(xyi[0] - x_i),
                xyi[0],
                xyi[1],
                xyi[2]];
        }).sort().slice(0, k);

        // Get the largest distance in the neighbor set.
        delta_i = d3.max(xi_neighbors)[0];

        // Prepare the weights for mean calculation and WLS.

        xi_neighbors = xi_neighbors.map(function(wxy) {
            return {
                w : _tricube_weight(wxy[0] / delta_i) * wxy[3],
                x : wxy[1],
                y  :wxy[2]
            };
        });

        // Find the weighted least squares, obviously.
        var _output = _weighted_least_squares(xi_neighbors);

        x0_i = _output.x0;
        beta_i = _output.beta;

        //
        y_proto.push(x0_i + beta_i * x_i);
    }

    return {x: x_proto, y: y_proto};
}
<commit_msg>Fix #485 - make least squares line span range of data rather than ticks<commit_after>function add_ls(args) {
    var svg = mg_get_svg_child_of(args.target);
    var data = args.data[0];
    var min_x = d3.min(args.data[0], function(d) { return d[args.x_accessor]; });
    var max_x = d3.max(args.data[0], function(d) { return d[args.x_accessor]; });

    d3.select(args.target).selectAll('.mg-least-squares-line').remove();

    svg.append('svg:line')
        .attr('x1', args.scales.X(min_x))
        .attr('x2', args.scales.X(max_x))
        .attr('y1', args.scales.Y(args.ls_line.fit(min_x)) )
        .attr('y2', args.scales.Y(args.ls_line.fit(max_x)) )
        .attr('class', 'mg-least-squares-line');
}

MG.add_ls = add_ls;

function add_lowess(args) {
    var svg = d3.select($(args.target).find('svg').get(0));
    var lowess = args.lowess_line;

    var line = d3.svg.line()
        .x(function(d) { return args.scales.X(d.x); })
        .y(function(d) { return args.scales.Y(d.y); })
            .interpolate(args.interpolate);

    svg.append('path')
        .attr('d', line(lowess))
        .attr('class', 'mg-lowess-line');
}

MG.add_lowess = add_lowess;

function lowess_robust(x, y, alpha, inc) {
    // Used http://www.unc.edu/courses/2007spring/biol/145/001/docs/lectures/Oct27.html
    // for the clear explanation of robust lowess.

    // calculate the the first pass.
    var _l;
    var r = [];
    var yhat = d3.mean(y);
    var i;
    for (i = 0; i < x.length; i += 1) { r.push(1); }
    _l = _calculate_lowess_fit(x,y,alpha, inc, r);
    var x_proto = _l.x;
    var y_proto = _l.y;

    // Now, take the fit, recalculate the weights, and re-run LOWESS using r*w instead of w.

    for (i = 0; i < 100; i += 1) {
        r = d3.zip(y_proto, y).map(function(yi) {
            return Math.abs(yi[1] - yi[0]);
        });

        var q = d3.quantile(r.sort(), 0.5);

        r = r.map(function(ri) {
            return _bisquare_weight(ri / (6 * q));
        });

        _l = _calculate_lowess_fit(x,y,alpha,inc, r);
        x_proto = _l.x;
        y_proto = _l.y;
    }

    return d3.zip(x_proto, y_proto).map(function(d) {
        var p = {};
        p.x = d[0];
        p.y = d[1];
        return p;
    });
}

MG.lowess_robust = lowess_robust;

function lowess(x, y, alpha, inc) {
    var r = [];
    for (var i = 0; i < x.length; i += 1) { r.push(1); }
    var _l = _calculate_lowess_fit(x, y, alpha, inc, r);
}

MG.lowess = lowess;

function least_squares(x_, y_) {
    var x, y, xi, yi,
        _x  = 0,
        _y  = 0,
        _xy = 0,
        _xx = 0;

    var n = x_.length;
    if (x_[0] instanceof Date) {
        x = x_.map(function(d) {
            return d.getTime();
        });
    } else {
        x = x_;
    }

    if (y_[0] instanceof Date) {
        y = y_.map(function(d) {
            return d.getTime();
        });
    } else {
        y = y_;
    }

    var xhat = d3.mean(x);
    var yhat = d3.mean(y);
    var numerator = 0, denominator = 0;

    for (var i = 0; i < x.length; i++) {
        xi = x[i];
        yi = y[i];
        numerator += (xi - xhat) * (yi - yhat);
        denominator += (xi - xhat) * (xi - xhat);
    }

    var beta = numerator / denominator;
    var x0 = yhat - beta * xhat;

    return {
        x0: x0,
        beta: beta,
        fit: function(x) {
            return x0 + x * beta;
        }
    };
}

MG.least_squares = least_squares;

function _pow_weight(u, w) {
    if (u >= 0 && u <= 1) {
        return Math.pow(1 - Math.pow(u,w), w);
    } else {
        return 0;
    }
}

function _bisquare_weight(u) {
    return _pow_weight(u, 2);
}

function _tricube_weight(u) {
    return _pow_weight(u, 3);
}

function _neighborhood_width(x0, xis) {
    return Array.max(xis.map(function(xi) {
        return Math.abs(x0 - xi);
    }));
}

function _manhattan(x1,x2) {
    return Math.abs(x1 - x2);
}

function _weighted_means(wxy) {
    var wsum = d3.sum(wxy.map(function(wxyi) { return wxyi.w; }));

    return {
        xbar: d3.sum(wxy.map(function(wxyi) {
            return wxyi.w * wxyi.x;
        })) / wsum,
        ybar:d3.sum(wxy.map(function(wxyi) {
            return wxyi.w * wxyi.y;
        })) / wsum
    };
}

function _weighted_beta(wxy, xbar, ybar) {
    var num = d3.sum(wxy.map(function(wxyi) {
        return Math.pow(wxyi.w, 2) * (wxyi.x - xbar) * (wxyi.y - ybar);
    }));

    var denom = d3.sum(wxy.map(function(wxyi) {
        return Math.pow(wxyi.w, 2) * Math.pow(wxyi.x - xbar, 2);
    }));

    return num / denom;
}

function _weighted_least_squares(wxy) {
    var ybar, xbar, beta_i, x0;

    var _wm = _weighted_means(wxy);

    xbar = _wm.xbar;
    ybar = _wm.ybar;

    var beta = _weighted_beta(wxy, xbar, ybar);

    return {
        beta : beta,
        xbar : xbar,
        ybar : ybar,
        x0   : ybar - beta * xbar

    };
}

function _calculate_lowess_fit(x, y, alpha, inc, residuals) {
    // alpha - smoothing factor. 0 < alpha < 1/
    //
    //
    var k = Math.floor(x.length * alpha);

    var sorted_x = x.slice();

    sorted_x.sort(function(a,b) {
        if (a < b) { return -1; }
        else if (a > b) { return 1; }

        return 0;
    });

    var x_max = d3.quantile(sorted_x, 0.98);
    var x_min = d3.quantile(sorted_x, 0.02);

    var xy = d3.zip(x, y, residuals).sort();

    var size = Math.abs(x_max - x_min) / inc;

    var smallest = x_min;
    var largest = x_max;
    var x_proto = d3.range(smallest, largest, size);

    var xi_neighbors;
    var x_i, beta_i, x0_i, delta_i, xbar, ybar;

    // for each prototype, find its fit.
    var y_proto = [];

    for (var i = 0; i < x_proto.length; i += 1) {
        x_i = x_proto[i];

        // get k closest neighbors.
        xi_neighbors = xy.map(function(xyi) {
            return [
                Math.abs(xyi[0] - x_i),
                xyi[0],
                xyi[1],
                xyi[2]];
        }).sort().slice(0, k);

        // Get the largest distance in the neighbor set.
        delta_i = d3.max(xi_neighbors)[0];

        // Prepare the weights for mean calculation and WLS.

        xi_neighbors = xi_neighbors.map(function(wxy) {
            return {
                w : _tricube_weight(wxy[0] / delta_i) * wxy[3],
                x : wxy[1],
                y  :wxy[2]
            };
        });

        // Find the weighted least squares, obviously.
        var _output = _weighted_least_squares(xi_neighbors);

        x0_i = _output.x0;
        beta_i = _output.beta;

        //
        y_proto.push(x0_i + beta_i * x_i);
    }

    return {x: x_proto, y: y_proto};
}
<|endoftext|>


<commit_before>/**
 * Moonshine
 * A multi node graph implementation using HTML5 Canvas
 *
 * based on https://github.com/boundary/html5-node-diagram
 **/

// Configurations
var CONFIG = {
    width: 120,
    height: 50,
    enableEditTitleOnClick: false
};

// internal varaibles
var stage;
var Node = window.Node;
var Segment = window.Segment;
var highlightedNode;

/**
 * Initialize and run the application
 */
(function($, window) {
	function initialize() {
		// Do some animation to the stage onload
		$("#stage").hide().delay(100).fadeIn(300);
		stage = $('#stage');

		// Create the nodes
		createNodes();

		// Create links between nodes
		createLinks();
	}
	initialize();
}(jQuery, window));

//-------------------------------------------------------------------
// Utility Methods
//-------------------------------------------------------------------

// Creates a node based on a template
function createNode(nodeTitle, nodeId, nodeX, nodeY){
	return new Node({
		title: nodeTitle,
		id: nodeId,
		filepath: 'placeholder',
		stage: stage,
		w: CONFIG.width,
		h: CONFIG.height,
		x: nodeX,
		y: nodeY,
		events: {
			click: function() {
				var nodeid = '#' + this.id;
				$node = $(nodeid);
				$node.focus();

				var nodeSelected = $node.data( 'nodeSelected');

				$node.mouseup( function(){
					$( nodeid ).css( 'background', '#4db6ac' ); /* backgound color from .node*/
				});
				$node.mousedown( function(){
					$( nodeid ).css( 'background', '#99cc00' ); /* highlight color*/
				});
				if( nodeSelected != 'selected') {
					// Do stuff for selected state
					$node.data( 'nodeSelected', 'selected' );

					var includesegments = this.segments;
					for( i = 0; i < includesegments.length; i++) {
						var includesegmentid = '#' + includesegments[i].id;
						$( includesegmentid ).css( 'opacity', '1' );
						$('#' + includesegments[i].origin.id ).css( 'opacity', '1' );
						$('#' + includesegments[i].destination.id ).css( 'opacity', '1' );
					}

					// allow the title to be modified if enabled
					if(CONFIG.enableEditTitleOnClick){
                        			// Reset the border for the previously highlighted node
                				if(undefined != highlightedNode){
                            				highlightedNode.css('border-color', '#ffffff');
                        			}

                        			// Highlight this node and setup a listener for keypress
						$node.css('border-color', '#ec461c');
						$node.bind("keypress", function(e){
							$thisNode = $(this);

							// Clear the content on first keypress
							if($thisNode.data( 'editStarted') != 'true'){
								$thisNode.data( 'editStarted', 'true');
								$thisNode.children().first().text('')
							}

							var code = (e.keyCode ? e.keyCode : e.which);
							var text = $thisNode.children().first().text() + String.fromCharCode(code);
							$thisNode.children().first().text(text);

						});

						// Save this node as the highlighted node
                        			highlightedNode = $node;
					}
				} else {
					// Do stuff for non selected state
					$node.data( 'nodeSelected', 'notselected' );

					var includesegments = this.segments;
					for( i = 0; i < includesegments.length; i++) {
						var includesegmentid = '#' + includesegments[i].id;
					}

					if(CONFIG.enableEditTitleOnClick){
						// Reset the node highlight signifying edit
						$node.css('border-color', '#ffffff');

						// Stop edit when the node is clicked again
						$node.unbind("keypress");
						$node.data( 'editStarted', 'false');
					}
				}
			}
		}
	}).attach();
}

// Prevent backspace key from navigating out of the app
$(document).on("keydown", function (e) {
    if (e.which === 8 && !$(e.target).is("input, textarea")) {
        e.preventDefault();
    }
});

/**
 * Create and attach a segment between two given nodes
 */
function createAndAttachSegment(originNode, destinationNode){
	var segmentId = "includesegment-" + originNode.id + "-" + destinationNode.id;
	new Segment({h: 5, id:segmentId, stage: stage, origin: originNode, destination: destinationNode}).attach();
}

/**
 * Creates all the nodes. All created nodes are public.
 * Generated code can be placed in this method and the links should be added in
 * the createLinks() method
 */
function createNodes() {
    // Dictionary of all nodes with the ID as key
    nodes = [];

    // List of links in {source, destination} format
    links = [];

    // Iterate over the datas defined in data.js
    $(graphDatas).each( function(){
        $data = $(this)[0];

        // create a node from the data and add it to the dictionary
        nodes[$data._id] = createNode($data.text, $data._id, $data.xPos, $data.yPos);

        // Store the link references and build links later once we have all the nodes
        $($data.links).each( function(){
            links[links.length] = {"source": $data._id, "target": $(this)[0]._id};
        });
    });
}

/**
 * Cretes the links between the nodes
 */
function createLinks() {
    // Now all the nodes should be available for creating the links
    $(links).each( function(){
        var source = nodes[$(this)[0].source];
        var target = nodes[$(this)[0].target];

        createAndAttachSegment(source, target);
    });
}
<commit_msg>Add experimental flag for enableAddNodeButton<commit_after>/**
 * Moonshine
 * A multi node graph implementation using HTML5 Canvas
 *
 * based on https://github.com/boundary/html5-node-diagram
 **/

// Configurations
var CONFIG = {
    width: 120,
    height: 50,
    enableEditTitleOnClick: false,
    enableAddNodeButton: false
};

// internal varaibles
var stage;
var Node = window.Node;
var Segment = window.Segment;
var highlightedNode;

/**
 * Initialize and run the application
 */
(function($, window) {
	function initialize() {
		// Do some animation to the stage onload
		$("#stage").hide().delay(100).fadeIn(300);
		stage = $('#stage');

		// Create the nodes
		createNodes();

		// Create links between nodes
		createLinks();
	}
	initialize();
}(jQuery, window));

//-------------------------------------------------------------------
// Utility Methods
//-------------------------------------------------------------------

// Creates a node based on a template
function createNode(nodeTitle, nodeId, nodeX, nodeY){
	return new Node({
		title: nodeTitle,
		id: nodeId,
		filepath: 'placeholder',
		stage: stage,
		w: CONFIG.width,
		h: CONFIG.height,
		x: nodeX,
		y: nodeY,
		events: {
			click: function() {
				var nodeid = '#' + this.id;
				$node = $(nodeid);
				$node.focus();

				var nodeSelected = $node.data( 'nodeSelected');

				$node.mouseup( function(){
					$( nodeid ).css( 'background', '#4db6ac' ); /* backgound color from .node*/
				});
				$node.mousedown( function(){
					$( nodeid ).css( 'background', '#99cc00' ); /* highlight color*/
				});
				if( nodeSelected != 'selected') {
					// Do stuff for selected state
					$node.data( 'nodeSelected', 'selected' );

					var includesegments = this.segments;
					for( i = 0; i < includesegments.length; i++) {
						var includesegmentid = '#' + includesegments[i].id;
						$( includesegmentid ).css( 'opacity', '1' );
						$('#' + includesegments[i].origin.id ).css( 'opacity', '1' );
						$('#' + includesegments[i].destination.id ).css( 'opacity', '1' );
					}

					// allow the title to be modified if enabled
					if(CONFIG.enableEditTitleOnClick){
                        			// Reset the border for the previously highlighted node
                				if(undefined != highlightedNode){
                            				highlightedNode.css('border-color', '#ffffff');
                        			}

                        			// Highlight this node and setup a listener for keypress
						$node.css('border-color', '#ec461c');
						$node.bind("keypress", function(e){
							$thisNode = $(this);

							// Clear the content on first keypress
							if($thisNode.data( 'editStarted') != 'true'){
								$thisNode.data( 'editStarted', 'true');
								$thisNode.children().first().text('')
							}

							var code = (e.keyCode ? e.keyCode : e.which);
							var text = $thisNode.children().first().text() + String.fromCharCode(code);
							$thisNode.children().first().text(text);

						});

						// Save this node as the highlighted node
                        			highlightedNode = $node;
					}
				} else {
					// Do stuff for non selected state
					$node.data( 'nodeSelected', 'notselected' );

					var includesegments = this.segments;
					for( i = 0; i < includesegments.length; i++) {
						var includesegmentid = '#' + includesegments[i].id;
					}

					if(CONFIG.enableEditTitleOnClick){
						// Reset the node highlight signifying edit
						$node.css('border-color', '#ffffff');

						// Stop edit when the node is clicked again
						$node.unbind("keypress");
						$node.data( 'editStarted', 'false');
					}
				}
			}
		}
	}).attach();
}

// Prevent backspace key from navigating out of the app
$(document).on("keydown", function (e) {
    if (e.which === 8 && !$(e.target).is("input, textarea")) {
        e.preventDefault();
    }
});

/**
 * Create and attach a segment between two given nodes
 */
function createAndAttachSegment(originNode, destinationNode){
	var segmentId = "includesegment-" + originNode.id + "-" + destinationNode.id;
	new Segment({h: 5, id:segmentId, stage: stage, origin: originNode, destination: destinationNode}).attach();
}

/**
 * Creates all the nodes. All created nodes are public.
 * Generated code can be placed in this method and the links should be added in
 * the createLinks() method
 */
function createNodes() {
    // Dictionary of all nodes with the ID as key
    nodes = [];

    // List of links in {source, destination} format
    links = [];

    // Iterate over the datas defined in data.js
    $(graphDatas).each( function(){
        $data = $(this)[0];

        // create a node from the data and add it to the dictionary
        nodes[$data._id] = createNode($data.text, $data._id, $data.xPos, $data.yPos);

        // Store the link references and build links later once we have all the nodes
        $($data.links).each( function(){
            links[links.length] = {"source": $data._id, "target": $(this)[0]._id};
        });
    });
}

/**
 * Cretes the links between the nodes
 */
function createLinks() {
    // Now all the nodes should be available for creating the links
    $(links).each( function(){
        var source = nodes[$(this)[0].source];
        var target = nodes[$(this)[0].target];

        createAndAttachSegment(source, target);
    });
}
<|endoftext|>


<commit_before>/* Licensed under the MIT license:
 * http://www.opensource.org/licenses/mit-license.php
 * Copyright (c) 2010 Mr.doob, rhyolight, bebraw
 */
function brushes() {
    this.init();
}
brushes.prototype = {
    brushOptions: {'size': {'min': 1, 'max': 30, 'value': 1, 'pressure': false},
        'opacity': {'min': 0, 'max': 100, 'value': 50, 'pressure': true},
        'location': {}},
    init: function () {
        this.wacom = document.embeds["wacomPlugin"];

        if(!this.wacom.isWacom) {
            this.wacom = {'pressure': 1.0}; // proxy
        }

        this.brushes = {};

        for( var i = 0; i < BRUSHES.length; i++ ) {
            var brushName = BRUSHES[i];

            this.brushes[brushName] = eval("new " + brushName + '()');
        }

        this.selected = BRUSHES[0];
    },
    initHotkeys: function () {
        function toggleBrushValue(hotkey, attributeName) {
            shortcut.add(hotkey, function(e) {
                // TODO: figure out how to do this properly
                //$('#' + attributeName).button("option", "value", "true");
            });
        }

        function increaseBrushValue(hotkey, attributeName) {
            shortcut.add(hotkey, function(e) {
                var currentSize = $("#" + attributeName).slider("value");

                $("#" + attributeName).slider("value", currentSize + 1);
            });
        }

        function decreaseBrushValue(hotkey, attributeName) {
            shortcut.add(hotkey, function(e) {
                var currentSize = $("#" + attributeName).slider("value");

                $("#" + attributeName).slider("value", currentSize - 1);
            });
        }

        // TODO: add hotkeys for modes and shading too

        toggleBrushValue(TOGGLE_BRUSH_SIZE_PRESSURE, 'brushsizepressure');
        increaseBrushValue(INCREASE_BRUSH_SIZE, 'brushsize');
        decreaseBrushValue(DECREASE_BRUSH_SIZE, 'brushsize');
        increaseBrushValue(INCREASE_BRUSH_SIZE_JITTER, 'brushsizejitter');
        decreaseBrushValue(DECREASE_BRUSH_SIZE_JITTER, 'brushsizejitter');

        toggleBrushValue(TOGGLE_BRUSH_OPACITY_PRESSURE, 'brushopacitypressure');
        increaseBrushValue(INCREASE_BRUSH_OPACITY, 'brushopacity');
        decreaseBrushValue(DECREASE_BRUSH_OPACITY, 'brushopacity');
        increaseBrushValue(INCREASE_BRUSH_OPACITY_JITTER, 'brushopacityjitter');
        decreaseBrushValue(DECREASE_BRUSH_OPACITY_JITTER, 'brushopacityjitter');

        increaseBrushValue(INCREASE_BRUSH_LOCATION_JITTER, 'brushlocationjitter');
        decreaseBrushValue(DECREASE_BRUSH_LOCATION_JITTER, 'brushlocationjitter');
    },
    initUI: function (parentId) {
        var panelWidth = 220;
        setUpPanel(parentId, "Brushes", "left", panelWidth, 410);

        // set up brushes panel
        $("#brushesPanel").append('

' +
            '

');

        // modes
        $("#brushOptions").append('
 \
                <input type="radio" id="lightenMode" name="brushMode" value="lighter" />Lighten \
                <input type="radio" id="normalMode" name="brushMode" value="source-over" checked="checked" />Normal \
                <input type="radio" id="darkenMode" name="brushMode" value="darker" />Darken \

 \
        ');

        $("#brushMode").buttonset();

        // TODO: figure out a neat way to visualize different modes
        //$("#brushMode").buttonset().click( function() {
        //    panels['brushes'].renderBrushPreviews();
        //});

        // shading
        $("#brushOptions").append('
 \
                <input type="radio" id="currentShading" name="brushShading" value="current" checked="checked" />Current \
                <input type="radio" id="sameShading" name="brushShading" value="same" />Same \
                <input type="radio" id="allShading" name="brushShading" value="all" />All \

 \
        ');

        // labels
        $("#brushOptions").append('
 \

Attribute
 \

Value
 \

Jitter
 \

 \
        ');

        $("#brushShading").buttonset();

        for (var brushOptionName in this.brushOptions) {
            var brushOptionValue = this.brushOptions[brushOptionName];

            $("#brushOptions").append('
');

            var optionTitle = capitalizeFirstLetter(brushOptionName);
            var optionId = 'brush' + brushOptionName;
            if('pressure' in brushOptionValue) {
                var pressureId = optionId + 'pressure';

                $("#brushOptions").append('<input type="checkbox" id="' +
                    pressureId + '" />' + optionTitle + '');

                var pressureValue = brushOptionValue.pressure;

                if(pressureValue) {
                    $('#' + pressureId).attr('checked', 'checked');
                }

                $('#' + pressureId).button().click(
                    function () {
                        // XXX: hack! figure out a nicer way to pass option name!
                        var option = $(this).attr('id').replace('brush', '').replace('pressure', '');
                        var pressure = panels['brushes'].brushOptions[option].pressure;

                        panels['brushes'].brushOptions[option].pressure = !pressure;
                    }
                );
            }
            else {
                $("#brushOptions").append('
' +
                    optionTitle + '
');
            }

            $("#brushOptions").append('

');

            if('value' in brushOptionValue) {
                $("#" + optionId).slider({
                    range: "max",
                    min: brushOptionValue.min,
                    max: brushOptionValue.max,
                    value: brushOptionValue.value,
                    change: function(event, ui) { // XXX: hook up this handler with slide too (preview!)
                        // XXX: hack! figure out a nicer way to pass option name!
                        var option = $(this).attr('id').replace('brush', '');
                        panels['brushes'].brushOptions[option].value = ui.value;
                        panels['brushes'].renderBrushPreviews();
                    }
                });
            }

            var jitterAmountId = optionId + 'jitter';
            $("#brushOptions").append(
                '
 \

 \

 \
                '
            );

            this.brushOptions[brushOptionName]['jitter'] = {'enabled': false,
                'value': 0};

            $("#brushOptions").append('

');

            this.setUpJitter(jitterAmountId);
        }

        // XXX: figure out the width in a nicer way
        this.createBrushes(panelWidth / 2.8);
    },
    setUpJitter: function ( jitterAmountId ) {
        $("#" + jitterAmountId).slider({
            range: "max",
            min: 0,
            max: 50, // XXX: 100 for totally random, not really useful though
            value: 0,
            change: function(event, ui) { // XXX: hook up this handler with slide too (preview!)
                // XXX: hack! figure out a nicer way to pass option name!
                var option = $(this).attr('id').replace('jitter', '').replace('brush', '');
                panels['brushes'].brushOptions[option].jitter.value = ui.value;
                panels['brushes'].renderBrushPreviews();
            }
        });
    },
    createBrushes: function ( brushWidth ) {
        for (var i = 0; i < BRUSHES.length; i++) {
            var brushName = BRUSHES[i];
            var brushId = brushName; //XXX: use + 'Brush'; to avoid id clashes!
            var brushHeight = 40;

            $("#brushes").append('<canvas class="brush" id="' + brushId + '"' +
                ' style="height:' + brushHeight + 'px;width:' + brushWidth +
                'px"' +  '></canvas>');
            $('.brush:first').css('border', '1px dashed');

            $('#' + brushId).click(function() {
                panels['brushes'].selected = $(this).attr('id');

                // XXX: render bg as gray instead?
                $('.brush').css('border', '');
                $(this).css('border', '1px dashed');
                // XXX: render border in the canvas itself!
            });
        }

        this.renderBrushPreviews();
    },
    renderBrushPreviews: function () {
        for (var brushName in this.brushes) {
            var brush = this.brushes[brushName];

            this.renderBrushPreview(brushName, brush);
        }
    },
    renderBrushPreview: function (brushName, brush) {
        var brushCanvas = new ProxyCanvas(brushName); // XXX: add Canvas suffix?
        brushCanvas.fill([255, 255, 255]); // XXX: set background color using CSS instead

        if( SHOWPREVIEWIMAGES ) {
            var brushPainter = new Painter(brushCanvas, brush,
                panels['palette'].getColor());

            var canvasWidth = brushCanvas.width;
            var pad = 10;

            for (var x = pad; x < canvasWidth - pad; x += 5) {
                var y = Math.sin(5 * (x - pad) / (canvasWidth - pad) * 2 * Math.PI) *
                    (brushCanvas.height / 2 - pad * 2) + (brushCanvas.height / 2);

                var point = new Point(x, y);
                point = this.applyJitter(point);
                brushPainter.paint(point, this.getSize(), this.getOpacity(),
                    this.getMode());
            }
        }

        brushCanvas.text(brushName, 'black', '48px Segoe UI, Arial, sans-serif',
            10, brushCanvas.height / 2);
    },
    applyJitter: function ( point ) {
        var randomDirection = getRandomDirection(this.brushOptions.location.jitter.value);

        return point.add(randomDirection);
    },
    getSelected: function () {
        return this.brushes[this.selected];
    },
    getSize: function () {
        return this.getValueTemplate('size');
    },
    getOpacity: function () {
        return this.getValueTemplate('opacity') / 100;
    },
    getValueTemplate: function (valueName) {
        var value = this.brushOptions[valueName].value;

        var jitterValue = this.brushOptions[valueName].jitter.value / 100;
        var valueMax = this.brushOptions[valueName].max;
        var valueMin = this.brushOptions[valueName].min;
        var randomValue = Math.random() * ((value - valueMin) / (valueMax - valueMin));
        var jitterNeg = value * jitterValue * randomValue;

        value = value - jitterNeg;

        if(this.brushOptions[valueName].pressure) {
            return value * this.wacom.pressure;
        }

        return value;
    },
    getMode: function () {
        return $('#brushMode input:checked').val();
    },
    getShadingType: function () {
        return $('#brushShading input:checked').val();
    }
}
<commit_msg>Commented wacom out from JS code as well.<commit_after>/* Licensed under the MIT license:
 * http://www.opensource.org/licenses/mit-license.php
 * Copyright (c) 2010 Mr.doob, rhyolight, bebraw
 */
function brushes() {
    this.init();
}
brushes.prototype = {
    brushOptions: {'size': {'min': 1, 'max': 30, 'value': 1, 'pressure': false},
        'opacity': {'min': 0, 'max': 100, 'value': 50, 'pressure': true},
        'location': {}},
    init: function () {
        //this.wacom = document.embeds["wacomPlugin"];

        //if(!this.wacom.isWacom) {
        this.wacom = {'pressure': 1.0}; // proxy
        //}

        this.brushes = {};

        for( var i = 0; i < BRUSHES.length; i++ ) {
            var brushName = BRUSHES[i];

            this.brushes[brushName] = eval("new " + brushName + '()');
        }

        this.selected = BRUSHES[0];
    },
    initHotkeys: function () {
        function toggleBrushValue(hotkey, attributeName) {
            shortcut.add(hotkey, function(e) {
                // TODO: figure out how to do this properly
                //$('#' + attributeName).button("option", "value", "true");
            });
        }

        function increaseBrushValue(hotkey, attributeName) {
            shortcut.add(hotkey, function(e) {
                var currentSize = $("#" + attributeName).slider("value");

                $("#" + attributeName).slider("value", currentSize + 1);
            });
        }

        function decreaseBrushValue(hotkey, attributeName) {
            shortcut.add(hotkey, function(e) {
                var currentSize = $("#" + attributeName).slider("value");

                $("#" + attributeName).slider("value", currentSize - 1);
            });
        }

        // TODO: add hotkeys for modes and shading too

        toggleBrushValue(TOGGLE_BRUSH_SIZE_PRESSURE, 'brushsizepressure');
        increaseBrushValue(INCREASE_BRUSH_SIZE, 'brushsize');
        decreaseBrushValue(DECREASE_BRUSH_SIZE, 'brushsize');
        increaseBrushValue(INCREASE_BRUSH_SIZE_JITTER, 'brushsizejitter');
        decreaseBrushValue(DECREASE_BRUSH_SIZE_JITTER, 'brushsizejitter');

        toggleBrushValue(TOGGLE_BRUSH_OPACITY_PRESSURE, 'brushopacitypressure');
        increaseBrushValue(INCREASE_BRUSH_OPACITY, 'brushopacity');
        decreaseBrushValue(DECREASE_BRUSH_OPACITY, 'brushopacity');
        increaseBrushValue(INCREASE_BRUSH_OPACITY_JITTER, 'brushopacityjitter');
        decreaseBrushValue(DECREASE_BRUSH_OPACITY_JITTER, 'brushopacityjitter');

        increaseBrushValue(INCREASE_BRUSH_LOCATION_JITTER, 'brushlocationjitter');
        decreaseBrushValue(DECREASE_BRUSH_LOCATION_JITTER, 'brushlocationjitter');
    },
    initUI: function (parentId) {
        var panelWidth = 220;
        setUpPanel(parentId, "Brushes", "left", panelWidth, 410);

        // set up brushes panel
        $("#brushesPanel").append('

' +
            '

');

        // modes
        $("#brushOptions").append('
 \
                <input type="radio" id="lightenMode" name="brushMode" value="lighter" />Lighten \
                <input type="radio" id="normalMode" name="brushMode" value="source-over" checked="checked" />Normal \
                <input type="radio" id="darkenMode" name="brushMode" value="darker" />Darken \

 \
        ');

        $("#brushMode").buttonset();

        // TODO: figure out a neat way to visualize different modes
        //$("#brushMode").buttonset().click( function() {
        //    panels['brushes'].renderBrushPreviews();
        //});

        // shading
        $("#brushOptions").append('
 \
                <input type="radio" id="currentShading" name="brushShading" value="current" checked="checked" />Current \
                <input type="radio" id="sameShading" name="brushShading" value="same" />Same \
                <input type="radio" id="allShading" name="brushShading" value="all" />All \

 \
        ');

        // labels
        $("#brushOptions").append('
 \

Attribute
 \

Value
 \

Jitter
 \

 \
        ');

        $("#brushShading").buttonset();

        for (var brushOptionName in this.brushOptions) {
            var brushOptionValue = this.brushOptions[brushOptionName];

            $("#brushOptions").append('
');

            var optionTitle = capitalizeFirstLetter(brushOptionName);
            var optionId = 'brush' + brushOptionName;
            if('pressure' in brushOptionValue) {
                var pressureId = optionId + 'pressure';

                $("#brushOptions").append('<input type="checkbox" id="' +
                    pressureId + '" />' + optionTitle + '');

                var pressureValue = brushOptionValue.pressure;

                if(pressureValue) {
                    $('#' + pressureId).attr('checked', 'checked');
                }

                $('#' + pressureId).button().click(
                    function () {
                        // XXX: hack! figure out a nicer way to pass option name!
                        var option = $(this).attr('id').replace('brush', '').replace('pressure', '');
                        var pressure = panels['brushes'].brushOptions[option].pressure;

                        panels['brushes'].brushOptions[option].pressure = !pressure;
                    }
                );
            }
            else {
                $("#brushOptions").append('
' +
                    optionTitle + '
');
            }

            $("#brushOptions").append('

');

            if('value' in brushOptionValue) {
                $("#" + optionId).slider({
                    range: "max",
                    min: brushOptionValue.min,
                    max: brushOptionValue.max,
                    value: brushOptionValue.value,
                    change: function(event, ui) { // XXX: hook up this handler with slide too (preview!)
                        // XXX: hack! figure out a nicer way to pass option name!
                        var option = $(this).attr('id').replace('brush', '');
                        panels['brushes'].brushOptions[option].value = ui.value;
                        panels['brushes'].renderBrushPreviews();
                    }
                });
            }

            var jitterAmountId = optionId + 'jitter';
            $("#brushOptions").append(
                '
 \

 \

 \
                '
            );

            this.brushOptions[brushOptionName]['jitter'] = {'enabled': false,
                'value': 0};

            $("#brushOptions").append('

');

            this.setUpJitter(jitterAmountId);
        }

        // XXX: figure out the width in a nicer way
        this.createBrushes(panelWidth / 2.8);
    },
    setUpJitter: function ( jitterAmountId ) {
        $("#" + jitterAmountId).slider({
            range: "max",
            min: 0,
            max: 50, // XXX: 100 for totally random, not really useful though
            value: 0,
            change: function(event, ui) { // XXX: hook up this handler with slide too (preview!)
                // XXX: hack! figure out a nicer way to pass option name!
                var option = $(this).attr('id').replace('jitter', '').replace('brush', '');
                panels['brushes'].brushOptions[option].jitter.value = ui.value;
                panels['brushes'].renderBrushPreviews();
            }
        });
    },
    createBrushes: function ( brushWidth ) {
        for (var i = 0; i < BRUSHES.length; i++) {
            var brushName = BRUSHES[i];
            var brushId = brushName; //XXX: use + 'Brush'; to avoid id clashes!
            var brushHeight = 40;

            $("#brushes").append('<canvas class="brush" id="' + brushId + '"' +
                ' style="height:' + brushHeight + 'px;width:' + brushWidth +
                'px"' +  '></canvas>');
            $('.brush:first').css('border', '1px dashed');

            $('#' + brushId).click(function() {
                panels['brushes'].selected = $(this).attr('id');

                // XXX: render bg as gray instead?
                $('.brush').css('border', '');
                $(this).css('border', '1px dashed');
                // XXX: render border in the canvas itself!
            });
        }

        this.renderBrushPreviews();
    },
    renderBrushPreviews: function () {
        for (var brushName in this.brushes) {
            var brush = this.brushes[brushName];

            this.renderBrushPreview(brushName, brush);
        }
    },
    renderBrushPreview: function (brushName, brush) {
        var brushCanvas = new ProxyCanvas(brushName); // XXX: add Canvas suffix?
        brushCanvas.fill([255, 255, 255]); // XXX: set background color using CSS instead

        if( SHOWPREVIEWIMAGES ) {
            var brushPainter = new Painter(brushCanvas, brush,
                panels['palette'].getColor());

            var canvasWidth = brushCanvas.width;
            var pad = 10;

            for (var x = pad; x < canvasWidth - pad; x += 5) {
                var y = Math.sin(5 * (x - pad) / (canvasWidth - pad) * 2 * Math.PI) *
                    (brushCanvas.height / 2 - pad * 2) + (brushCanvas.height / 2);

                var point = new Point(x, y);
                point = this.applyJitter(point);
                brushPainter.paint(point, this.getSize(), this.getOpacity(),
                    this.getMode());
            }
        }

        brushCanvas.text(brushName, 'black', '48px Segoe UI, Arial, sans-serif',
            10, brushCanvas.height / 2);
    },
    applyJitter: function ( point ) {
        var randomDirection = getRandomDirection(this.brushOptions.location.jitter.value);

        return point.add(randomDirection);
    },
    getSelected: function () {
        return this.brushes[this.selected];
    },
    getSize: function () {
        return this.getValueTemplate('size');
    },
    getOpacity: function () {
        return this.getValueTemplate('opacity') / 100;
    },
    getValueTemplate: function (valueName) {
        var value = this.brushOptions[valueName].value;

        var jitterValue = this.brushOptions[valueName].jitter.value / 100;
        var valueMax = this.brushOptions[valueName].max;
        var valueMin = this.brushOptions[valueName].min;
        var randomValue = Math.random() * ((value - valueMin) / (valueMax - valueMin));
        var jitterNeg = value * jitterValue * randomValue;

        value = value - jitterNeg;

        if(this.brushOptions[valueName].pressure) {
            return value * this.wacom.pressure;
        }

        return value;
    },
    getMode: function () {
        return $('#brushMode input:checked').val();
    },
    getShadingType: function () {
        return $('#brushShading input:checked').val();
    }
}
<|endoftext|>