<commit_before>import { merge } from './updates.js';
import * as symbols from './symbols.js';
import * as template from './template.js';
import SlotContentMixin from './SlotContentMixin.js';
import WrappedStandardElement from './WrappedStandardElement.js';

const Base =
  SlotContentMixin(
    WrappedStandardElement.wrap('textarea')
  );

/**
 * Text area that grows to accommodate its content
 *
 * [This text area grows as you add text](/demos/autoSizeTextarea.html)
 *
 * This text input component is useful in situations where you want to ask the
 * user to enter as much text as they want, but don't want to take up a lot of
 * room on the page.
 *
 * *Note:* This component uses [WrappedStandardElement](WrappedStandardElement)
 * to wrap a standard `<textarea>` element. This allows it to provide all
 * standard `HTMLTextAreaElement` properties, methods, and events, in addition
 * to those specifically listed in the `AutoSizeTextarea` API.
 *
 * @inherits WrappedStandardElement
 * @mixes SlotContentMixin
 */
class AutoSizeTextarea extends Base {

  componentDidMount() {
    if (super.componentDidMount) { super.componentDidMount(); }

    this[symbols.contentSlot].addEventListener('slotchange', () => {
      this.setState({ valueTracksContent: true });
    });

    // The following jsDoc comment doesn't directly apply to the statement which
    // follows, but is placed there because the comment has to go somewhere to
    // be visible to jsDoc, and the statement is at tangentially related.
    /**
     * Raised when the user changes the element's text content.
     *
     * This is the standard `input` event; the component does not do any work to
     * raise it. It is documented here to let people know it is available to
     * detect when the user edits the content.
     *
     * @event input
     */
    this.$.inner.addEventListener('input', () => {
      this[symbols.raiseChangeEvents] = true;
      this.setState({ valueTracksContent: false });
      /** @type {any} */
      const inner = this.$.inner;
      this.setState({
        value: inner.value
      });
      this[symbols.raiseChangeEvents] = false;
    });

    // For auto-sizing to work, we need the text copy to have the same border,
    // padding, and other relevant characteristics as the original text area.
    // Since those aspects are affected by CSS, we have to wait until the
    // element is in the document before we can update the text copy.
    const textareaStyle = getComputedStyle(this.$.inner);
    const lineHeight = this.$.extraSpace.clientHeight;
    this.setState({
      copyStyle: {
        'border-bottom-style': textareaStyle.borderBottomStyle,
        'border-bottom-width': textareaStyle.borderBottomWidth,
        'border-left-style': textareaStyle.borderLeftStyle,
        'border-left-width': textareaStyle.borderLeftWidth,
        'border-right-style': textareaStyle.borderRightStyle,
        'border-right-width': textareaStyle.borderRightWidth,
        'border-top-style': textareaStyle.borderTopStyle,
        'border-top-width': textareaStyle.borderTopWidth,
        'padding-bottom': textareaStyle.paddingBottom,
        'padding-left': textareaStyle.paddingLeft,
        'padding-right': textareaStyle.paddingRight,
        'padding-top': textareaStyle.paddingTop
      },
      lineHeight
    });
  }

  get defaultState() {
    return Object.assign(super.defaultState, {
      minimumRows: 1,
      value: null,
      valueTracksContent: true
    });
  }

  /**
   * Determines the minimum number of rows shown. This is similar to the rows
   * attribute on a standard textarea, but because this element can grow, is
   * expressed as a minimum rather than a fixed number.
   *
   * By default, this property is 1, so when empty, the text area will be a
   * single line tall. That's efficient in terms of the space it consumes, but
   * until the user interacts with the element, they may not realize they can
   * enter multiple lines of text. Setting the property to a value higher than 1
   * will signal to the user that they can enter multiple lines of a text.
   *
   * By setting this property, you can also communicate to the user some sense
   * of how much text you're expecting them to provide. For example, on a
   * feedback form, asking the user to enter their feedback in a single-line
   * text box implies you don't really want them to enter much text — even if
   * the text box will grow when they type. By setting this to a value like,
   * say, 10 rows, you can signal that you're fully expecting them to enter more
   * text.
   *
   * @type {number}
   * @default 1
   */
  get minimumRows() {
    return this.state.minimumRows;
  }
  set minimumRows(minimumRows) {
    const parsed = Number(minimumRows);
    if (!isNaN(parsed)) {
      this.setState({
        minimumRows: parsed
      });
    }
  }

  /*
   * Things to note about this component's DOM structure:
   *
   * * The component works by copying the text to an invisible element which
   *   will automatically grow in size; the expanding copy will expand the
   *   container, which in turn will vertically stretch the text area to match.
   *
   * * The invisible copyContainer contains an extra space element that ensures
   *   that, even if the last line of the textarea is blank, there will be
   *   something in the line that forces the text copy to grow by a line.
   *
   * * The inner text element has box-sizing: border-box, but the copy has
   *   content-box. The latter makes it easier for us to set the minimum height
   *   of the copy by just setting the height of the content, without having to
   *   account for borders and padding.
   *
   * * We put the slot inside an element that's hidden. This gives us easy
   *   access to assigned content so we can copy into the textarea, while
   *   ensuring the original content doesn't show up directly.
   */
  get [symbols.template]() {
    return template.html`

        <textarea id="inner"></textarea>

        <slot></slot>

    `;
  }

  get updates() {

    const value = this.value;

    let copyStyle = this.state.copyStyle;
    if (copyStyle) {
      const minHeight = this.state.minimumRows * this.state.lineHeight;
      copyStyle = Object.assign({}, copyStyle, {
        'min-height': `${minHeight}px`
      });
    }

    return merge(super.updates, {
      $: {
        copyContainer: {
          style: copyStyle
        },
        inner: {
          value
        },
        textCopy: {
          textContent: value
        }
      }
    });
  }

  /**
   * The text currently shown in the textarea.
   *
   * Note that the text shown in the textarea can also be updated by changing
   * the element's innerHTML/textContent. However, if the value property is
   * explicitly set, that will override the innerHTML/textContent.
   *
   * @type {string}
   */
  get value() {
    return this.state.valueTracksContent ?
      getTextFromContent(this.state.content) :
      this.state.value;
  }
  set value(value) {
    this.setState({
      value,
      valueTracksContent: false
    });
  }

}

// Return the text represented by the given content nodes.
function getTextFromContent(contentNodes) {
  if (contentNodes === null) {
    return '';
  }
  const texts = [...contentNodes].map(node => node.textContent);
  const text = texts.join('').trim();
  return unescapeHtml(text);
}

function unescapeHtml(html) {
  return html
    .replace(/&/g, '&')
    .replace(/</g, '<')
    .replace(/>/g, ">")
    .replace(/"/g, '"')
    .replace(/'/g, '\'');
}

customElements.define('elix-auto-size-textarea', AutoSizeTextarea);
export default AutoSizeTextarea;
<commit_msg>Port AutoSizeTextarea<commit_after>import * as symbols from './symbols.js';
import * as template from './template.js';
import SlotContentMixin from './SlotContentMixin.js';
import WrappedStandardElement from './WrappedStandardElement.js';

const Base =
  SlotContentMixin(
    WrappedStandardElement.wrap('textarea')
  );

/**
 * Text area that grows to accommodate its content
 *
 * [This text area grows as you add text](/demos/autoSizeTextarea.html)
 *
 * This text input component is useful in situations where you want to ask the
 * user to enter as much text as they want, but don't want to take up a lot of
 * room on the page.
 *
 * *Note:* This component uses [WrappedStandardElement](WrappedStandardElement)
 * to wrap a standard `<textarea>` element. This allows it to provide all
 * standard `HTMLTextAreaElement` properties, methods, and events, in addition
 * to those specifically listed in the `AutoSizeTextarea` API.
 *
 * @inherits WrappedStandardElement
 * @mixes SlotContentMixin
 */
class AutoSizeTextarea extends Base {

  componentDidMount() {
    if (super.componentDidMount) { super.componentDidMount(); }

    this[symbols.contentSlot].addEventListener('slotchange', () => {
      this.setState({ valueTracksContent: true });
    });

    // The following jsDoc comment doesn't directly apply to the statement which
    // follows, but is placed there because the comment has to go somewhere to
    // be visible to jsDoc, and the statement is at tangentially related.
    /**
     * Raised when the user changes the element's text content.
     *
     * This is the standard `input` event; the component does not do any work to
     * raise it. It is documented here to let people know it is available to
     * detect when the user edits the content.
     *
     * @event input
     */
    this.$.inner.addEventListener('input', () => {
      this[symbols.raiseChangeEvents] = true;
      this.setState({ valueTracksContent: false });
      /** @type {any} */
      const inner = this.$.inner;
      this.setState({
        value: inner.value
      });
      this[symbols.raiseChangeEvents] = false;
    });

    // For auto-sizing to work, we need the text copy to have the same border,
    // padding, and other relevant characteristics as the original text area.
    // Since those aspects are affected by CSS, we have to wait until the
    // element is in the document before we can update the text copy.
    const textareaStyle = getComputedStyle(this.$.inner);
    const lineHeight = this.$.extraSpace.clientHeight;
    this.setState({
      copyStyle: {
        'border-bottom-style': textareaStyle.borderBottomStyle,
        'border-bottom-width': textareaStyle.borderBottomWidth,
        'border-left-style': textareaStyle.borderLeftStyle,
        'border-left-width': textareaStyle.borderLeftWidth,
        'border-right-style': textareaStyle.borderRightStyle,
        'border-right-width': textareaStyle.borderRightWidth,
        'border-top-style': textareaStyle.borderTopStyle,
        'border-top-width': textareaStyle.borderTopWidth,
        'padding-bottom': textareaStyle.paddingBottom,
        'padding-left': textareaStyle.paddingLeft,
        'padding-right': textareaStyle.paddingRight,
        'padding-top': textareaStyle.paddingTop
      },
      lineHeight
    });
  }

  get defaultState() {
    return Object.assign(super.defaultState, {
      minimumRows: 1,
      value: null,
      valueTracksContent: true
    });
  }

  /**
   * Determines the minimum number of rows shown. This is similar to the rows
   * attribute on a standard textarea, but because this element can grow, is
   * expressed as a minimum rather than a fixed number.
   *
   * By default, this property is 1, so when empty, the text area will be a
   * single line tall. That's efficient in terms of the space it consumes, but
   * until the user interacts with the element, they may not realize they can
   * enter multiple lines of text. Setting the property to a value higher than 1
   * will signal to the user that they can enter multiple lines of a text.
   *
   * By setting this property, you can also communicate to the user some sense
   * of how much text you're expecting them to provide. For example, on a
   * feedback form, asking the user to enter their feedback in a single-line
   * text box implies you don't really want them to enter much text — even if
   * the text box will grow when they type. By setting this to a value like,
   * say, 10 rows, you can signal that you're fully expecting them to enter more
   * text.
   *
   * @type {number}
   * @default 1
   */
  get minimumRows() {
    return this.state.minimumRows;
  }
  set minimumRows(minimumRows) {
    const parsed = Number(minimumRows);
    if (!isNaN(parsed)) {
      this.setState({
        minimumRows: parsed
      });
    }
  }

  [symbols.render](state, changed) {
    super[symbols.render](state, changed);
    if (changed.copyStyle) {
      Object.assign(this.$.copyContainer.style, state.copyStyle);
    }
    if (changed.lineHeight || changed.minimumRows && state.lineHeight != null) {
      const minHeight = state.minimumRows * state.lineHeight;
      this.$.copyContainer.style.minHeight = `${minHeight}px`;
    }
    if (changed.value) {
      const value = state.value;
      this.$.inner.value = value;
      this.$.textCopy.textContent = value;
    }
  }

  /*
   * Things to note about this component's DOM structure:
   *
   * * The component works by copying the text to an invisible element which
   *   will automatically grow in size; the expanding copy will expand the
   *   container, which in turn will vertically stretch the text area to match.
   *
   * * The invisible copyContainer contains an extra space element that ensures
   *   that, even if the last line of the textarea is blank, there will be
   *   something in the line that forces the text copy to grow by a line.
   *
   * * The inner text element has box-sizing: border-box, but the copy has
   *   content-box. The latter makes it easier for us to set the minimum height
   *   of the copy by just setting the height of the content, without having to
   *   account for borders and padding.
   *
   * * We put the slot inside an element that's hidden. This gives us easy
   *   access to assigned content so we can copy into the textarea, while
   *   ensuring the original content doesn't show up directly.
   */
  get [symbols.template]() {
    return template.html`

        <textarea id="inner"></textarea>

        <slot></slot>

    `;
  }

  /**
   * The text currently shown in the textarea.
   *
   * Note that the text shown in the textarea can also be updated by changing
   * the element's innerHTML/textContent. However, if the value property is
   * explicitly set, that will override the innerHTML/textContent.
   *
   * @type {string}
   */
  get value() {
    return this.state.valueTracksContent ?
      getTextFromContent(this.state.content) :
      this.state.value;
  }
  set value(value) {
    this.setState({
      value,
      valueTracksContent: false
    });
  }

}

// Return the text represented by the given content nodes.
function getTextFromContent(contentNodes) {
  if (contentNodes === null) {
    return '';
  }
  const texts = [...contentNodes].map(node => node.textContent);
  const text = texts.join('').trim();
  return unescapeHtml(text);
}

function unescapeHtml(html) {
  return html
    .replace(/&/g, '&')
    .replace(/</g, '<')
    .replace(/>/g, ">")
    .replace(/"/g, '"')
    .replace(/'/g, '\'');
}

customElements.define('elix-auto-size-textarea', AutoSizeTextarea);
export default AutoSizeTextarea;
<|endoftext|>


<commit_before>import * as React from 'react';

export default function component(
  tag,
  { displayName, className, interpolations }
) {
  const Result = function(props) {
    const next = { className };

    if (interpolations) {
      const style = {};

      Object.keys(interpolations).forEach(name => {
        const value = interpolations[name];
        style[`--${name}`] = typeof value === 'function' ? value(props) : value;
      });
    }

    return React.createElement(tag, next);
  };

  Result.displayName = displayName;

  return Result;
}
<commit_msg>fix: actually pass the styles down<commit_after>import * as React from 'react';

export default function component(
  tag,
  { displayName, className, interpolations }
) {
  const Result = function(props) {
    const next = Object.assign({}, props, {
      className: props.className
        ? `${className} ${props.className}`
        : className,
    });

    if (interpolations) {
      const style = {};

      Object.keys(interpolations).forEach(name => {
        const value = interpolations[name];
        style[`--${name}`] = typeof value === 'function' ? value(props) : value;
      });

      next.style = Object.assign(style, next.style);
    }

    return React.createElement(tag, next);
  };

  Result.displayName = displayName;

  return Result;
}
<|endoftext|>


<commit_before>import React from 'react';

export default class PlantListAddBox extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            name: ''
        };
    }

    static get propTypes() {
        return {
            onAdd: React.PropTypes.func.isRequired
        };
    }

    handleAdd() {
        const addInput = this.refs.addInput;
        const name = addInput.value.trim();

        if (name.length < 2) {
            addInput.setCustomValidity('Name must be at least two characters');
        } else {
            addInput.setCustomValidity('');
        }

        if (addInput.checkValidity()) {
            this.props.onAdd(name);
            this.setState({
                name: ''
            });
        }
    }

    handleChange(event) {
        this.setState({
            name: event.target.value
        });
    }

    render() {
        return (

                <input
                    type="text"
                    placeholder="Plant name"
                    size="12"
                    maxLength="100"
                    value={this.state.name}
                    ref="addInput"
                    onChange={this.handleChange.bind(this)} />
                <button
                    type="button"
                    onClick={this.handleAdd.bind(this)}>
                    Add
                </button>

        );
    }
}<commit_msg>Eliminate state from `PlantListAddBox`<commit_after>import React from 'react';

export default class PlantListAddBox extends React.Component {
    static get propTypes() {
        return {
            onAdd: React.PropTypes.func.isRequired
        };
    }

    handleAdd() {
        const addInput = this.refs.addInput;
        const name = addInput.value.trim();

        if (name.length < 2) {
            addInput.setCustomValidity('Name must be at least two characters');
        } else {
            addInput.setCustomValidity('');
        }

        if (addInput.checkValidity()) {
            this.props.onAdd(name);
            addInput.value = '';
        }
    }

    render() {
        return (

                <input
                    type="text"
                    placeholder="Plant name"
                    size="12"
                    maxLength="100"
                    ref="addInput" />
                <button
                    type="button"
                    onClick={this.handleAdd.bind(this)}>
                    Add
                </button>

        );
    }
}<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import FormGroup from 'react-bootstrap/lib/FormGroup';
import FormControl from 'react-bootstrap/lib/FormControl';
import ControlLabel from 'react-bootstrap/lib/ControlLabel';
import Table from 'react-bootstrap/lib/Table';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import s from './Movies.css';

var MovieList = React.createClass({

  getInitialState: function(){
    return { searchString: '' };
  },

  handleChange: function(e){
    this.setState({searchString:e.target.value});
  },

  handleClick: function (obj) {
    this.props.handleSelect(obj);
  },

  render: function() {

    var movies = this.props.items,
      searchString = this.state.searchString.trim().toLowerCase();

    if(searchString.length > 0){

      movies = movies.filter(function(l){
        return l.TitleName.toLowerCase().match( searchString );
      });
    }

    return

Find Movies

      <form>
        <FormGroup>
          <ControlLabel>Search by title</ControlLabel>
          <FormControl
            type="text"
            value={this.state.searchString}
            placeholder="Type here"
            onChange={this.handleChange}
          />
          <FormControl.Feedback />
        </FormGroup>
      </form>

          Title
          Released

        { movies.map(function(m, index){
          let movieItemClass = s.movieItem;
          {if (this.props.selectedMovie === m) {movieItemClass = s.selected}}
          var boundClick = this.handleClick.bind(this, m);
          return
{m.TitleName}	{m.ReleaseYear}
}, this) }

;

  }
});

export default withStyles(s)(MovieList);
<commit_msg>fixing formatting<commit_after>import React, { PropTypes } from 'react';
import FormGroup from 'react-bootstrap/lib/FormGroup';
import FormControl from 'react-bootstrap/lib/FormControl';
import ControlLabel from 'react-bootstrap/lib/ControlLabel';
import Table from 'react-bootstrap/lib/Table';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import s from './Movies.css';

var MovieList = React.createClass({

  getInitialState: function(){
    return { searchString: '' };
  },

  handleChange: function(e){
    this.setState({searchString:e.target.value});
  },

  handleClick: function (obj) {
    this.props.handleSelect(obj);
  },

  render: function() {

    var movies = this.props.items,
      searchString = this.state.searchString.trim().toLowerCase();

    if(searchString.length > 0){

      movies = movies.filter(function(l){
        return l.TitleName.toLowerCase().match( searchString );
      });
    }

    return (

Find Movies

        <form>
          <FormGroup>
            <ControlLabel>Search by title</ControlLabel>
            <FormControl
              type="text"
              value={this.state.searchString}
              placeholder="Type here"
              onChange={this.handleChange}
            />
            <FormControl.Feedback />
          </FormGroup>
        </form>

            Title
            Released

          { movies.map(function(m, index){
            let movieItemClass = s.movieItem;
            {if (this.props.selectedMovie === m) {movieItemClass = s.selected}}
            var boundClick = this.handleClick.bind(this, m);
            return
{m.TitleName}	{m.ReleaseYear}
}, this) }

    );

  }
});

export default withStyles(s)(MovieList);
<|endoftext|>


<commit_before>require(['config'], function() {
    require([
        '$',
        'modal-center',
        'sheet-top',
        'sheet-right',
        'sheet-left',
        'sheet-bottom',
        'pinny'
    ],
    function(
        $,
        modalCenter,
        sheetTop,
        sheetRight,
        sheetLeft,
        sheetBottom
    ) {
        var $modalCenter = $('#modalCenterPinny').pinny({
            position: modalCenter,
            coverage: '90%'
        });

        $('#modalCenter').on('click', function() {
            $modalCenter.pinny('toggle');
        });

        var $sheetTop = $('#sheetTopPinny').pinny({
            position: sheetTop,
            coverage: '80%',
            shade: {
                duration: 0
            }
        });

        $('#sheetTop').on('click', function() {
            $sheetTop.pinny('toggle');
        });

        var $sheetRight = $('#sheetRightPinny').pinny({
            position: sheetRight,
            coverage: '80%',
            shade: {
                duration: 0
            }
        });

        $('#sheetRight').on('click', function() {
            $sheetRight.pinny('toggle');
        });

        var $sheetLeft = $('#sheetLeftPinny').pinny({
            position: sheetLeft,
            coverage: '80%',
            shade: {
                duration: 0
            }
        });

        $('#sheetLeft').on('click', function() {
            $sheetLeft.pinny('toggle');
        });

        var $sheetBottom = $('#sheetBottomPinny').pinny({
            position: sheetBottom,
            coverage: '80%',
            shade: {
                duration: 0
            }
        });

        $('#sheetBottom').on('click', function() {
            $sheetBottom.pinny('toggle');
        });

        // Enable active states
        $(document).on('touchstart', function() {});
    });
});
<commit_msg>Remove accidental shade option commit<commit_after>require(['config'], function() {
    require([
        '$',
        'modal-center',
        'sheet-top',
        'sheet-right',
        'sheet-left',
        'sheet-bottom',
        'pinny'
    ],
    function(
        $,
        modalCenter,
        sheetTop,
        sheetRight,
        sheetLeft,
        sheetBottom
    ) {
        var $modalCenter = $('#modalCenterPinny').pinny({
            position: modalCenter,
            coverage: '90%'
        });

        $('#modalCenter').on('click', function() {
            $modalCenter.pinny('toggle');
        });

        var $sheetTop = $('#sheetTopPinny').pinny({
            position: sheetTop,
            coverage: '80%',
            shade: {
                duration: 200
            }
        });

        $('#sheetTop').on('click', function() {
            $sheetTop.pinny('toggle');
        });

        var $sheetRight = $('#sheetRightPinny').pinny({
            position: sheetRight,
            coverage: '80%'
        });

        $('#sheetRight').on('click', function() {
            $sheetRight.pinny('toggle');
        });

        var $sheetLeft = $('#sheetLeftPinny').pinny({
            position: sheetLeft,
            coverage: '80%'
        });

        $('#sheetLeft').on('click', function() {
            $sheetLeft.pinny('toggle');
        });

        var $sheetBottom = $('#sheetBottomPinny').pinny({
            position: sheetBottom,
            coverage: '80%'
        });

        $('#sheetBottom').on('click', function() {
            $sheetBottom.pinny('toggle');
        });

        // Enable active states
        $(document).on('touchstart', function() {});
    });
});
<|endoftext|>


<commit_before>'use strict';

// Production specific configuration
// =================================
module.exports = {
  // Server IP
  ip:       process.env.OPENSHIFT_NODEJS_IP ||
            process.env.IP ||
            undefined,

  // Server port
  port:     process.env.OPENSHIFT_NODEJS_PORT ||
            process.env.PORT ||
            8080,

  // Server Address
  addr:     process.env.SERVER_ADDR ||
            "",

  // Location of image uploads
  imageUploadPath: '/opt/uploads/images/',

  // MongoDB connection options
  mongo: {
    uri:    process.env.MONGOLAB_URI ||
            process.env.MONGOHQ_URL ||
            process.env.OPENSHIFT_MONGODB_DB_URL+process.env.OPENSHIFT_APP_NAME ||
            'mongodb://localhost/observatory3'
  }
};
<commit_msg>Add domain to config<commit_after>'use strict';

// Production specific configuration
// =================================
module.exports = {
  // Server IP
  ip:       process.env.OPENSHIFT_NODEJS_IP ||
            process.env.IP ||
            undefined,

  // Server port
  port:     process.env.OPENSHIFT_NODEJS_PORT ||
            process.env.PORT ||
            8080,

  // Server Address
  addr:     process.env.SERVER_ADDRESS ||
            "https://rcos.io",

  // Location of image uploads
  imageUploadPath: '/opt/uploads/images/',

  // MongoDB connection options
  mongo: {
    uri:    process.env.MONGOLAB_URI ||
            process.env.MONGOHQ_URL ||
            process.env.OPENSHIFT_MONGODB_DB_URL+process.env.OPENSHIFT_APP_NAME ||
            'mongodb://localhost/observatory3'
  }
};
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.Component.extend({
  tagNmae: 'div',
  classNames: ['rating-panel'],

  rating: 0,
  maxRating: 5,
  item: null,
  setAction: '',

  stars: Ember.computed('rating', 'maxRating', function() {
    var fullStars = this.starRange(1, this.get('rating'), 'full');
    var emptyStars = this.starRange(this.get('rating') + 1, this.get('maxRating'), 'empty');
    return fullStars.concat(emptyStars);
  }),

  starRange: function(start, end, type) {
    var starsData = [];
    for (var i = start; i <= end; i++) {
      starsData.push({ rating: i, full: type === 'full' });
    }
    return starsData;
  },

});
<commit_msg>simple action to set star rating but not the way to do it<commit_after>import Ember from 'ember';

export default Ember.Component.extend({
  tagNmae: 'div',
  classNames: ['rating-panel'],

  rating: 0,
  maxRating: 5,
  item: null,
  setAction: '',

  stars: Ember.computed('rating', 'maxRating', function() {
    var fullStars = this.starRange(1, this.get('rating'), 'full');
    var emptyStars = this.starRange(this.get('rating') + 1, this.get('maxRating'), 'empty');
    return fullStars.concat(emptyStars);
  }),

  starRange: function(start, end, type) {
    var starsData = [];
    for (var i = start; i <= end; i++) {
      starsData.push({ rating: i, full: type === 'full' });
    }
    return starsData;
  },

  actions: {
    set: function(newRating) {
      this.get('item').set('rating', newRating);
    }
  }
});
<|endoftext|>


<commit_before>define([
	"dojo/_base/declare","dijit/layout/BorderContainer","dojo/on",
	"dojo/dom-class","dijit/layout/ContentPane","dojo/dom-construct",
	"../PageGrid","../formatter","../../WorkspaceManager","dojo/_base/lang",
	"dojo/dom-attr"
], function(
	declare, BorderContainer, on,
	domClass,ContentPane,domConstruct,
	Grid,formatter,WorkspaceManager,lang,
	domAttr
){
	return declare([BorderContainer], {
		"baseClass": "ExperimentViewer",
		"disabled":false,
		"query": null,
		data: null,
		_setDataAttr: function(data){
			this.data = data;
			console.log("job result viewer data: ", data);
			var paths = this.data.autoMeta.output_files.map(function(o){
				return o[0];
			});

			WorkspaceManager.getObjects(paths,true).then(lang.hitch(this, function(objs){
				this._resultObjects = objs;
				console.log("got objects: ", objs);
				this.refresh();
			}));

		},
		refresh: function(){
			if (this.data) {
				if (this.data.autoMeta && this.data.autoMeta.app){
					this.viewHeader.set('content', this.data.autoMeta.app.id + " Job Result");
				}
				var output = ["
"];

				if (this.data.userMeta) {
					Object.keys(this.data.userMeta).forEach(function(prop){
						output.push("
" + prop + ": " + this.data.userMeta[prop] + "
");
					},this);
				}

				if (this.data.autoMeta) {
					Object.keys(this.data.autoMeta).forEach(function(prop){
						if (prop=="output_files") { return; }
						if (prop=="app") { return; }
						if (prop=="job_output") { return; }
						if (prop=="hostname") { return; }

						output.push("
" +prop + ": " + this.data.autoMeta[prop] + "
");
					},this);
				}
				if (this._resultObjects) {
					output.push("
Result Files
 ");
					output.push('

');
					this._resultObjects.forEach(function(obj){
						output.push("
");
						output.push('	');
						output.push("" + obj.name + "	");
						output.push("" + obj.type+ "	");
						output.push("" + obj.size + "	");
						Object.keys(obj.autoMeta).forEach(function(prop){
							if (!obj.autoMeta[prop]) { return; }
							output.push("");
							output.push(prop + ": " + obj.autoMeta[prop]);
							output.push("	");
						});
						output.push("
");
					});
					output.push("

");
				}

				output.push("
");
				this.viewer.set("content", output.join(""));
			}
		},
		startup: function(){
			if (this._started) {return;}
			this.inherited(arguments);
			this.viewHeader = new ContentPane({content: "Loading Job Results...", region: "top"});
			this.viewer= new ContentPane({content: "", region: "center"});
			this.addChild(this.viewHeader);
			this.addChild(this.viewer);

			this.on("i:click", function(evt){
				var rel = domAttr.get(evt.target,'rel');
				if (rel) {
					WorkspaceManager.downloadFile(rel);
				}else{
					console.warn("link not found: ", rel);
				}
			});
		}
	});
});
<commit_msg>formatting job results<commit_after>define([
	"dojo/_base/declare","dijit/layout/BorderContainer","dojo/on",
	"dojo/dom-class","dijit/layout/ContentPane","dojo/dom-construct",
	"../PageGrid","../formatter","../../WorkspaceManager","dojo/_base/lang",
	"dojo/dom-attr"
], function(
	declare, BorderContainer, on,
	domClass,ContentPane,domConstruct,
	Grid,formatter,WorkspaceManager,lang,
	domAttr
){
	return declare([BorderContainer], {
		"baseClass": "ExperimentViewer",
		"disabled":false,
		"query": null,
		data: null,
		_resultType: null,
		_metaOut: {"start_time":{"label":"Start time"},"elapsed_time":{"label":"Run time"},"end_time":{"label":"End time"},"parameters":{"label":"Parameters"}},
		_appLabel: "",
		_resultMetaTypes: {},
		_autoLabels:{},
		_setDataAttr: function(data){
			this.data = data;
			console.log("job result viewer data: ", data);
			var paths = this.data.autoMeta.output_files.map(function(o){
				return o[0];
			});

			WorkspaceManager.getObjects(paths,true).then(lang.hitch(this, function(objs){
				this._resultObjects = objs;
				console.log("got objects: ", objs);
				this.setupResultType();
				this.refresh();
			}));

		},
		setupResultType: function(){
			if (this.data.autoMeta.app.id){
				this._resultType=this.data.autoMeta.app.id;
			}
			if (this._resultType=="GenomeAnnotation"){
				this._resultMetaTypes={"genome":{"label":"Genome"}};
				this._appLabel="Genome Annotation";
				this._autoLabels= {"scientific_name":{"label":"Organism"},"domain":{"label":"Domain"},"num_features":{"label":"Feature count"},"genome_id":{"label":"Annotation ID"}};
			}
		},
		refresh: function(){
			if (this.data) {
				var jobHeader='

';
				if (this.data.autoMeta && this.data.autoMeta.app){
					jobHeader=jobHeader+this._appLabel+" ";
				}
				jobHeader=jobHeader+"Job Result"+'

';
				this.viewHeader.set('content',jobHeader);

				var output = ["
"];
				output.push('

');

				if (this.data.autoMeta) {
					Object.keys(this.data.autoMeta).forEach(function(prop){
						if (prop=="output_files") { return; }
						if (prop=="app") { return; }
						if (prop=="job_output") { return; }
						if (prop=="hostname") { return; }
						if (this._metaOut.hasOwnProperty(prop)){
							//this._metaOut[prop]["value"]=this.data.autoMeta[prop];
						        output.push('
'+this._metaOut[prop]["label"]+ '	' + this.data.autoMeta[prop] + "
");
						}
					},this);
				}

				var result_output=[];
				if (this._resultObjects) {
					result_output.push('

Result Files
');
					result_output.push('

');
					this._resultObjects.forEach(function(obj){
						if(!this._resultMetaTypes.hasOwnProperty(obj.type)){
							result_output.push('
');
							result_output.push('	');
							result_output.push('' + obj.name + "	");
							result_output.push('' + obj.type+ "	");
							result_output.push('' + obj.size + "	");
							Object.keys(obj.autoMeta).forEach(function(prop){
								if (!obj.autoMeta[prop] || prop=="inspection_started") { return; }
								var label = this._autoLabels.hasOwnProperty(prop) ? this._autoLabels[prop]["label"] : prop;
								result_output.push("");
								result_output.push(label + ": " + obj.autoMeta[prop]);
								result_output.push("	");
							},this);
							result_output.push("
");
						}
						else{
							var subRecord=[];
							Object.keys(obj.autoMeta).forEach(function(prop){
								if (!obj.autoMeta[prop] || prop=="inspection_started") { return; }
								var label = this._autoLabels.hasOwnProperty(prop) ? this._autoLabels[prop]["label"] : prop;
								subRecord.push(label+": "+obj.autoMeta[prop]);
							},this);
							output.push('
'+this._resultMetaTypes[obj.type]["label"]+ '	' + subRecord.join(", ") + "
");
						}
					},this);
					result_output.push("

");
				}

				output.push("

");
				output.push.apply(output,result_output);

				if (this.data.userMeta) {
					Object.keys(this.data.userMeta).forEach(function(prop){
						output.push("
" + prop + ": " + this.data.userMeta[prop] + "
");
					},this);
				}

				output.push("
");
				this.viewer.set("content", output.join(""));
			}
		},
		startup: function(){
			if (this._started) {return;}
			this.inherited(arguments);
			this.viewHeader = new ContentPane({content: "Loading Job Results...", region: "top"});
			this.viewer= new ContentPane({content: "", region: "center"});
			this.addChild(this.viewHeader);
			this.addChild(this.viewer);

			this.on("i:click", function(evt){
				var rel = domAttr.get(evt.target,'rel');
				if (rel) {
					WorkspaceManager.downloadFile(rel);
				}else{
					console.warn("link not found: ", rel);
				}
			});
		}
	});
});
<|endoftext|>


<commit_before>/**
 * BarrelTypeController
 *
 * @description :: Server-side logic for managing Barreltypes
 * @help        :: See http://sailsjs.org/#!/documentation/concepts/Controllers
 */

module.exports = {

    /**
     * @api {get} /barreltype
     * @apiName find
     * @apiGroup BarrelType
     * @apiDescription Get the list of all barrel types according to permissions.
     *
     * @apiSuccess {Array} An array of barrel type
     *
     * @apiUse forbiddenError
     */
    find: (req, res) => {

        // Check permissions
        if (!(Team.can(req, 'barrelType/admin'))) {
            return res.error(403, 'forbidden', 'You are not authorized to read the barrel types.');
        }

        // Find BarrelType
        BarrelType.find()
            .exec((error, barrelTypes) => {
                if (error) {
                    return res.negotiate(error);
                }

                BarrelType.subscribe(req, _.pluck(barrelTypes, 'id'));
                BarrelType.watch(req);

                return res.ok(barrelTypes);
            });

    },

    /**
     * @api {post} /barreltype
     * @apiName create
     * @apiGroup Barrel Type
     * @apiDescription Create a new barrel type
     *
     * @apiParam {string} name : The name of the contents of the barrel (required)
     * @apiParam {string} shortName : A short unique code from the name of the contents (required)
     * @apiParam {integer} liters : The amount of drink in the barrel (required)
     * @apiParam {float} supplierPrice : purchasing price (required)
     * @apiParam {float} sellPrice : sell price(required)
     *
     * @apiSuccess {BarrelType} The alert button that you've just created
     *
     * @apiUse badRequestError
     * @apiUse forbiddenError
     */
    create: (req, res) => {

        // Check permissions
        if (!Team.can(req, 'alertButton/admin')) {
            return res.error(403, 'forbidden', 'You are not authorized to create an Alert button.');
        }

        // Check parameters
        let missingParameters = [];
        if (!req.param('name')) {
            missingParameters.push('name');
        }
        if (!req.param('shortName')) {
            missingParameters.push('shortName');
        }
        if (!req.param('liters')) {
            missingParameters.push('message');
        }
        if (!req.param('supplierPrice')) {
            missingParameters.push('supplierPrice');
        }
        if (!req.param('sellPrice')) {
            missingParameters.push('sellPrice');
        }
        // return error with missing parameters if there are missing parameters
        if (missingParameters.length) {
            console.log(missingParameters.join(', '));
            return res.error(400, 'BadRequest', 'Unknown parameters : ' + missingParameters.join(', '));
        }

        // Create the BarrelType
        BarrelType.create({
            name: req.param('name'),
            shortName: req.param('shortName'),
            liters: req.param('liters'),
            supplierPrice: req.param('supplierPrice'),
            sellPrice: req.param('sellPrice')
        }).exec((error, barrelType) => {
            if (error) {
                return res.negotiate(error);
            }

            BarrelType.publishCreate(barrelType);
            BarrelType.subscribe(req, [barrelType.id]);

            return res.ok(barrelType);
        });

    },

};

<commit_msg>BarrelTypeController.update<commit_after>/**
 * BarrelTypeController
 *
 * @description :: Server-side logic for managing Barreltypes
 * @help        :: See http://sailsjs.org/#!/documentation/concepts/Controllers
 */

module.exports = {

    /**
     * @api {get} /barreltype
     * @apiName find
     * @apiGroup BarrelType
     * @apiDescription Get the list of all barrel types according to permissions.
     *
     * @apiSuccess {Array} An array of barrel type
     *
     * @apiUse forbiddenError
     */
    find: (req, res) => {

        // Check permissions
        if (!(Team.can(req, 'barrelType/admin'))) {
            return res.error(403, 'forbidden', 'You are not authorized to read the barrel types.');
        }

        // Find BarrelType
        BarrelType.find()
            .exec((error, barrelTypes) => {
                if (error) {
                    return res.negotiate(error);
                }

                BarrelType.subscribe(req, _.pluck(barrelTypes, 'id'));
                BarrelType.watch(req);

                return res.ok(barrelTypes);
            });

    },

    /**
     * @api {post} /barreltype
     * @apiName create
     * @apiGroup Barrel Type
     * @apiDescription Create a new barrel type
     *
     * @apiParam {string} name : The name of the contents of the barrel (required)
     * @apiParam {string} shortName : A short unique code from the name of the contents (required)
     * @apiParam {integer} liters : The amount of drink in the barrel (required)
     * @apiParam {float} supplierPrice : purchasing price (required)
     * @apiParam {float} sellPrice : sell price(required)
     *
     * @apiSuccess {BarrelType} The alert button that you've just created
     *
     * @apiUse badRequestError
     * @apiUse forbiddenError
     */
    create: (req, res) => {

        // Check permissions
        if (!Team.can(req, 'BarrelType/admin')) {
            return res.error(403, 'forbidden', 'You are not authorized to create an Barrel Type.');
        }

        // Check parameters
        let missingParameters = [];
        if (!req.param('name')) {
            missingParameters.push('name');
        }
        if (!req.param('shortName')) {
            missingParameters.push('shortName');
        }
        if (!req.param('liters')) {
            missingParameters.push('message');
        }
        if (!req.param('supplierPrice')) {
            missingParameters.push('supplierPrice');
        }
        if (!req.param('sellPrice')) {
            missingParameters.push('sellPrice');
        }
        // return error with missing parameters if there are missing parameters
        if (missingParameters.length) {
            console.log(missingParameters.join(', '));
            return res.error(400, 'BadRequest', 'Unknown parameters : ' + missingParameters.join(', '));
        }

        // Create the BarrelType
        BarrelType.create({
            name: req.param('name'),
            shortName: req.param('shortName'),
            liters: req.param('liters'),
            supplierPrice: req.param('supplierPrice'),
            sellPrice: req.param('sellPrice')
        }).exec((error, barrelType) => {
            if (error) {
                return res.negotiate(error);
            }

            BarrelType.publishCreate(barrelType);
            BarrelType.subscribe(req, [barrelType.id]);

            return res.ok(barrelType);
        });

    },

    /**
     * @api {put} /barreltype/:id
     * @apiName update
     * @apiGroup BarrelType
     * @apiDescription Update the given barrel type
     *
     * @apiParam {string} id : Id of the barrel type to edit (required)
     * @apiParam {string} name : The name of the contents of the barrel (optional)
     * @apiParam {string} shortName : A short unique code from the name of the contents (optional)
     * @apiParam {integer} liters : The amount of drink in the barrel (optional)
     * @apiParam {float} supplierPrice : purchasing price (optional)
     * @apiParam {float} sellPrice : sell price(optional)
     *
     * @apiSuccess {BarrelType} The barrel type that you've just updated
     *
     * @apiUse forbiddenError
     * @apiUse notFoundError
     */
    update: (req, res) => {

        // Check permissions
        if (!Team.can(req, 'barrelType/admin')) {
            return res.error(403, 'forbidden', 'You are not authorized to update a Barrel Type.');
        }

        // Find the barrel type
        BarrelType.findOne({id: req.param('id')})
            .exec((error, barrelType) => {
                if (error) {
                    return res.negotiate(error);
                }
                if(!barrelType) {
                    return res.error(404, 'notfound', 'The requested barrel type cannot be found');
                }

                // Update
                barrelType.name = req.param('name', barrelType.name);
                barrelType.shortName = req.param('shortName', barrelType.shortName);
                barrelType.liters = req.param('liters', barrelType.liters);
                barrelType.sellPrice = req.param('sellPrice', barrelType.sellPrice);
                barrelType.supplierPrice = req.param('supplierPrice', barrelType.supplierPrice);

                barrelType.save((error) => {
                    if (error) {
                        return res.negotiate(error);
                    }

                    BarrelType.publishUpdate(barrelType.id, barrelType);
                    BarrelType.subscribe(req, [barrelType.id]);

                    return res.ok(barrelType);
                });

            });

    },

};

<|endoftext|>


<commit_before>#!/usr/bin/env node

import { install } from 'source-map-support';
install();

import 'babel-polyfill';
/* eslint-disable */
// Libs
import chalk from 'chalk';
import program from 'commander';
import fs from 'fs-extra';
import moment from 'moment';
import co from 'co';
import prompt from 'co-prompt';
import templateJSON from '../templates/default.json';

// TODO: think about changing these status functions to a single type
// signiture -> changeStatus(index, key, newStatus)
// would this be a case for currying? or some other functional tecq?

function makeNote(jsonObj) {
  var dir = getDir();
  var toMd = dir + '/note.md';
  var noteMd = fs.createWriteStream(toMd);
  Object.keys(jsonObj).map(function(title) {
    noteMd.write("# " + title + "\n");
    Object.keys(jsonObj[title]['items']).map(function(items, index){
      var status = jsonObj[title]['items'][items]['status'];
      var checkBox = '- [ ]';
      var itemIndex = ' ' + index + '.) ';
      if (status === 'complete') {
        checkBox = '- [x]';
      } else if (status === 'failed') {
        checkBox = '- [-]';
      }
      noteMd.write(checkBox + itemIndex + jsonObj[title]['items'][items]['description'] + "\n");
    });
    noteMd.write("\n");
  });
}

function addNote(noteObj, key) {
  var dir = getDir();
  var toData = dir + '/data.json';
  var dataJSON = fs.readJsonSync(toData);
  var noteString = noteObj.reduce(function(memo, word){
    return memo + ' ' + word;
  });

  var descriptionObj = {
    description: noteString,
    status: 'incomplete',
  };

  // modify toData
  Object.keys(dataJSON).map(function(note){
    if (dataJSON[note]['cli-ref'] === key) {
      dataJSON[note]['items'].push(descriptionObj);
      fs.writeJsonSync(toData, dataJSON);
    }
  });
  makeNote(dataJSON);
}

function removeNote(index, key) {
  var dir = getDir();
  var toData = dir + '/data.json';
  var dataJSON = fs.readJsonSync(dir + '/data.json');
  var cliFound = false;
  Object.keys(dataJSON).map(function(note, noteIndex){
    if (dataJSON[note]['cli-ref'] === key) {
      cliFound = true;
      if (!dataJSON[note]['items'][index]) {
        throw new Error('index ' + index + ' in "' + key + '" object does not exist');
      }
      dataJSON[note]['items'].splice(index, 1);
      fs.writeJsonSync(toData, dataJSON);
    } else if (Object.keys(dataJSON).length === (noteIndex + 1) && !cliFound) {
      throw new Error('"' + key + '" <cli-ref> does not exist');
    }
  });
  makeNote(dataJSON);
}

function completeNote(index, key) {
  var dir = getDir();
  var toData = dir + '/data.json';
  var dataJSON = fs.readJsonSync(toData);
  var cliFound = false;
  Object.keys(dataJSON).map(function(note, noteIndex) {
    if (dataJSON[note]['cli-ref'] === key) {
      cliFound = true;
      if (!dataJSON[note]['items'][index]) {
        throw new Error('index ' + index + ' in "' + key + '" object does not exist');
      }
      dataJSON[note]['items'][index]['status'] = 'complete';
      fs.writeJsonSync(toData, dataJSON);
    } else if (Object.keys(dataJSON).length === (noteIndex + 1) && !cliFound) {
      throw new Error('"' + key + '" <cli-ref> does not exist');
    }
  });
  makeNote(dataJSON);
}

function incompleteNote(index, key) {
  var dir = getDir();
  var toData = dir + '/data.json';
  var dataJSON = fs.readJsonSync(toData);
  var cliFound = false;
  Object.keys(dataJSON).map(function(note, noteIndex) {
    if (dataJSON[note]['cli-ref'] === key) {
      cliFound = true;
      if (!dataJSON[note]['items'][index]) {
        throw new Error('index ' + index + ' in "' + key + '" object does not exist');
      }
      dataJSON[note]['items'][index]['status'] = 'incomplete';
      fs.writeJsonSync(toData, dataJSON);
    } else if (Object.keys(dataJSON).length === (noteIndex + 1) && !cliFound) {
      throw new Error('"' + key + '" <cli-ref> does not exist');
    }
  });
  makeNote(dataJSON);
}

function failNote(index, key) {
  var dir = getDir();
  var toData = dir + '/data.json';
  var dataJSON = fs.readJsonSync(toData);
  var cliFound = false;
  Object.keys(dataJSON).map(function(note, noteIndex) {
    if (dataJSON[note]['cli-ref'] === key) {
      cliFound = true;
      if (!dataJSON[note]['items'][index]) {
        throw new Error('index ' + index + ' in "' + key + '" object does not exist');
      }
      dataJSON[note]['items'][index]['status'] = 'failed';
      fs.writeJsonSync(toData, dataJSON);
      return makeNote(dataJSON);
    } else if (Object.keys(dataJSON).length === (noteIndex + 1) && !cliFound) {
      throw new Error('"' + key + '" <cli-ref> does not exist');
    }
  });
}
function initializeNotes(userDir) {
  console.log(chalk.green('Success!'));
  var rcFile = process.env['HOME'] + '/.nonoterc.json';
  fs.closeSync(fs.openSync(rcFile, 'w'));

  var dotFileJSON = {}
  dotFileJSON.notesDirectory = userDir;

  fs.writeJsonSync(rcFile, dotFileJSON);
  console.log(' ');
  console.log(chalk.green('Success!'));
  console.log(' ');
  console.log('dotfile `.nonoterc.json` created at $HOME' );
  console.log(' ');
  console.log('Notes will be made in this directory: ')
  console.log(chalk.cyan(dotFileJSON.notesDirectory));
  console.log(' ');
}
function getConfig() {
  var config = process.env['HOME'] + '/.nonoterc.json';
  // TODO: handle the case of `nonote new` when `nonote init` has not been run
  return fs.readJsonSync(config).notesDirectory;
}

function getDir(type) {
  var today = moment().format("DD-MM-YYYY");
  var notesDir = getConfig();
  var days = notesDir + '/days/';
  var toDir = days + today;
  return toDir;
}

function createDir(create, path) {
  var templateDest = path + '/templates/';
  var templateFile = path + '/templates/default.json';
  if (create) {
    fs.mkdirsSync(path);
    fs.mkdirsSync(templateDest);
    fs.closeSync(fs.openSync(templateFile, 'w'));
    fs.writeJsonSync(templateFile, templateJSON);
    console.log(' ');
    console.log(chalk.green('Success!'));
  } else {
    console.log(' ');
    console.log('Make sure that dir exists and has a templates dir in it with a note config!');
  }
}

program
  .version('0.0.1')
  .command('new [template]')
  .alias('n')
  .description('create a new note for the day')
  .action(function(template, cmd) {
    if(!template) {
      template = 'default';
    }
    var today = moment().format("DD-MM-YYYY");
    var dir = getConfig() + '/';
    var notePath = dir + today;
    var templateData = dir + 'templates/' + template + '.json';

    console.log('notePath:', notePath);
    console.log(chalk.cyan('creating new note for today!'));

    // fs.mkdirsSync(notePath);
    // fs.copySync(templateData, noteData);
    // makeNote(dataJSON);

    console.log(chalk.white('new note created for: ') + chalk.bold.green(today));
  });

program
  .command('init')
  .description('initializes notes')
  .action(function() {
    co(function *() {

      var notesDirPath = yield prompt('notes directory path (from $HOME): ');
      var homePath = process.env['HOME'] + '/' + notesDirPath;
      initializeNotes(homePath);

      var shouldCreate = yield prompt.confirm('Would you like me to create "' + homePath + '" for you?(Recommended) [y/N] ');
      createDir(shouldCreate, homePath);
      console.log('Start taking notes with ' + chalk.cyan('nonote new!'));
      // TODO: create a readme
      process.exit();
    })
  });

program
  .command('add [cli-ref] <notes...>')
  .alias('a')
  .description('add note to object')
  .action(function(ref, note, cmd) {
    try {
      addNote(note, ref);
      console.log(chalk.green('note added!'));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

program
  .command('remove [cli-ref] <index>')
  .alias('r')
  .description('remove note from note object')
  .action(function(ref, note, cmd) {
    try {
      removeNote(note, ref);
      console.log(chalk.green('note at index[' + note + '] was removed!'));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

program
  .command('complete [cli-ref] <index>')
  .alias('c')
  .description('mark item as complete')
  .action(function(ref, note, cmd) {
    try {
      completeNote(note, ref);
      console.log(chalk.green('note at index[' + note + '] was marked as complete!'));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

program
  .command('incomplete [cli-ref] <index>')
  .alias('i')
  .description('mark item as incomplete')
  .action(function(ref, note, cmd) {
    try {
      incompleteNote(note, ref);
      console.log(chalk.green('note at index[' + note + '] was marked as incomplete!'));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

program
  .command('failed [cli-ref] <index>')
  .alias('f')
  .description('mark item as failed')
  .action(function(ref, note, cmd) {
    try {
      failNote(note, ref);
      console.log(chalk.green('note at index[' + note + '] was marked as failed :('));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

  program.parse(process.argv);

  /* eslint-enable*/
<commit_msg>striing interp<commit_after>#!/usr/bin/env node

import { install } from 'source-map-support';
install();

import 'babel-polyfill';
/* eslint-disable */
// Libs
import chalk from 'chalk';
import program from 'commander';
import fs from 'fs-extra';
import moment from 'moment';
import co from 'co';
import prompt from 'co-prompt';
import templateJSON from '../templates/default.json';

// TODO: think about changing these status functions to a single type
// signiture -> changeStatus(index, key, newStatus)
// would this be a case for currying? or some other functional tecq?

function makeNote(jsonObj) {
  var dir = getDir();
  var toMd = dir + '/note.md';
  var noteMd = fs.createWriteStream(toMd);
  Object.keys(jsonObj).map(function(title) {
    noteMd.write(`#  ${title} \n`);
    Object.keys(jsonObj[title]['items']).map(function(items, index){
      var status = jsonObj[title]['items'][items]['status'];
      var checkBox = '- [ ]';
      var itemIndex = ` ${index} .) `;
      if (status === 'complete') {
        checkBox = '- [x]';
      } else if (status === 'failed') {
        checkBox = '- [-]';
      }
      noteMd.write(checkBox + itemIndex + jsonObj[title]['items'][items]['description'] + "\n");
    });
    noteMd.write("\n");
  });
}

function addNote(noteObj, key) {
  var dir = getDir();
  var toData = dir + '/data.json';
  var dataJSON = fs.readJsonSync(toData);
  var noteString = noteObj.reduce(function(memo, word){
    return memo + ' ' + word;
  });

  var descriptionObj = {
    description: noteString,
    status: 'incomplete',
  };

  // modify toData
  Object.keys(dataJSON).map(function(note){
    if (dataJSON[note]['cli-ref'] === key) {
      dataJSON[note]['items'].push(descriptionObj);
      fs.writeJsonSync(toData, dataJSON);
    }
  });
  makeNote(dataJSON);
}

function removeNote(index, key) {
  var dir = getDir();
  var toData = dir + '/data.json';
  var dataJSON = fs.readJsonSync(dir + '/data.json');
  var cliFound = false;
  Object.keys(dataJSON).map(function(note, noteIndex){
    if (dataJSON[note]['cli-ref'] === key) {
      cliFound = true;
      if (!dataJSON[note]['items'][index]) {
        throw new Error(`index ${index} in "${key}" object does not exist`);
      }
      dataJSON[note]['items'].splice(index, 1);
      fs.writeJsonSync(toData, dataJSON);
    } else if (Object.keys(dataJSON).length === (noteIndex + 1) && !cliFound) {
      throw new Error(`"${key}" <cli-ref> does not exist`);
    }
  });
  makeNote(dataJSON);
}

function completeNote(index, key) {
  var dir = getDir();
  var toData = dir + '/data.json';
  var dataJSON = fs.readJsonSync(toData);
  var cliFound = false;
  Object.keys(dataJSON).map(function(note, noteIndex) {
    if (dataJSON[note]['cli-ref'] === key) {
      cliFound = true;
      if (!dataJSON[note]['items'][index]) {
        throw new Error(`index ${index} in "${key}" object does not exist`);
      }
      dataJSON[note]['items'][index]['status'] = 'complete';
      fs.writeJsonSync(toData, dataJSON);
    } else if (Object.keys(dataJSON).length === (noteIndex + 1) && !cliFound) {
      throw new Error(`"${key}" <cli-ref> does not exist`);
    }
  });
  makeNote(dataJSON);
}

function incompleteNote(index, key) {
  var dir = getDir();
  var toData = dir + '/data.json';
  var dataJSON = fs.readJsonSync(toData);
  var cliFound = false;
  Object.keys(dataJSON).map(function(note, noteIndex) {
    if (dataJSON[note]['cli-ref'] === key) {
      cliFound = true;
      if (!dataJSON[note]['items'][index]) {
        throw new Error(`index ${index} in "${key}" object does not exist`);
      }
      dataJSON[note]['items'][index]['status'] = 'incomplete';
      fs.writeJsonSync(toData, dataJSON);
    } else if (Object.keys(dataJSON).length === (noteIndex + 1) && !cliFound) {
      throw new Error(`"${key}" <cli-ref> does not exist`);
    }
  });
  makeNote(dataJSON);
}

function failNote(index, key) {
  var dir = getDir();
  var toData = dir + '/data.json';
  var dataJSON = fs.readJsonSync(toData);
  var cliFound = false;
  Object.keys(dataJSON).map(function(note, noteIndex) {
    if (dataJSON[note]['cli-ref'] === key) {
      cliFound = true;
      if (!dataJSON[note]['items'][index]) {
        throw new Error(`index ${index} in "${key}" object does not exist`);
      }
      dataJSON[note]['items'][index]['status'] = 'failed';
      fs.writeJsonSync(toData, dataJSON);
      return makeNote(dataJSON);
    } else if (Object.keys(dataJSON).length === (noteIndex + 1) && !cliFound) {
      throw new Error(`"${key}" <cli-ref> does not exist`);
    }
  });
}
function initializeNotes(userDir) {
  console.log(chalk.green('Success!'));
  var rcFile = process.env['HOME'] + '/.nonoterc.json';
  fs.closeSync(fs.openSync(rcFile, 'w'));

  var dotFileJSON = {}
  dotFileJSON.notesDirectory = userDir;

  fs.writeJsonSync(rcFile, dotFileJSON);
  console.log(' ');
  console.log(chalk.green('Success!'));
  console.log(' ');
  console.log('dotfile `.nonoterc.json` created at $HOME' );
  console.log(' ');
  console.log('Notes will be made in this directory: ')
  console.log(chalk.cyan(dotFileJSON.notesDirectory));
  console.log(' ');
}
function getConfig() {
  var config = process.env['HOME'] + '/.nonoterc.json';
  // TODO: handle the case of `nonote new` when `nonote init` has not been run
  return fs.readJsonSync(config).notesDirectory;
}

function getDir(type) {
  var today = moment().format("DD-MM-YYYY");
  var notesDir = getConfig();
  var days = notesDir + '/days/';
  var toDir = days + today;
  return toDir;
}

function createDir(create, path) {
  var templateDest = path + '/templates/';
  var templateFile = path + '/templates/default.json';
  if (create) {
    fs.mkdirsSync(path);
    fs.mkdirsSync(templateDest);
    fs.closeSync(fs.openSync(templateFile, 'w'));
    fs.writeJsonSync(templateFile, templateJSON);
    console.log(' ');
    console.log(chalk.green('Success!'));
  } else {
    console.log(' ');
    console.log('Make sure that dir exists and has a templates dir in it with a note config!');
  }
}

program
  .version('0.0.1')
  .command('new [template]')
  .alias('n')
  .description('create a new note for the day')
  .action(function(template, cmd) {
    if(!template) {
      template = 'default';
    }
    var today = moment().format("DD-MM-YYYY");
    var dir = getConfig()
    var notePath = dir + today;
    var templateData = `${dir}/templates/${template}.json`;

    console.log('notePath:', notePath);
    console.log(chalk.cyan('creating new note for today!'));

    // fs.mkdirsSync(notePath);
    // fs.copySync(templateData, noteData);
    // makeNote(dataJSON);

    console.log(chalk.white('new note created for: ') + chalk.bold.green(today));
  });

program
  .command('init')
  .description('initializes notes')
  .action(function() {
    co(function *() {

      var notesDirPath = yield prompt('notes directory path (from $HOME): ');
      var homePath = process.env['HOME'] + '/' + notesDirPath;
      initializeNotes(homePath);

      var shouldCreate = yield prompt.confirm('Would you like me to create "' + homePath + '" for you?(Recommended) [y/N] ');
      createDir(shouldCreate, homePath);
      console.log('Start taking notes with ' + chalk.cyan('nonote new!'));
      // TODO: create a readme
      process.exit();
    })
  });

program
  .command('add [cli-ref] <notes...>')
  .alias('a')
  .description('add note to object')
  .action(function(ref, note, cmd) {
    try {
      addNote(note, ref);
      console.log(chalk.green('note added!'));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

program
  .command('remove [cli-ref] <index>')
  .alias('r')
  .description('remove note from note object')
  .action(function(ref, note, cmd) {
    try {
      removeNote(note, ref);
      console.log(chalk.green('note at index[' + note + '] was removed!'));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

program
  .command('complete [cli-ref] <index>')
  .alias('c')
  .description('mark item as complete')
  .action(function(ref, note, cmd) {
    try {
      completeNote(note, ref);
      console.log(chalk.green('note at index[' + note + '] was marked as complete!'));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

program
  .command('incomplete [cli-ref] <index>')
  .alias('i')
  .description('mark item as incomplete')
  .action(function(ref, note, cmd) {
    try {
      incompleteNote(note, ref);
      console.log(chalk.green('note at index[' + note + '] was marked as incomplete!'));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

program
  .command('failed [cli-ref] <index>')
  .alias('f')
  .description('mark item as failed')
  .action(function(ref, note, cmd) {
    try {
      failNote(note, ref);
      console.log(chalk.green('note at index[' + note + '] was marked as failed :('));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

  program.parse(process.argv);

  /* eslint-enable*/
<|endoftext|>


<commit_before>var obj_canvas,
obj_c,
cp_canvas = null;

var canvas
var video_canvas,
vid_c;

var brown_const=0;

var vid_width = 640;
var vid_height = 480;

var svg_led;
var context;

var l = 80,
	n = 4,
	v = 1/4;

var n_max = 20;

function setupD3() {
    canvas = d3.select("#canvasArea").append("canvas")
        .attr("width", vid_width)
        .attr("height", vid_height);

    svg_led = d3.select("#canvasArea").append("svg:svg")
        .attr("width", 150)
        .attr("height", 150)
        .attr("transform", "translate(300)")
        .attr("viewBox", "40 40 220 220")
        .style("opacity", "0.5");

    var shape_bg = svg_led.append("svg:rect")
    							.attr("width", 300)
    							.attr("height", 300)
    							.style("fill","#000000");

    var shape_stage = svg_led.append("svg:rect")
    							.attr("x", 112.5)
    							.attr("y", 112.5)
    							.attr("width", 75)
    							.attr("height", 75)
    							.style("fill", "#111111");

    var g_ledL = svg_led.append("svg:g")
    						.attr("transform", "matrix(1 0 0 -1 55 150)");
    			g_ledL.append("svg:polygon")
    						.attr("points", "-39.042,8.417 24.708,8.417 24.7,6.191 20.958,5.667 6.708,1.417 6.708,6.167 -39.042,6.167 	");
    			g_ledL.append("svg:polygon")
    						.attr("points", "-38.792,-8.333 21.458,-8.333 24.208,-6.333 24.208,3.667 6.708,-2.333 6.708,-5.833 -38.792,-5.833 	");
    var led_L = g_ledL.append("svg:path")
    						.attr("d", "M39.042,0.834c0-3.697-0.483-7.667-4.069-10.966c-8.452-7.775-36.53-7.701-38.847-7.701c-3.728,0-4.75,7.909-4.75,17.667c0,9.757,1.022,17.667,4.75,17.667c2.282,0,32.307,0.417,38.792-6.494C38.095,7.62,39.042,4.622,39.042,0.834z")
    						.style("fill", "#ffffff")
    						.style("opacity", "0");

    var g_ledR = svg_led.append("svg:g")
    						.attr("transform", "matrix(-1 0 0 1 245 150)");
    			g_ledR.append("svg:polygon")
    						.attr("points", "-39.042,8.417 24.708,8.417 24.7,6.191 20.958,5.667 6.708,1.417 6.708,6.167 -39.042,6.167 	");
    			g_ledR.append("svg:polygon")
    						.attr("points", "-38.792,-8.333 21.458,-8.333 24.208,-6.333 24.208,3.667 6.708,-2.333 6.708,-5.833 -38.792,-5.833 	");
    var led_R = g_ledR.append("svg:path")
    						.attr("d", "M39.042,0.834c0-3.697-0.483-7.667-4.069-10.966c-8.452-7.775-36.53-7.701-38.847-7.701c-3.728,0-4.75,7.909-4.75,17.667c0,9.757,1.022,17.667,4.75,17.667c2.282,0,32.307,0.417,38.792-6.494C38.095,7.62,39.042,4.622,39.042,0.834z")
    						.style("fill", "#ffffff")
    						.style("opacity", "0");

    var g_ledU = svg_led.append("svg:g")
    						.attr("transform", "matrix(0 1 1 0 150 55)");
    			g_ledU.append("svg:polygon")
    						.attr("points", "-39.042,8.417 24.708,8.417 24.7,6.191 20.958,5.667 6.708,1.417 6.708,6.167 -39.042,6.167 	");
    			g_ledU.append("svg:polygon")
    						.attr("points", "-38.792,-8.333 21.458,-8.333 24.208,-6.333 24.208,3.667 6.708,-2.333 6.708,-5.833 -38.792,-5.833 	");
    var led_U = g_ledU.append("svg:path")
    						.attr("d", "M39.042,0.834c0-3.697-0.483-7.667-4.069-10.966c-8.452-7.775-36.53-7.701-38.847-7.701c-3.728,0-4.75,7.909-4.75,17.667c0,9.757,1.022,17.667,4.75,17.667c2.282,0,32.307,0.417,38.792-6.494C38.095,7.62,39.042,4.622,39.042,0.834z")
    						.style("fill", "#ffffff")
    						.style("opacity", "0");

    var g_ledD = svg_led.append("svg:g")
    						.attr("transform", "matrix(0 -1 -1 0 150 245)");
    			g_ledD.append("svg:polygon")
    						.attr("points", "-39.042,8.417 24.708,8.417 24.7,6.191 20.958,5.667 6.708,1.417 6.708,6.167 -39.042,6.167 	");
    			g_ledD.append("svg:polygon")
    						.attr("points", "-38.792,-8.333 21.458,-8.333 24.208,-6.333 24.208,3.667 6.708,-2.333 6.708,-5.833 -38.792,-5.833 	");
    var led_D = g_ledD.append("svg:path")
    						.attr("d", "M39.042,0.834c0-3.697-0.483-7.667-4.069-10.966c-8.452-7.775-36.53-7.701-38.847-7.701c-3.728,0-4.75,7.909-4.75,17.667c0,9.757,1.022,17.667,4.75,17.667c2.282,0,32.307,0.417,38.792-6.494C38.095,7.62,39.042,4.622,39.042,0.834z")
    						.style("fill", "#ffffff")
    						.style("opacity", "0");

    context = canvas.node().getContext("2d");

	var w = 640,
    	h = 480,
    	m = 20,
    	radius = l/2+10,
    	degrees = 180 / Math.PI;

	var objects = d3.range(n_max).map(function() {
  		var x = 40 + Math.random() * (w-40), y = 40 + Math.random() * (h-40);
  		return {
    		vx: 0,
    		vy: 0,
    		path: d3.range(m).map(function() { return [x, y]; }),
    		count: 0,
    		active: 0,
    		size: l,
    		color: "#FA6600"
  		};
	});

	var svg = d3.select("#canvasArea").append("svg:svg")
    	.attr("width", vid_width)
    	.attr("height", vid_height);

	var g = svg.selectAll("g")
    	.data(objects)
		.enter().append("svg:g");

	var box = g.append("svg:rect");

	function drawObjects(){
		for (var i = -1; ++i < n;) {
    		var object = objects[i],
        		x = object.path[0][0],
        		y = object.path[0][1];

    		// stuck at the walls.
    		if (x < 0)
    		{
    			object.path[0][0] = l;
    		}
    		if(x > w-l)
    		{
    			object.path[0][0] = w-l;
    		}
    		if (y < 0)
    		{
    			object.path[0][1] = l;
    		}
    		if (y > h-l)
    		{
    			object.path[0][1] = h-l;
    		}
    		object.size = l;
    		object.active = (i<n)?1:0;
    	}
    	box.attr("opacity", function(d,i){
    		return d.active;
    	});
		box.attr("width", function(d,i){
			return d.size;
		});
		box.attr("height", function(d,i){
			return d.size;
		});
		box.attr("stroke", function(d,i){
			return d.color;
		});
  		box.attr("transform", function(d) {
    		return "translate(" + d.path[0] + ")";
  		});

  		led_U.style("opacity",arrow.int1);
  		led_L.style("opacity",arrow.int2);
  		led_D.style("opacity",arrow.int3);
  		led_R.style("opacity",arrow.int4);
  	}

	d3.timer(function() {
  		drawObjects();
	});

	window.setInterval(getVideo, 1000/20);

	function getVideo(){
        getVidFrame("http://171.65.102.132:8080/?action=snapshot?t=" + new Date().getTime(), function(image) {
            context.clearRect(0, 0, vid_width, vid_height);
            context.drawImage(image, 0, 0, vid_width, vid_height);
        });

    	function getVidFrame(path, callback) {
            var image = new Image;
            image.src = path;
            image.onload = function() {
                callback(image);
				//console.log(new Date().getTime());
            };
        }
    }
}
<commit_msg>combine d3 svg<commit_after>var obj_canvas,
obj_c,
cp_canvas = null;

var canvas
var video_canvas,
vid_c;

var brown_const=0;

var vid_width = 640;
var vid_height = 480;

var svg_led;
var context;

var l = 80,
	n = 4,
	v = 1/4;

var n_max = 20;

function setupD3() {
    canvas = d3.select("#canvasArea").append("canvas")
        .attr("width", vid_width)
        .attr("height", vid_height);

    svg_led = d3.select("#canvasArea").append("svg:svg")
        .attr("width", 150)
        .attr("height", 150)
        .attr("viewBox", "40 40 220 220")
        .style("opacity", "0.5")
        .attr("transform", "translate(300)");

    var shape_bg = svg_led.append("svg:rect")
    							.attr("width", 300)
    							.attr("height", 300)
    							.style("fill","#000000");

    var shape_stage = svg_led.append("svg:rect")
    							.attr("x", 112.5)
    							.attr("y", 112.5)
    							.attr("width", 75)
    							.attr("height", 75)
    							.style("fill", "#111111");

    var g_ledL = svg_led.append("svg:g")
    						.attr("transform", "matrix(1 0 0 -1 55 150)");
    			g_ledL.append("svg:polygon")
    						.attr("points", "-39.042,8.417 24.708,8.417 24.7,6.191 20.958,5.667 6.708,1.417 6.708,6.167 -39.042,6.167 	");
    			g_ledL.append("svg:polygon")
    						.attr("points", "-38.792,-8.333 21.458,-8.333 24.208,-6.333 24.208,3.667 6.708,-2.333 6.708,-5.833 -38.792,-5.833 	");
    var led_L = g_ledL.append("svg:path")
    						.attr("d", "M39.042,0.834c0-3.697-0.483-7.667-4.069-10.966c-8.452-7.775-36.53-7.701-38.847-7.701c-3.728,0-4.75,7.909-4.75,17.667c0,9.757,1.022,17.667,4.75,17.667c2.282,0,32.307,0.417,38.792-6.494C38.095,7.62,39.042,4.622,39.042,0.834z")
    						.style("fill", "#ffffff")
    						.style("opacity", "0");

    var g_ledR = svg_led.append("svg:g")
    						.attr("transform", "matrix(-1 0 0 1 245 150)");
    			g_ledR.append("svg:polygon")
    						.attr("points", "-39.042,8.417 24.708,8.417 24.7,6.191 20.958,5.667 6.708,1.417 6.708,6.167 -39.042,6.167 	");
    			g_ledR.append("svg:polygon")
    						.attr("points", "-38.792,-8.333 21.458,-8.333 24.208,-6.333 24.208,3.667 6.708,-2.333 6.708,-5.833 -38.792,-5.833 	");
    var led_R = g_ledR.append("svg:path")
    						.attr("d", "M39.042,0.834c0-3.697-0.483-7.667-4.069-10.966c-8.452-7.775-36.53-7.701-38.847-7.701c-3.728,0-4.75,7.909-4.75,17.667c0,9.757,1.022,17.667,4.75,17.667c2.282,0,32.307,0.417,38.792-6.494C38.095,7.62,39.042,4.622,39.042,0.834z")
    						.style("fill", "#ffffff")
    						.style("opacity", "0");

    var g_ledU = svg_led.append("svg:g")
    						.attr("transform", "matrix(0 1 1 0 150 55)");
    			g_ledU.append("svg:polygon")
    						.attr("points", "-39.042,8.417 24.708,8.417 24.7,6.191 20.958,5.667 6.708,1.417 6.708,6.167 -39.042,6.167 	");
    			g_ledU.append("svg:polygon")
    						.attr("points", "-38.792,-8.333 21.458,-8.333 24.208,-6.333 24.208,3.667 6.708,-2.333 6.708,-5.833 -38.792,-5.833 	");
    var led_U = g_ledU.append("svg:path")
    						.attr("d", "M39.042,0.834c0-3.697-0.483-7.667-4.069-10.966c-8.452-7.775-36.53-7.701-38.847-7.701c-3.728,0-4.75,7.909-4.75,17.667c0,9.757,1.022,17.667,4.75,17.667c2.282,0,32.307,0.417,38.792-6.494C38.095,7.62,39.042,4.622,39.042,0.834z")
    						.style("fill", "#ffffff")
    						.style("opacity", "0");

    var g_ledD = svg_led.append("svg:g")
    						.attr("transform", "matrix(0 -1 -1 0 150 245)");
    			g_ledD.append("svg:polygon")
    						.attr("points", "-39.042,8.417 24.708,8.417 24.7,6.191 20.958,5.667 6.708,1.417 6.708,6.167 -39.042,6.167 	");
    			g_ledD.append("svg:polygon")
    						.attr("points", "-38.792,-8.333 21.458,-8.333 24.208,-6.333 24.208,3.667 6.708,-2.333 6.708,-5.833 -38.792,-5.833 	");
    var led_D = g_ledD.append("svg:path")
    						.attr("d", "M39.042,0.834c0-3.697-0.483-7.667-4.069-10.966c-8.452-7.775-36.53-7.701-38.847-7.701c-3.728,0-4.75,7.909-4.75,17.667c0,9.757,1.022,17.667,4.75,17.667c2.282,0,32.307,0.417,38.792-6.494C38.095,7.62,39.042,4.622,39.042,0.834z")
    						.style("fill", "#ffffff")
    						.style("opacity", "0");

    context = canvas.node().getContext("2d");

	var w = 640,
    	h = 480,
    	m = 20,
    	radius = l/2+10,
    	degrees = 180 / Math.PI;

	var objects = d3.range(n_max).map(function() {
  		var x = 40 + Math.random() * (w-40), y = 40 + Math.random() * (h-40);
  		return {
    		vx: 0,
    		vy: 0,
    		path: d3.range(m).map(function() { return [x, y]; }),
    		count: 0,
    		active: 0,
    		size: l,
    		color: "#FA6600"
  		};
	});

	var svg = d3.select("#canvasArea").append("svg:svg")
    	.attr("width", vid_width)
    	.attr("height", vid_height);

	var g = svg.selectAll("g")
    	.data(objects)
		.enter().append("svg:g");

	var box = g.append("svg:rect");

	function drawObjects(){
		for (var i = -1; ++i < n;) {
    		var object = objects[i],
        		x = object.path[0][0],
        		y = object.path[0][1];

    		// stuck at the walls.
    		if (x < 0)
    		{
    			object.path[0][0] = l;
    		}
    		if(x > w-l)
    		{
    			object.path[0][0] = w-l;
    		}
    		if (y < 0)
    		{
    			object.path[0][1] = l;
    		}
    		if (y > h-l)
    		{
    			object.path[0][1] = h-l;
    		}
    		object.size = l;
    		object.active = (i<n)?1:0;
    	}
    	box.attr("opacity", function(d,i){
    		return d.active;
    	});
		box.attr("width", function(d,i){
			return d.size;
		});
		box.attr("height", function(d,i){
			return d.size;
		});
		box.attr("stroke", function(d,i){
			return d.color;
		});
  		box.attr("transform", function(d) {
    		return "translate(" + d.path[0] + ")";
  		});

  		led_U.style("opacity",arrow.int1);
  		led_L.style("opacity",arrow.int2);
  		led_D.style("opacity",arrow.int3);
  		led_R.style("opacity",arrow.int4);
  	}

	d3.timer(function() {
  		drawObjects();
	});

	window.setInterval(getVideo, 1000/20);

	function getVideo(){
        getVidFrame("http://171.65.102.132:8080/?action=snapshot?t=" + new Date().getTime(), function(image) {
            context.clearRect(0, 0, vid_width, vid_height);
            context.drawImage(image, 0, 0, vid_width, vid_height);
        });

    	function getVidFrame(path, callback) {
            var image = new Image;
            image.src = path;
            image.onload = function() {
                callback(image);
				//console.log(new Date().getTime());
            };
        }
    }
}
<|endoftext|>


<commit_before>/// string.js --- string utilities
//
// Copyright (c) 2011 Quildreen Motta
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/// Module khaos.collection.string

//// -- Aliases --------------------------------------------------------
var __trim        = ''.trim
var __concatenate = ''.concat

//// -- Building -------------------------------------------------------

///// Function repeat
// Creates a `String' by repeating the given one a number of `times'.
//
// repeat :: String, Number -> String
function repeat(string, times) {
  return times <= 0?      ''
  :      /* otherwise */  Array(times + 1).join(string) }

///// Function concatenate
// Creates a `String' by concatenating all the given ones together.
//
// concatenate :: String... -> String
function concatenate() {
  return __concatenate.apply(null, arguments) }

//// -- Manipulating ---------------------------------------------------

///// Function trim
// Removes whitespace from both ends of the `string'.
//
// trim :: String -> String
function trim(string) {
  return __trim.call(string) }

// TODO: consider being explicit about which characters are considered
// whitespace, given the `\s' character class has several problems.

///// Function trim_left
// Removes whitespace from the beginning of the `string'.
//
// trim_left :: String -> String
function trim_left(string) {
  return string.replace(/^\s+/, '') }

///// Function trim_right
// Removes whitespace from the end of the `string'.
//
// trim_right :: String -> String
function trim_right(string) {
  return string.replace(/\s+$/, '') }

//// -- Inspection -----------------------------------------------------

///// Function starts_with_p
// Does the `string' start with a given piece of text?
//
// starts_with_p :: String, String -> Bool
function starts_with_p(string, what) {
  return string.slice(0, what.length) == what }

///// Function ends_with_p
// Does the `string' end with a given piece of text?
//
// ends_with_p :: String, String -> Bool
function ends_with_p(string, what) {
  return string.slice(-what.length) == what }

///// Function empty_p
// Is the `string' empty?
//
// empty_p :: String -> Bool
function empty_p(string) {
  return string === '' }

///// Function has_p
// Does the `string' contain a given piece of text?
//
// has_p :: String, String -> Bool
function has_p(string, what) {
  return string.indexOf(what) != -1 }

///// Function size
// Returns the number of characters in the `string'.
//
// size :: String -> Number
function size(string) {
  return string.length }

///// Function count
// Returns the number of times the given piece of text appears in the
// `string'.
//
// count :: String, String -> Number
function count(string, what) {
  var pos, result
  result = 0
  while (true) { pos = string.indexOf(what, pos + 1)
                 if (pos != -1)  ++result
                 else            break }

  return result }

//// -- Case folding ---------------------------------------------------

///// Function upcase
// Returns a new version of the `string', with upper-cased characters.
//
// upcase :: String -> String
function upcase(string) {
  return string.toUpperCase() }

///// Function downcase
// Returns a new version of the `string', with lower-cased characters.
//
// downcase :: String -> String
function downcase(string) {
  return string.toLowerCase() }

///// Function capitalise
// Returns a new version of the `string', with the first letter
// upper-cased, all the rest lower-cased.
//
// If `all_words' is given and is truthy, we make the first letter of
// each word upper-cased.
//
// capitalise :: String, Bool? -> String
function capitalise(string, all_words) {
  var re = all_words?       /\b\w/g
         : /* otherwise */  /\b\w/

  return downcase(string).replace(re, upcase) }

///// Function dasherise
// Returns a new version of the `string', with all words separated only
// by dashes.
//
// All of the whitespace is stripped in the process.
//
// dasherise :: String -> String
function dasherise(string) {
  return trim(string).replace(/\s+/g, '-') }

///// Function camelise
// Returns a new version of the `string', with all the whitespace and
// hyphens stripped, the first letter of each word upper-cased and the
// rest of the letters lower-cased.
//
// camelise :: String -> String
function camelise(string) {
  var re = /[\s\-_]+(\w)/g

  return downcase(string).replace(re, function(match, letter) {
                                        return upcase(letter) })}

//// -- Slicing --------------------------------------------------------

///// Function first
// Returns the first character in the `string'.
//
// first :: String -> Maybe Char
function first(string) {
  return string.charAt(0) }

///// Function rest
// Returns a new `string' with all but the first character.
//
// rest :: String -> String
function rest(string) {
  return string.slice(1) }

///// Function last
// Returns the last character in the `string'.
//
// last :: String -> Maybe Char
function last(string) {
  return string.charAt(string.length - 1) }

///// Function but_last
// Returns a new `string' with all but the last character.
//
// but_last :: String -> String
function but_last(string) {
  return string.slice(0, -1) }

///// Function slice
// Returns a new `string', containing the part of the original sequence
// from [`start', `end'[.
//
// If either `start' or `end' are given negative indexes, the number is
// taken to be an offset from the end of the sequence.
//
// slice :: String, start:Number?, end:Number? -> String
function slice(string, start, end) {
  return string.slice(start, end) }

///// Function take
// Returns a new `string', from the first character up to the given
// `size'.
//
// take :: String, Number -> String
function take(string, size) {
  return string.slice(0, size) }

///// Function drop
// Returns a new `string', without the first N items.
//
// drop :: String, Number -> String
function drop(string, size) {
  return string.slice(size) }

///// Function split
// Returns a list of `String's, by breaking the original string
// everytime the predicate holds.
//
// split :: String, (Char, Number, String -> Bool) -> [String]
function split(string, predicate) {
  var i, len
  var result = []
  var start  = 0
  for (i = 0, len = string.length; i < len; ++i) {
    if (predicate(string.charAt(i), i, string)) {
      result.push(string.slice(0, i))
      start = i }}

  if (start < len) result.push(string.slice(start))
  return result }

//// -- Comparisons ----------------------------------------------------

///// Function compare
// Returns an `Ordering' from the comparison of two `String's.
//
// If `foldcase' is given and is truthy, we ignore both string's casing
// completely, such that `Foo` would equal `foO`.
//
// compare :: String, String, Bool? -> Ordering
function compare(left, right, foldcase) {
  if (foldcase) {
    left  = downcase(left)
    right = downcase(right) }

  return left < right?   -1
  :      left === right?  0
  :      /* otherwise */  1 }

///// Function equal_p
// Are both `String's equal?
//
// If `foldcase' is given and is truthy, we ignore both string's casing
// competely, such that `Foo` would equal `foO`.
//
// equal_p :: String, String, Bool? -> Bool
function equal_p(left, right, foldcase) {
  return !compare(left, right, foldcase) }

//// -- Formatting -----------------------------------------------------

///// Function format
// Evaluates a template, substituting the variables with respect to the
// environment provided by the given `mappings'.
//
// If a mapping is not given, we assume it to be empty, in which case
// the template variables are simply stripped away.
//
// A template variable is a special construct in the form:
//
//     :bnf:
//     <template-variable> ::= "{:" <any but "}"> "}"
//
// For example, provide a "Hello, world!" template, that adjusts to a
// given name, one could write:
//
//     format("Hello, {:subject}!", { subject: "world" })
//     // => "Hello, world!"
//
// A template variable can be escaped by placing a backslash between the
// open-curly braces and the colon, such that the construct would be
// output verbatim:
//
//     // Remember backslashes must be escaped inside Strings.
//     format("Hello, {\\:subject}", { subject: "world" })
//     // => "Hello, {\\:subject}"
//
//
// format :: String, { String -> String | (String... -> String) } -> String
function format(string, mappings) {
  mappings = mappings || {}
  return string.replace(/{(\\?:)([^}]+)}/g, resolve_identifier)

  function resolve_identifier(match, mod, key) {
    return starts_with_p(mod, '\\')?  '{:' + key + '}'
    :      key in mappings?           mappings[key]
    :      /* otherwise */            '' }}

//// -- Exports --------------------------------------------------------
module.exports = { repeat: repeat
                 , concatenate: concatenate

                 , trim: trim
                 , trim_left: trim_left
                 , trim_right: trim_right

                 , starts_with_p: starts_with_p
                 , ends_with_p: ends_with_p
                 , has_p: has_p
                 , empty_p: empty_p
                 , size: size
                 , count: count

                 , upcase: upcase
                 , downcase: downcase
                 , capitalise: capitalise
                 , dasherise: dasherise
                 , camelise: camelise

                 , first: first
                 , rest: rest
                 , last: last
                 , but_last: but_last
                 , slice: slice
                 , take: take
                 , drop: drop
                 , split: split

                 , compare: compare
                 , equal_p: equal_p

                 , format: format
                 }
<commit_msg>Adds summary for collection.string module.<commit_after>/// string.js --- string utilities
//
// Copyright (c) 2011 Quildreen Motta
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/// Module khaos.collection.string
//
// This module provides basic services for manipulating and interacting
// with Strings in JavaScript.
//
// With this, the range of manipulation services in JavaScript is
// extended with:
//
//   * Building Strings.
//   * Trimming whitespaces from Strings.
//   * Inspecting common properties of Strings.
//   * Mapping a particular String format to another, which mostly
//     includes the special mappings for case-folding.
//   * Fine-grained and high-level slicing.
//   * Comparing strings.
//   * Formatting and templating.
//
// Some of these services are already provided by the native String
// object's prototype, in which case we just make them available through
// generic functions.

//// -- Aliases --------------------------------------------------------
var __trim        = ''.trim
var __concatenate = ''.concat

//// -- Building -------------------------------------------------------

///// Function repeat
// Creates a `String' by repeating the given one a number of `times'.
//
// repeat :: String, Number -> String
function repeat(string, times) {
  return times <= 0?      ''
  :      /* otherwise */  Array(times + 1).join(string) }

///// Function concatenate
// Creates a `String' by concatenating all the given ones together.
//
// concatenate :: String... -> String
function concatenate() {
  return __concatenate.apply(null, arguments) }

//// -- Manipulating ---------------------------------------------------

///// Function trim
// Removes whitespace from both ends of the `string'.
//
// trim :: String -> String
function trim(string) {
  return __trim.call(string) }

// TODO: consider being explicit about which characters are considered
// whitespace, given the `\s' character class has several problems.

///// Function trim_left
// Removes whitespace from the beginning of the `string'.
//
// trim_left :: String -> String
function trim_left(string) {
  return string.replace(/^\s+/, '') }

///// Function trim_right
// Removes whitespace from the end of the `string'.
//
// trim_right :: String -> String
function trim_right(string) {
  return string.replace(/\s+$/, '') }

//// -- Inspection -----------------------------------------------------

///// Function starts_with_p
// Does the `string' start with a given piece of text?
//
// starts_with_p :: String, String -> Bool
function starts_with_p(string, what) {
  return string.slice(0, what.length) == what }

///// Function ends_with_p
// Does the `string' end with a given piece of text?
//
// ends_with_p :: String, String -> Bool
function ends_with_p(string, what) {
  return string.slice(-what.length) == what }

///// Function empty_p
// Is the `string' empty?
//
// empty_p :: String -> Bool
function empty_p(string) {
  return string === '' }

///// Function has_p
// Does the `string' contain a given piece of text?
//
// has_p :: String, String -> Bool
function has_p(string, what) {
  return string.indexOf(what) != -1 }

///// Function size
// Returns the number of characters in the `string'.
//
// size :: String -> Number
function size(string) {
  return string.length }

///// Function count
// Returns the number of times the given piece of text appears in the
// `string'.
//
// count :: String, String -> Number
function count(string, what) {
  var pos, result
  result = 0
  while (true) { pos = string.indexOf(what, pos + 1)
                 if (pos != -1)  ++result
                 else            break }

  return result }

//// -- Case folding ---------------------------------------------------

///// Function upcase
// Returns a new version of the `string', with upper-cased characters.
//
// upcase :: String -> String
function upcase(string) {
  return string.toUpperCase() }

///// Function downcase
// Returns a new version of the `string', with lower-cased characters.
//
// downcase :: String -> String
function downcase(string) {
  return string.toLowerCase() }

///// Function capitalise
// Returns a new version of the `string', with the first letter
// upper-cased, all the rest lower-cased.
//
// If `all_words' is given and is truthy, we make the first letter of
// each word upper-cased.
//
// capitalise :: String, Bool? -> String
function capitalise(string, all_words) {
  var re = all_words?       /\b\w/g
         : /* otherwise */  /\b\w/

  return downcase(string).replace(re, upcase) }

///// Function dasherise
// Returns a new version of the `string', with all words separated only
// by dashes.
//
// All of the whitespace is stripped in the process.
//
// dasherise :: String -> String
function dasherise(string) {
  return trim(string).replace(/\s+/g, '-') }

///// Function camelise
// Returns a new version of the `string', with all the whitespace and
// hyphens stripped, the first letter of each word upper-cased and the
// rest of the letters lower-cased.
//
// camelise :: String -> String
function camelise(string) {
  var re = /[\s\-_]+(\w)/g

  return downcase(string).replace(re, function(match, letter) {
                                        return upcase(letter) })}

//// -- Slicing --------------------------------------------------------

///// Function first
// Returns the first character in the `string'.
//
// first :: String -> Maybe Char
function first(string) {
  return string.charAt(0) }

///// Function rest
// Returns a new `string' with all but the first character.
//
// rest :: String -> String
function rest(string) {
  return string.slice(1) }

///// Function last
// Returns the last character in the `string'.
//
// last :: String -> Maybe Char
function last(string) {
  return string.charAt(string.length - 1) }

///// Function but_last
// Returns a new `string' with all but the last character.
//
// but_last :: String -> String
function but_last(string) {
  return string.slice(0, -1) }

///// Function slice
// Returns a new `string', containing the part of the original sequence
// from [`start', `end'[.
//
// If either `start' or `end' are given negative indexes, the number is
// taken to be an offset from the end of the sequence.
//
// slice :: String, start:Number?, end:Number? -> String
function slice(string, start, end) {
  return string.slice(start, end) }

///// Function take
// Returns a new `string', from the first character up to the given
// `size'.
//
// take :: String, Number -> String
function take(string, size) {
  return string.slice(0, size) }

///// Function drop
// Returns a new `string', without the first N items.
//
// drop :: String, Number -> String
function drop(string, size) {
  return string.slice(size) }

///// Function split
// Returns a list of `String's, by breaking the original string
// everytime the predicate holds.
//
// split :: String, (Char, Number, String -> Bool) -> [String]
function split(string, predicate) {
  var i, len
  var result = []
  var start  = 0
  for (i = 0, len = string.length; i < len; ++i) {
    if (predicate(string.charAt(i), i, string)) {
      result.push(string.slice(0, i))
      start = i }}

  if (start < len) result.push(string.slice(start))
  return result }

//// -- Comparisons ----------------------------------------------------

///// Function compare
// Returns an `Ordering' from the comparison of two `String's.
//
// If `foldcase' is given and is truthy, we ignore both string's casing
// completely, such that `Foo` would equal `foO`.
//
// compare :: String, String, Bool? -> Ordering
function compare(left, right, foldcase) {
  if (foldcase) {
    left  = downcase(left)
    right = downcase(right) }

  return left < right?   -1
  :      left === right?  0
  :      /* otherwise */  1 }

///// Function equal_p
// Are both `String's equal?
//
// If `foldcase' is given and is truthy, we ignore both string's casing
// competely, such that `Foo` would equal `foO`.
//
// equal_p :: String, String, Bool? -> Bool
function equal_p(left, right, foldcase) {
  return !compare(left, right, foldcase) }

//// -- Formatting -----------------------------------------------------

///// Function format
// Evaluates a template, substituting the variables with respect to the
// environment provided by the given `mappings'.
//
// If a mapping is not given, we assume it to be empty, in which case
// the template variables are simply stripped away.
//
// A template variable is a special construct in the form:
//
//     :bnf:
//     <template-variable> ::= "{:" <any but "}"> "}"
//
// For example, provide a "Hello, world!" template, that adjusts to a
// given name, one could write:
//
//     format("Hello, {:subject}!", { subject: "world" })
//     // => "Hello, world!"
//
// A template variable can be escaped by placing a backslash between the
// open-curly braces and the colon, such that the construct would be
// output verbatim:
//
//     // Remember backslashes must be escaped inside Strings.
//     format("Hello, {\\:subject}", { subject: "world" })
//     // => "Hello, {\\:subject}"
//
//
// format :: String, { String -> String | (String... -> String) } -> String
function format(string, mappings) {
  mappings = mappings || {}
  return string.replace(/{(\\?:)([^}]+)}/g, resolve_identifier)

  function resolve_identifier(match, mod, key) {
    return starts_with_p(mod, '\\')?  '{:' + key + '}'
    :      key in mappings?           mappings[key]
    :      /* otherwise */            '' }}

//// -- Exports --------------------------------------------------------
module.exports = { repeat: repeat
                 , concatenate: concatenate

                 , trim: trim
                 , trim_left: trim_left
                 , trim_right: trim_right

                 , starts_with_p: starts_with_p
                 , ends_with_p: ends_with_p
                 , has_p: has_p
                 , empty_p: empty_p
                 , size: size
                 , count: count

                 , upcase: upcase
                 , downcase: downcase
                 , capitalise: capitalise
                 , dasherise: dasherise
                 , camelise: camelise

                 , first: first
                 , rest: rest
                 , last: last
                 , but_last: but_last
                 , slice: slice
                 , take: take
                 , drop: drop
                 , split: split

                 , compare: compare
                 , equal_p: equal_p

                 , format: format
                 }
<|endoftext|>