<commit_before>// jQuery Context Menu Plugin
//
// Version 1.01
//
// Cory S.N. LaViska
// A Beautiful Site (http://abeautifulsite.net/)
// Modified by Alexis Deveria
//
// More info: http://abeautifulsite.net/2008/09/jquery-context-menu-plugin/
//
// Terms of Use
//
// This plugin is dual-licensed under the GNU General Public License
//   and the MIT License and is copyright A Beautiful Site, LLC.
//
if(jQuery)( function() {
	$.extend($.fn, {

		contextMenu: function(o, callback) {
			// Defaults
			if( o.menu == undefined ) return false;
			if( o.inSpeed == undefined ) o.inSpeed = 150;
			if( o.outSpeed == undefined ) o.outSpeed = 75;
			// 0 needs to be -1 for expected results (no fade)
			if( o.inSpeed == 0 ) o.inSpeed = -1;
			if( o.outSpeed == 0 ) o.outSpeed = -1;
			// Loop each context menu
			$(this).each( function() {
				var el = $(this);
				var offset = $(el).offset();
				// Add contextMenu class
				$('#' + o.menu).addClass('contextMenu');
				// Simulate a true right click
				$(this).mousedown( function(e) {
					var evt = e;
					$(this).mouseup( function(e) {
						var srcElement = $(this);
						$(this).unbind('mouseup');
						if( evt.button == 2 || o.allowLeft) {
							e.stopPropagation();
							// Hide context menus that may be showing
							$(".contextMenu").hide();
							// Get this context menu
							var menu = $('#' + o.menu);

							if( $(el).hasClass('disabled') ) return false;

							// Detect mouse position
							var d = {}, x = e.pageX, y = e.pageY;

							var x_off = $(window).width() - menu.width(),
								y_off = $(window).height() - menu.height();

							if(x > x_off) x = x_off-15;
							if(y > y_off) y = y_off-30; // 30 is needed to prevent scrollbars in FF

							// Show the menu
							$(document).unbind('click');
							$(menu).css({ top: y, left: x }).fadeIn(o.inSpeed);
							// Hover events
							$(menu).find('A').mouseover( function() {
								$(menu).find('LI.hover').removeClass('hover');
								$(this).parent().addClass('hover');
							}).mouseout( function() {
								$(menu).find('LI.hover').removeClass('hover');
							});

							// Keyboard
							$(document).keypress( function(e) {
								switch( e.keyCode ) {
									case 38: // up
										if( $(menu).find('LI.hover').size() == 0 ) {
											$(menu).find('LI:last').addClass('hover');
										} else {
											$(menu).find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover');
											if( $(menu).find('LI.hover').size() == 0 ) $(menu).find('LI:last').addClass('hover');
										}
									break;
									case 40: // down
										if( $(menu).find('LI.hover').size() == 0 ) {
											$(menu).find('LI:first').addClass('hover');
										} else {
											$(menu).find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover');
											if( $(menu).find('LI.hover').size() == 0 ) $(menu).find('LI:first').addClass('hover');
										}
									break;
									case 13: // enter
										$(menu).find('LI.hover A').trigger('click');
									break;
									case 27: // esc
										$(document).trigger('click');
									break
								}
							});

							// When items are selected
							$('#' + o.menu).find('A').unbind('mouseup');
							$('#' + o.menu).find('LI:not(.disabled) A').mouseup( function() {
								$(document).unbind('click').unbind('keypress');
								$(".contextMenu").hide();
								// Callback
								if( callback ) callback( $(this).attr('href').substr(1), $(srcElement), {x: x - offset.left, y: y - offset.top, docX: x, docY: y} );
								return false;
							});

							// Hide bindings
							setTimeout( function() { // Delay for Mozilla
								$(document).click( function() {
									$(document).unbind('click').unbind('keypress');
									$(menu).fadeOut(o.outSpeed);
									return false;
								});
							}, 0);
						}
					});
				});

				// Disable text selection
				if( $.browser.mozilla ) {
					$('#' + o.menu).each( function() { $(this).css({ 'MozUserSelect' : 'none' }); });
				} else if( $.browser.msie ) {
					$('#' + o.menu).each( function() { $(this).bind('selectstart.disableTextSelect', function() { return false; }); });
				} else {
					$('#' + o.menu).each(function() { $(this).bind('mousedown.disableTextSelect', function() { return false; }); });
				}
				// Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome)
				$(el).add($('UL.contextMenu')).bind('contextmenu', function() { return false; });

			});
			return $(this);
		},

		// Disable context menu items on the fly
		disableContextMenuItems: function(o) {
			if( o == undefined ) {
				// Disable all
				$(this).find('LI').addClass('disabled');
				return( $(this) );
			}
			$(this).each( function() {
				if( o != undefined ) {
					var d = o.split(',');
					for( var i = 0; i < d.length; i++ ) {
						$(this).find('A[href="' + d[i] + '"]').parent().addClass('disabled');

					}
				}
			});
			return( $(this) );
		},

		// Enable context menu items on the fly
		enableContextMenuItems: function(o) {
			if( o == undefined ) {
				// Enable all
				$(this).find('LI.disabled').removeClass('disabled');
				return( $(this) );
			}
			$(this).each( function() {
				if( o != undefined ) {
					var d = o.split(',');
					for( var i = 0; i < d.length; i++ ) {
						$(this).find('A[href="' + d[i] + '"]').parent().removeClass('disabled');

					}
				}
			});
			return( $(this) );
		},

		// Disable context menu(s)
		disableContextMenu: function() {
			$(this).each( function() {
				$(this).addClass('disabled');
			});
			return( $(this) );
		},

		// Enable context menu(s)
		enableContextMenu: function() {
			$(this).each( function() {
				$(this).removeClass('disabled');
			});
			return( $(this) );
		},

		// Destroy context menu(s)
		destroyContextMenu: function() {
			// Destroy specified context menus
			$(this).each( function() {
				// Disable action
				$(this).unbind('mousedown').unbind('mouseup');
			});
			return( $(this) );
		}

	});
})(jQuery);<commit_msg>Made some context menu optimizations<commit_after>// jQuery Context Menu Plugin
//
// Version 1.01
//
// Cory S.N. LaViska
// A Beautiful Site (http://abeautifulsite.net/)
// Modified by Alexis Deveria
//
// More info: http://abeautifulsite.net/2008/09/jquery-context-menu-plugin/
//
// Terms of Use
//
// This plugin is dual-licensed under the GNU General Public License
//   and the MIT License and is copyright A Beautiful Site, LLC.
//
if(jQuery)( function() {
	var win = $(window);
	var doc = $(document);

	$.extend($.fn, {

		contextMenu: function(o, callback) {
			// Defaults
			if( o.menu == undefined ) return false;
			if( o.inSpeed == undefined ) o.inSpeed = 150;
			if( o.outSpeed == undefined ) o.outSpeed = 75;
			// 0 needs to be -1 for expected results (no fade)
			if( o.inSpeed == 0 ) o.inSpeed = -1;
			if( o.outSpeed == 0 ) o.outSpeed = -1;
			// Loop each context menu
			$(this).each( function() {
				var el = $(this);
				var offset = $(el).offset();

				var menu = $('#' + o.menu);

				// Add contextMenu class
				menu.addClass('contextMenu');

				// Simulate a true right click
				$(this).mousedown( function(e) {
					var evt = e;
					$(this).mouseup( function(e) {
						var srcElement = $(this);
						srcElement.unbind('mouseup');
						if( evt.button === 2 || o.allowLeft) {
							e.stopPropagation();
							// Hide context menus that may be showing
							$(".contextMenu").hide();
							// Get this context menu

							if( el.hasClass('disabled') ) return false;

							// Detect mouse position
							var d = {}, x = e.pageX, y = e.pageY;

							var x_off = win.width() - menu.width(),
								y_off = win.height() - menu.height();

							if(x > x_off - 15) x = x_off-15;
							if(y > y_off - 30) y = y_off-30; // 30 is needed to prevent scrollbars in FF

							// Show the menu
							doc.unbind('click');
							menu.css({ top: y, left: x }).fadeIn(o.inSpeed);
							// Hover events
							menu.find('A').mouseover( function() {
								menu.find('LI.hover').removeClass('hover');
								$(this).parent().addClass('hover');
							}).mouseout( function() {
								menu.find('LI.hover').removeClass('hover');
							});

							// Keyboard
							doc.keypress( function(e) {
								switch( e.keyCode ) {
									case 38: // up
										if( !menu.find('LI.hover').length ) {
											menu.find('LI:last').addClass('hover');
										} else {
											menu.find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover');
											if( !menu.find('LI.hover').length ) menu.find('LI:last').addClass('hover');
										}
									break;
									case 40: // down
										if( menu.find('LI.hover').length == 0 ) {
											menu.find('LI:first').addClass('hover');
										} else {
											menu.find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover');
											if( !menu.find('LI.hover').length ) menu.find('LI:first').addClass('hover');
										}
									break;
									case 13: // enter
										menu.find('LI.hover A').trigger('click');
									break;
									case 27: // esc
										doc.trigger('click');
									break
								}
							});

							// When items are selected
							menu.find('A').unbind('mouseup');
							menu.find('LI:not(.disabled) A').mouseup( function() {
								doc.unbind('click').unbind('keypress');
								$(".contextMenu").hide();
								// Callback
								if( callback ) callback( $(this).attr('href').substr(1), $(srcElement), {x: x - offset.left, y: y - offset.top, docX: x, docY: y} );
								return false;
							});

							// Hide bindings
							setTimeout( function() { // Delay for Mozilla
								doc.click( function() {
									doc.unbind('click').unbind('keypress');
									menu.fadeOut(o.outSpeed);
									return false;
								});
							}, 0);
						}
					});
				});

				// Disable text selection
				if( $.browser.mozilla ) {
					$('#' + o.menu).each( function() { $(this).css({ 'MozUserSelect' : 'none' }); });
				} else if( $.browser.msie ) {
					$('#' + o.menu).each( function() { $(this).bind('selectstart.disableTextSelect', function() { return false; }); });
				} else {
					$('#' + o.menu).each(function() { $(this).bind('mousedown.disableTextSelect', function() { return false; }); });
				}
				// Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome)
				$(el).add($('UL.contextMenu')).bind('contextmenu', function() { return false; });

			});
			return $(this);
		},

		// Disable context menu items on the fly
		disableContextMenuItems: function(o) {
			if( o == undefined ) {
				// Disable all
				$(this).find('LI').addClass('disabled');
				return( $(this) );
			}
			$(this).each( function() {
				if( o != undefined ) {
					var d = o.split(',');
					for( var i = 0; i < d.length; i++ ) {
						$(this).find('A[href="' + d[i] + '"]').parent().addClass('disabled');

					}
				}
			});
			return( $(this) );
		},

		// Enable context menu items on the fly
		enableContextMenuItems: function(o) {
			if( o == undefined ) {
				// Enable all
				$(this).find('LI.disabled').removeClass('disabled');
				return( $(this) );
			}
			$(this).each( function() {
				if( o != undefined ) {
					var d = o.split(',');
					for( var i = 0; i < d.length; i++ ) {
						$(this).find('A[href="' + d[i] + '"]').parent().removeClass('disabled');

					}
				}
			});
			return( $(this) );
		},

		// Disable context menu(s)
		disableContextMenu: function() {
			$(this).each( function() {
				$(this).addClass('disabled');
			});
			return( $(this) );
		},

		// Enable context menu(s)
		enableContextMenu: function() {
			$(this).each( function() {
				$(this).removeClass('disabled');
			});
			return( $(this) );
		},

		// Destroy context menu(s)
		destroyContextMenu: function() {
			// Destroy specified context menus
			$(this).each( function() {
				// Disable action
				$(this).unbind('mousedown').unbind('mouseup');
			});
			return( $(this) );
		}

	});
})(jQuery);<|endoftext|>


<commit_before>import React, {PropTypes, Component} from 'react'
import _ from 'lodash'
import classnames from 'classnames'

import TemplateDrawer from 'shared/components/TemplateDrawer'
import QueryStatus from 'shared/components/QueryStatus'

import {
  MATCH_INCOMPLETE_TEMPLATES,
  applyMasks,
  insertTempVar,
  unMask,
} from 'src/dashboards/constants'

class QueryTextArea extends Component {
  constructor(props) {
    super(props)
    this.state = {
      value: this.props.query,
      isTemplating: false,
      selectedTemplate: {
        tempVar: _.get(this.props.templates, ['0', 'tempVar'], ''),
      },
      filteredTemplates: this.props.templates,
    }

    this.handleKeyDown = ::this.handleKeyDown
    this.handleChange = ::this.handleChange
    this.handleUpdate = ::this.handleUpdate
    this.handleChooseTemplate = ::this.handleChooseTemplate
    this.handleCloseDrawer = ::this.handleCloseDrawer
    this.findTempVar = ::this.findTempVar
    this.handleTemplateReplace = ::this.handleTemplateReplace
    this.handleMouseOverTempVar = ::this.handleMouseOverTempVar
    this.handleClickTempVar = ::this.handleClickTempVar
    this.closeDrawer = ::this.closeDrawer
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.query !== nextProps.query) {
      this.setState({value: nextProps.query})
    }
  }

  handleCloseDrawer() {
    this.setState({isTemplating: false})
  }

  handleMouseOverTempVar(template) {
    this.handleTemplateReplace(template)
  }

  handleClickTempVar(template) {
    // Clicking a tempVar does the same thing as hitting 'Enter'
    this.handleTemplateReplace(template, true)
    this.closeDrawer()
  }

  closeDrawer() {
    this.setState({
      isTemplating: false,
      selectedTemplate: {
        tempVar: _.get(this.props.templates, ['0', 'tempVar'], ''),
      },
    })
  }

  handleKeyDown(e) {
    const {isTemplating, value} = this.state

    if (isTemplating) {
      switch (e.key) {
        case 'Tab':
        case 'ArrowRight':
        case 'ArrowDown':
          e.preventDefault()
          return this.handleTemplateReplace(this.findTempVar('next'))
        case 'ArrowLeft':
        case 'ArrowUp':
          e.preventDefault()
          return this.handleTemplateReplace(this.findTempVar('previous'))
        case 'Enter':
          e.preventDefault()
          this.handleTemplateReplace(this.state.selectedTemplate, true)
          return this.closeDrawer()
        case 'Escape':
          e.preventDefault()
          return this.closeDrawer()
      }
    } else if (e.key === 'Escape') {
      e.preventDefault()
      this.setState({value, isTemplating: false})
    } else if (e.key === 'Enter') {
      e.preventDefault()
      this.handleUpdate()
    }
  }

  handleTemplateReplace(selectedTemplate, replaceWholeTemplate) {
    const {selectionStart, value} = this.editor
    const {tempVar} = selectedTemplate
    const newTempVar = replaceWholeTemplate
      ? tempVar
      : tempVar.substring(0, tempVar.length - 1)

    // mask matches that will confuse our regex
    const masked = applyMasks(value)
    const matched = masked.match(MATCH_INCOMPLETE_TEMPLATES)

    let templatedValue
    if (matched) {
      templatedValue = insertTempVar(masked, newTempVar)
      templatedValue = unMask(templatedValue)
    }

    const enterModifier = replaceWholeTemplate ? 0 : -1
    const diffInLength =
      tempVar.length - _.get(matched, '0', []).length + enterModifier

    this.setState({value: templatedValue, selectedTemplate}, () =>
      this.editor.setSelectionRange(
        selectionStart + diffInLength,
        selectionStart + diffInLength
      )
    )
  }

  findTempVar(direction) {
    const {filteredTemplates: templates} = this.state
    const {selectedTemplate} = this.state

    const i = _.findIndex(templates, selectedTemplate)
    const lastIndex = templates.length - 1

    if (i >= 0) {
      if (direction === 'next') {
        return templates[(i + 1) % templates.length]
      }

      if (direction === 'previous') {
        if (i === 0) {
          return templates[lastIndex]
        }

        return templates[i - 1]
      }
    }

    return templates[0]
  }

  handleChange() {
    const {templates} = this.props
    const {selectedTemplate} = this.state
    const value = this.editor.value

    // mask matches that will confuse our regex
    const masked = applyMasks(value)
    const matched = masked.match(MATCH_INCOMPLETE_TEMPLATES)

    if (matched && !_.isEmpty(templates)) {
      // maintain cursor poition
      const start = this.editor.selectionStart

      const end = this.editor.selectionEnd
      const filterText = matched[0].substr(1).toLowerCase()

      const filteredTemplates = templates.filter(t =>
        t.tempVar.toLowerCase().includes(filterText)
      )

      const found = filteredTemplates.find(
        t => t.tempVar === selectedTemplate && selectedTemplate.tempVar
      )
      const newTemplate = found ? found : filteredTemplates[0]

      this.setState({
        isTemplating: true,
        selectedTemplate: newTemplate,
        filteredTemplates,
        value,
      })
      this.editor.setSelectionRange(start, end)
    } else {
      this.setState({isTemplating: false, value})
    }
  }

  handleUpdate() {
    this.props.onUpdate(this.state.value)
  }

  handleChooseTemplate(template) {
    this.setState({value: template.query})
  }

  handleSelectTempVar(tempVar) {
    this.setState({selectedTemplate: tempVar})
  }

  render() {
    const {config: {status}} = this.props
    const {
      value,
      isTemplating,
      selectedTemplate,
      filteredTemplates,
    } = this.state

    return (

        <textarea
          className="query-editor--field"
          onChange={this.handleChange}
          onKeyDown={this.handleKeyDown}
          onBlur={this.handleUpdate}
          ref={editor => (this.editor = editor)}
          value={value}
          placeholder="Enter a query or select database, measurement, and field below and have us build one for you..."
          autoComplete="off"
          spellCheck="false"
          data-test="query-editor-field"
        />

              <QueryStatus status={status} />

              {isTemplating
                ? <TemplateDrawer
                    onClickTempVar={this.handleClickTempVar}
                    templates={filteredTemplates}
                    selected={selectedTemplate}
                    onMouseOverTempVar={this.handleMouseOverTempVar}
                    handleClickOutside={this.handleCloseDrawer}
                  />
                : null}

    )
  }
}

const {arrayOf, bool, func, shape, string} = PropTypes

QueryTextArea.propTypes = {
  query: string.isRequired,
  onUpdate: func.isRequired,
  config: shape().isRequired,
  isInDataExplorer: bool,
  templates: arrayOf(
    shape({
      tempVar: string.isRequired,
    })
  ),
}

export default QueryTextArea
<commit_msg>Add FillQuery to Query builder in CEO<commit_after>import React, {PropTypes, Component} from 'react'
import _ from 'lodash'
import classnames from 'classnames'

import FillQuery from 'shared/components/FillQuery'
import TemplateDrawer from 'shared/components/TemplateDrawer'
import QueryStatus from 'shared/components/QueryStatus'

import {
  MATCH_INCOMPLETE_TEMPLATES,
  applyMasks,
  insertTempVar,
  unMask,
} from 'src/dashboards/constants'

class QueryTextArea extends Component {
  constructor(props) {
    super(props)
    this.state = {
      value: this.props.query,
      isTemplating: false,
      selectedTemplate: {
        tempVar: _.get(this.props.templates, ['0', 'tempVar'], ''),
      },
      filteredTemplates: this.props.templates,
    }

    this.handleKeyDown = ::this.handleKeyDown
    this.handleChange = ::this.handleChange
    this.handleUpdate = ::this.handleUpdate
    this.handleChooseTemplate = ::this.handleChooseTemplate
    this.handleCloseDrawer = ::this.handleCloseDrawer
    this.findTempVar = ::this.findTempVar
    this.handleTemplateReplace = ::this.handleTemplateReplace
    this.handleMouseOverTempVar = ::this.handleMouseOverTempVar
    this.handleClickTempVar = ::this.handleClickTempVar
    this.closeDrawer = ::this.closeDrawer
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.query !== nextProps.query) {
      this.setState({value: nextProps.query})
    }
  }

  handleCloseDrawer() {
    this.setState({isTemplating: false})
  }

  handleMouseOverTempVar(template) {
    this.handleTemplateReplace(template)
  }

  handleClickTempVar(template) {
    // Clicking a tempVar does the same thing as hitting 'Enter'
    this.handleTemplateReplace(template, true)
    this.closeDrawer()
  }

  closeDrawer() {
    this.setState({
      isTemplating: false,
      selectedTemplate: {
        tempVar: _.get(this.props.templates, ['0', 'tempVar'], ''),
      },
    })
  }

  handleKeyDown(e) {
    const {isTemplating, value} = this.state

    if (isTemplating) {
      switch (e.key) {
        case 'Tab':
        case 'ArrowRight':
        case 'ArrowDown':
          e.preventDefault()
          return this.handleTemplateReplace(this.findTempVar('next'))
        case 'ArrowLeft':
        case 'ArrowUp':
          e.preventDefault()
          return this.handleTemplateReplace(this.findTempVar('previous'))
        case 'Enter':
          e.preventDefault()
          this.handleTemplateReplace(this.state.selectedTemplate, true)
          return this.closeDrawer()
        case 'Escape':
          e.preventDefault()
          return this.closeDrawer()
      }
    } else if (e.key === 'Escape') {
      e.preventDefault()
      this.setState({value, isTemplating: false})
    } else if (e.key === 'Enter') {
      e.preventDefault()
      this.handleUpdate()
    }
  }

  handleTemplateReplace(selectedTemplate, replaceWholeTemplate) {
    const {selectionStart, value} = this.editor
    const {tempVar} = selectedTemplate
    const newTempVar = replaceWholeTemplate
      ? tempVar
      : tempVar.substring(0, tempVar.length - 1)

    // mask matches that will confuse our regex
    const masked = applyMasks(value)
    const matched = masked.match(MATCH_INCOMPLETE_TEMPLATES)

    let templatedValue
    if (matched) {
      templatedValue = insertTempVar(masked, newTempVar)
      templatedValue = unMask(templatedValue)
    }

    const enterModifier = replaceWholeTemplate ? 0 : -1
    const diffInLength =
      tempVar.length - _.get(matched, '0', []).length + enterModifier

    this.setState({value: templatedValue, selectedTemplate}, () =>
      this.editor.setSelectionRange(
        selectionStart + diffInLength,
        selectionStart + diffInLength
      )
    )
  }

  findTempVar(direction) {
    const {filteredTemplates: templates} = this.state
    const {selectedTemplate} = this.state

    const i = _.findIndex(templates, selectedTemplate)
    const lastIndex = templates.length - 1

    if (i >= 0) {
      if (direction === 'next') {
        return templates[(i + 1) % templates.length]
      }

      if (direction === 'previous') {
        if (i === 0) {
          return templates[lastIndex]
        }

        return templates[i - 1]
      }
    }

    return templates[0]
  }

  handleChange() {
    const {templates} = this.props
    const {selectedTemplate} = this.state
    const value = this.editor.value

    // mask matches that will confuse our regex
    const masked = applyMasks(value)
    const matched = masked.match(MATCH_INCOMPLETE_TEMPLATES)

    if (matched && !_.isEmpty(templates)) {
      // maintain cursor poition
      const start = this.editor.selectionStart

      const end = this.editor.selectionEnd
      const filterText = matched[0].substr(1).toLowerCase()

      const filteredTemplates = templates.filter(t =>
        t.tempVar.toLowerCase().includes(filterText)
      )

      const found = filteredTemplates.find(
        t => t.tempVar === selectedTemplate && selectedTemplate.tempVar
      )
      const newTemplate = found ? found : filteredTemplates[0]

      this.setState({
        isTemplating: true,
        selectedTemplate: newTemplate,
        filteredTemplates,
        value,
      })
      this.editor.setSelectionRange(start, end)
    } else {
      this.setState({isTemplating: false, value})
    }
  }

  handleUpdate() {
    this.props.onUpdate(this.state.value)
  }

  handleChooseTemplate(template) {
    this.setState({value: template.query})
  }

  handleSelectTempVar(tempVar) {
    this.setState({selectedTemplate: tempVar})
  }

  render() {
    const {config: {status}} = this.props
    const {
      value,
      isTemplating,
      selectedTemplate,
      filteredTemplates,
    } = this.state

    return (

        <textarea
          className="query-editor--field"
          onChange={this.handleChange}
          onKeyDown={this.handleKeyDown}
          onBlur={this.handleUpdate}
          ref={editor => (this.editor = editor)}
          value={value}
          placeholder="Enter a query or select database, measurement, and field below and have us build one for you..."
          autoComplete="off"
          spellCheck="false"
          data-test="query-editor-field"
        />

              <QueryStatus status={status}>
                <FillQuery
                  onSelection={e => {
                    console.log(e)
                  }}
                />
              </QueryStatus>

              {isTemplating
                ? <TemplateDrawer
                    onClickTempVar={this.handleClickTempVar}
                    templates={filteredTemplates}
                    selected={selectedTemplate}
                    onMouseOverTempVar={this.handleMouseOverTempVar}
                    handleClickOutside={this.handleCloseDrawer}
                  />
                : null}

    )
  }
}

const {arrayOf, bool, func, shape, string} = PropTypes

QueryTextArea.propTypes = {
  query: string.isRequired,
  onUpdate: func.isRequired,
  config: shape().isRequired,
  isInDataExplorer: bool,
  templates: arrayOf(
    shape({
      tempVar: string.isRequired,
    })
  ),
}

export default QueryTextArea
<|endoftext|>


<commit_before>'use strict';
(function(module) {

  var indexView = {};

  var template = Handlebars.compile($('#registeredTemplate').text());

  var initialLoad = function (event) {
    $('.page-content').hide();
    $('#landingPage').show();
  };
  initialLoad();

  //**This function is being commented out, so page.js uses the routes file instead -MM**

  // var handleTheSectionView = function () {
  //   $('#nav-bar').on('click', '.nav-item', function(event) {
  //     event.preventDefault();
  //     $('.page-content').hide();
  //     $(`#${$(this).data('content')}`).fadeIn(400);
  //   });
  // }
  //
  // handleTheSectionView();

  var handleTheReportODButton = function () {
    $('#reportOD').on('click', function(event) {
      event.preventDefault();
      $('.page-content').hide();
      $('#informational').fadeIn(400);
    });
  }
  handleTheReportODButton();

  var handleTheRegisterButton = function () {
    $('#register').on('click', function(event) {
      event.preventDefault();
      $('.page-content').hide();
      $('#registerCarrier').fadeIn(400);
    });
  }
  handleTheRegisterButton();

  var handleTheYesReportODButton = function () {
    $('#yesReportOD').on('click', function(event) {
      event.preventDefault();
      $('.page-content').hide();
      $('#mapSection').fadeIn(400);
      $('#mapInfo').fadeIn(400);
    });
  }
  handleTheYesReportODButton();

  var handleInfoFormSubmit = function () {
    $('#carrierInfo').submit(function(event) {
      event.preventDefault();
      var carrierData = {
        name: $(this).find('#name').val(),
        number: parseInt($(this).find('#number').val()),
        address: $(this).find('#address').val(),
        city: $(this).find('#city').val(),
        state: $(this).find('#state').val(),
        zip: parseInt($(this).find('#zip').val()),
        email: $(this).find('#email').val()
      }
      console.log(carrierData);
      Carrier.postData(carrierData);
      $('.page-content').hide();
      $('#confirmRegistration').fadeIn(500);
      // TODO investigate the serialize method of jQuery for form data submission
      //TODO figure out how to clear form fields upon submission
      //TODO ensure that form entries are posting to DB properly
    });
  }
  handleInfoFormSubmit();

})(window);
<commit_msg>Added form refresh functionality<commit_after>'use strict';
(function(module) {

  var indexView = {};

  var template = Handlebars.compile($('#registeredTemplate').text());

  var initialLoad = function (event) {
    $('.page-content').hide();
    $('#landingPage').show();
  };
  initialLoad();

  //**This function is being commented out, so page.js uses the routes file instead -MM**

  // var handleTheSectionView = function () {
  //   $('#nav-bar').on('click', '.nav-item', function(event) {
  //     event.preventDefault();
  //     $('.page-content').hide();
  //     $(`#${$(this).data('content')}`).fadeIn(400);
  //   });
  // }
  //
  // handleTheSectionView();

  var handleTheReportODButton = function () {
    $('#reportOD').on('click', function(event) {
      event.preventDefault();
      $('.page-content').hide();
      $('#informational').fadeIn(400);
    });
  }
  handleTheReportODButton();

  var handleTheRegisterButton = function () {
    $('#register').on('click', function(event) {
      event.preventDefault();
      $('.page-content').hide();
      $('#registerCarrier').fadeIn(400);
    });
  }
  handleTheRegisterButton();

  var handleTheYesReportODButton = function () {
    $('#yesReportOD').on('click', function(event) {
      event.preventDefault();
      $('.page-content').hide();
      $('#mapSection').fadeIn(400);
      $('#mapInfo').fadeIn(400);
    });
  }
  handleTheYesReportODButton();

  var handleInfoFormSubmit = function () {
    $('#carrierInfo').submit(function(event) {
      event.preventDefault();
      var carrierData = {
        name: $(this).find('#name').val(),
        number: parseInt($(this).find('#number').val()),
        address: $(this).find('#address').val(),
        city: $(this).find('#city').val(),
        state: $(this).find('#state').val(),
        zip: parseInt($(this).find('#zip').val()),
        email: $(this).find('#email').val()
      }
      console.log(carrierData);
      Carrier.postData(carrierData);
      $('.page-content').hide();
      $('#carrierInfo')[0].reset();
      $('#confirmRegistration').fadeIn(500);
      // TODO investigate the serialize method of jQuery for form data submission
    });
  }
  handleInfoFormSubmit();

})(window);
<|endoftext|>


<commit_before>(function(){

  var builder = require('botbuilder');

  const TENANT_ID = process.env.TENANT_ID;
  const BOT_NAME = process.env.BOT_NAME;
  const KEYWORDS_REGEX = process.env.KEYWORDS_REGEX;

  module.exports.setupBot = function(connector){

    var bot = new builder.UniversalBot(connector);

    bot.dialog('/', function (session) {
      var data = getMessageData(session);

      for(var key in data){
        console.log(key,JSON.stringify(data[key]));
      }

      if(data.tenantId != TENANT_ID){
        session.send('Sorry. This client is unsupported. Please set up a new bot for your own client.');
        return;
      }

      if(data.isGroup && data.mentions.length > 0 && new RegExp(KEYWORDS_REGEX, 'i').test(data.text)){
        session.beginDialog('/givethanks');
      }
      else if(!data.isGroup){
        session.beginDialog('/getinfo');
      }

    });

    bot.dialog('/givethanks',function(session){
      //We've been tagged in a Chat
      //We have single or multiple user mentions
      //And the chat has a keyword in it.
      var data = getMessageData(session);
      var names = [];
      data.mentions.forEach(function(mention){
        names.push(formatName(mention.mentioned.name));
      });

      var last = names.pop()
      if(names.length === 0){
        names = last;
      }
      else{
        names = names.join(', ') + ' and ' + last;
      }

      session.send("Aaaay! Great job " + names + "!");
      session.endDialog(formatName(data.userName) + ' sent you recognition!');
    });

    bot.dialog('/getinfo',function(session){
      //We're in a single chat
      //User wants some information
      var data = getMessageData(session);
      session.endDialog('Ayyy. This hasn\'t been implemented yet. At some point, ' +
      'I should be able to give you some answers here, but not yet!')
    });

    return bot;
  }

  function getMessageData(session){
    var output = {};
    var msg = session.message;

    output.textFormat = msg.textFormat;
    output.text = msg.text;
    output.mentions = [];
    msg.entities.forEach(function(e){
      if(e.type === 'mention' && e.mentioned.name !== BOT_NAME){
        output.mentions.push(e);
      }
    });
    if(msg.sourceEvent.teamsChannelId){
      output.teamsChannelId = msg.sourceEvent.teamsChannelId;
    }
    if(msg.sourceEvent.teamsTeamId){
      output.teamsTeamId = msg.sourceEvent.teamsTeamId;
    }
    output.tenantId = msg.sourceEvent.tenant.id;
    output.addressId = msg.address.id;
    output.channelId = msg.address.channelId;
    output.isGroup = (msg.address.conversation.isGroup) ? true : false;
    output.conversationId = msg.address.conversation.id;
    output.userId = msg.user.id;
    output.userName = msg.user.name;

    return output;
  }

  function formatName(name){
    var names = name.split(', ');
    return names[1] + ' ' + names[0];
  }

}());
<commit_msg>Adding some logging<commit_after>(function(){

  var builder = require('botbuilder');

  const TENANT_ID = process.env.TENANT_ID;
  const BOT_NAME = process.env.BOT_NAME;
  const KEYWORDS_REGEX = process.env.KEYWORDS_REGEX;

  module.exports.setupBot = function(connector){

    var bot = new builder.UniversalBot(connector);

    bot.dialog('/', function (session) {
      var data = getMessageData(session);

      for(var key in data){
        console.log(key,JSON.stringify(data[key]));
      }
      console.log('-----');

      if(data.tenantId != TENANT_ID){
        session.send('Sorry. This client is unsupported. Please set up a new bot for your own client.');
        return;
      }

      if(data.isGroup && data.mentions.length > 0 && new RegExp(KEYWORDS_REGEX, 'i').test(data.text)){
        session.beginDialog('/givethanks');
      }
      else if(!data.isGroup){
        session.beginDialog('/getinfo');
      }

    });

    bot.dialog('/givethanks',function(session){
      //We've been tagged in a Chat
      //We have single or multiple user mentions
      //And the chat has a keyword in it.
      var data = getMessageData(session);
      var names = [];
      data.mentions.forEach(function(mention){
        names.push(formatName(mention.mentioned.name));
      });

      var last = names.pop()
      if(names.length === 0){
        names = last;
      }
      else{
        names = names.join(', ') + ' and ' + last;
      }

      session.send("Aaaay! Great job " + names + "!");
      session.endDialog(formatName(data.userName) + ' sent you recognition!');
    });

    bot.dialog('/getinfo',function(session){
      //We're in a single chat
      //User wants some information
      var data = getMessageData(session);
      session.endDialog('Ayyy. This hasn\'t been implemented yet. At some point, ' +
      'I should be able to give you some answers here, but not yet!')
    });

    return bot;
  }

  function getMessageData(session){
    var output = {};
    var msg = session.message;

    output.textFormat = msg.textFormat;
    output.text = msg.text;
    output.mentions = [];
    msg.entities.forEach(function(e){
      if(e.type === 'mention' && e.mentioned.name !== BOT_NAME){
        output.mentions.push(e);
      }
    });
    if(msg.sourceEvent.teamsChannelId){
      output.teamsChannelId = msg.sourceEvent.teamsChannelId;
    }
    if(msg.sourceEvent.teamsTeamId){
      output.teamsTeamId = msg.sourceEvent.teamsTeamId;
    }
    output.tenantId = msg.sourceEvent.tenant.id;
    output.addressId = msg.address.id;
    output.channelId = msg.address.channelId;
    output.isGroup = (msg.address.conversation.isGroup) ? true : false;
    output.conversationId = msg.address.conversation.id;
    output.userId = msg.user.id;
    output.userName = msg.user.name;

    return output;
  }

  function formatName(name){
    var names = name.split(', ');
    return names[1] + ' ' + names[0];
  }

}());
<|endoftext|>


<commit_before>// This module defines a reusable Chord Diagram using D3.
define(function(require) {

  // Load D3 v4 via our custom bundle build output.
  var d3 = require("../d3/d3.min");

  // Constructor function for a Chord Diagram.
  // Accepts a container `div` DOM element.
  return function ChordDiagram(div){

    // Configuration parameters.
    var width = 500,
        height = 500,
        outerPadding = 50,
        arcThickness = 20,
        padAngle = 0.07,
        outerRadius = width / 2 - outerPadding,
        innerRadius = outerRadius - arcThickness,
        labelPadding = 10;

    // These "column" variables represent keys in the row objects of the input table.
    // Kibana's `tabify` happens to give us column names "1", "2", and "3".
    // These correspond to the Schemas defined for the plugin.
    var chordWeightColumn = "1",
        chordSourceColumn = "2",
        chordDestinationColumn = "3";

    // Accessor functions for columns.
    var weight = function (d){ return d[chordWeightColumn]; },
        source = function (d){ return d[chordSourceColumn]; },
        destination = function (d){ return d[chordDestinationColumn]; };

    // D3 Local objects for DOM-local storage of label angles and
    // whether or not labels should be flipped upside-down.
    var angle = d3.local(),
        flip = d3.local();

    // DOM Elements.
    var svg = d3.select(div).append("svg")
          .attr("width", width)
          .attr("height", height),
        g = svg.append("g")
          .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"),
        ribbonsG = g.append("g"),
        chordGroupsG = g.append("g");

    // D3 layouts, shapes and scales.
    var ribbon = d3.ribbon()
          .radius(innerRadius),
        chord = d3.chord()
          .padAngle(padAngle),
        color = d3.scaleOrdinal()
          .range(d3.schemeCategory20),
        arc = d3.arc()
          .innerRadius(innerRadius)
          .outerRadius(outerRadius);

    // Renders the given data as a chord diagram.
    function render(data){

      // Pre-process the data and calculate the Chord Diagram layout.
      var matrix = generateMatrix(data),
          chords = chord(matrix);

      // Render the ribbons of the Chord Diagram (the connecting fibers inside the circle).
      var ribbons = ribbonsG
        .selectAll("path")
          .data(chords);
      ribbons.enter().append("path").merge(ribbons)
        .attr("d", ribbon)
        .style("fill", function(d) { return color(d.source.index); })
        .style("opacity", 0.6)
        .style("stroke", "black")
        .style("stroke-opacity", 0.2)
        .on("mousedown", function (d){
          console.log(d);
        });
      ribbons.exit().remove();

      // Scaffold the chord groups.
      var chordGroups = chordGroupsG.selectAll("g").data(chords.groups);
      var chordGroupsEnter = chordGroups.enter().append("g");
      chordGroupsEnter.append("text");
      chordGroupsEnter.append("path");
      chordGroups.exit().remove();
      chordGroups = chordGroups.merge(chordGroupsEnter);

      // Add labels
      chordGroups
        .select("text")
          .each(function(d) {
            angle.set(this, (d.startAngle + d.endAngle) / 2);
            flip.set(this, angle.get(this) > Math.PI);
          })
          .attr("transform", function(d) {
            return [
              "rotate(" + (angle.get(this) / Math.PI * 180 - 90) + ")",
              "translate(" + (outerRadius + labelPadding) + ")",
              flip.get(this) ? "rotate(180)" : ""
            ].join("");
          })
          .attr("text-anchor", function(d) {
            return flip.get(this) ? "end" : "start";
          })
          .attr("alignment-baseline", "central")
          .text(function(d) {
            return matrix.names[d.index];
          });

      // Render the chord group arcs.
      chordGroups
        .select("path")
          .attr("d", arc)
          .style("fill", function(group) {
            return color(group.index);
          });

    }

    // Generates a matrix (2D array) from the given data, which is expected to
    // have fields {origin, destination, count}. The matrix data structure is required
    // for use with the D3 Chord layout.
    function generateMatrix(data){
      var indices = {},
          matrix = [],
          names = [],
          n = 0, i, j;

      function recordIndex(name){
        if( !(name in indices) ){
          indices[name] = n++;
          names.push(name);
        }
      }

      data.forEach(function (d){
        recordIndex(source(d));
        recordIndex(destination(d));
      });

      for(i = 0; i < n; i++){
        matrix.push([]);
        for(j = 0; j < n; j++){
          matrix[i].push(0);
        }
      }

      data.forEach(function (d){
        i = indices[source(d)];
        j = indices[destination(d)];
        matrix[i][j] = weight(d);
      });

      matrix.names = names;

      return matrix;
    }

    return render;
  }
});
<commit_msg>Extract source and destination names from clicked ribbon. Closes #23<commit_after>// This module defines a reusable Chord Diagram using D3.
define(function(require) {

  // Load D3 v4 via our custom bundle build output.
  var d3 = require("../d3/d3.min");

  // Constructor function for a Chord Diagram.
  // Accepts a container `div` DOM element.
  return function ChordDiagram(div){

    // Configuration parameters.
    var width = 500,
        height = 500,
        outerPadding = 50,
        arcThickness = 20,
        padAngle = 0.07,
        outerRadius = width / 2 - outerPadding,
        innerRadius = outerRadius - arcThickness,
        labelPadding = 10;

    // These "column" variables represent keys in the row objects of the input table.
    // Kibana's `tabify` happens to give us column names "1", "2", and "3".
    // These correspond to the Schemas defined for the plugin.
    var chordWeightColumn = "1",
        chordSourceColumn = "2",
        chordDestinationColumn = "3";

    // Accessor functions for columns.
    var weight = function (d){ return d[chordWeightColumn]; },
        source = function (d){ return d[chordSourceColumn]; },
        destination = function (d){ return d[chordDestinationColumn]; };

    // D3 Local objects for DOM-local storage of label angles and
    // whether or not labels should be flipped upside-down.
    var angle = d3.local(),
        flip = d3.local();

    // DOM Elements.
    var svg = d3.select(div).append("svg")
          .attr("width", width)
          .attr("height", height),
        g = svg.append("g")
          .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"),
        ribbonsG = g.append("g"),
        chordGroupsG = g.append("g");

    // D3 layouts, shapes and scales.
    var ribbon = d3.ribbon()
          .radius(innerRadius),
        chord = d3.chord()
          .padAngle(padAngle),
        color = d3.scaleOrdinal()
          .range(d3.schemeCategory20),
        arc = d3.arc()
          .innerRadius(innerRadius)
          .outerRadius(outerRadius);

    // Renders the given data as a chord diagram.
    function render(data){

      // Pre-process the data and calculate the Chord Diagram layout.
      var matrix = generateMatrix(data),
          chords = chord(matrix);

      // Render the ribbons of the Chord Diagram (the connecting fibers inside the circle).
      var ribbons = ribbonsG
        .selectAll("path")
          .data(chords);
      ribbons.enter().append("path").merge(ribbons)
        .attr("d", ribbon)
        .style("fill", function(d) { return color(d.source.index); })
        .style("opacity", 0.6)
        .style("stroke", "black")
        .style("stroke-opacity", 0.2)
        .on("mousedown", function (d){
          console.log(d);
          console.log("source: " + matrix.names[d.source.index];
          console.log("destination: " + matrix.names[d.destination.index];
        });
      ribbons.exit().remove();

      // Scaffold the chord groups.
      var chordGroups = chordGroupsG.selectAll("g").data(chords.groups);
      var chordGroupsEnter = chordGroups.enter().append("g");
      chordGroupsEnter.append("text");
      chordGroupsEnter.append("path");
      chordGroups.exit().remove();
      chordGroups = chordGroups.merge(chordGroupsEnter);

      // Add labels
      chordGroups
        .select("text")
          .each(function(d) {
            angle.set(this, (d.startAngle + d.endAngle) / 2);
            flip.set(this, angle.get(this) > Math.PI);
          })
          .attr("transform", function(d) {
            return [
              "rotate(" + (angle.get(this) / Math.PI * 180 - 90) + ")",
              "translate(" + (outerRadius + labelPadding) + ")",
              flip.get(this) ? "rotate(180)" : ""
            ].join("");
          })
          .attr("text-anchor", function(d) {
            return flip.get(this) ? "end" : "start";
          })
          .attr("alignment-baseline", "central")
          .text(function(d) {
            return matrix.names[d.index];
          });

      // Render the chord group arcs.
      chordGroups
        .select("path")
          .attr("d", arc)
          .style("fill", function(group) {
            return color(group.index);
          });

    }

    // Generates a matrix (2D array) from the given data, which is expected to
    // have fields {origin, destination, count}. The matrix data structure is required
    // for use with the D3 Chord layout.
    function generateMatrix(data){
      var indices = {},
          matrix = [],
          names = [],
          n = 0, i, j;

      function recordIndex(name){
        if( !(name in indices) ){
          indices[name] = n++;
          names.push(name);
        }
      }

      data.forEach(function (d){
        recordIndex(source(d));
        recordIndex(destination(d));
      });

      for(i = 0; i < n; i++){
        matrix.push([]);
        for(j = 0; j < n; j++){
          matrix[i].push(0);
        }
      }

      data.forEach(function (d){
        i = indices[source(d)];
        j = indices[destination(d)];
        matrix[i][j] = weight(d);
      });

      matrix.names = names;

      return matrix;
    }

    return render;
  }
});
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 Steven Soloff
 *
 * This is free software: you can redistribute it and/or modify it under the
 * terms of the MIT License (https://opensource.org/licenses/MIT).
 * This software comes with ABSOLUTELY NO WARRANTY.
 */

'use strict';

/**
 * The eval module is used to submit the expression to be evaluated and
 * configure all associated options for the evaluation operation.
 *
 * @module eval/index
 */

var $ = require('jquery'),
    fs = require('fs'),
    jQueryMap = {};

function clearExpressionText() {
    jQueryMap.$expressionText.val('');
}

function evaluateExpression(expressionText) {
    var randomNumberGeneratorJson,
        requestBody;

    requestBody = {
        expression: {
            text: expressionText
        }
    };

    randomNumberGeneratorJson = jQueryMap.$randomNumberGeneratorJson.val();
    if (randomNumberGeneratorJson) {
        requestBody.randomNumberGenerator = JSON.parse(randomNumberGeneratorJson);
    }

    $.postJSON(
        '/expression/evaluate',
        requestBody,
        onEvaluateExpressionResponseSuccess,
        onEvaluateExpressionResponseError
    );
}

function getExpressionText() {
    var expressionText,
        roundingFunction;

    expressionText = jQueryMap.$expressionText.val();
    roundingFunction = $('input[name="roundingMode"]:checked').val();
    if (roundingFunction) {
        expressionText = roundingFunction + '(' + expressionText + ')';
    }
    return expressionText;
}

function hideErrorMessage() {
    jQueryMap.$errorMessage.invisible();
}

function hideHelp() {
    jQueryMap.$help.hide();
}

function initController() {
    jQueryMap.$expressionForm.submit(function (event) {
        evaluateExpression(getExpressionText());
        event.preventDefault();
    });
    jQueryMap.$toggleHelp.click(toggleHelp);
}

function initJQueryMap($container) {
    jQueryMap = {
        $container: $container,
        $errorMessage: $container.find('#main-eval-errorMessage'),
        $expressionForm: $container.find('#main-eval-expressionForm'),
        $expressionText: $container.find('#main-eval-expressionText'),
        $help: $container.find('#main-eval-help'),
        $randomNumberGeneratorJson: $container.find('#main-eval-randomNumberGeneratorJson'),
        $toggleHelp: $container.find('#main-eval-toggleHelp')
    };
}

/**
 * Initializes the eval module.
 *
 * @memberOf module:eval/index
 *
 * @param {Object!} $container - A jQuery collection that represents a
 *      single DOM element to be used as the container for the eval
 *      controls.
 */
function initModule($container) {
    $container.html(fs.readFileSync(__dirname + '/index.html', 'utf8'));

    initJQueryMap($container);
    initView();
    initController();

    $.gevent.subscribe(jQueryMap.$container, 'main-evaluateexpression', onEvaluateExpression);
}

function initView() {
    hideHelp();
    hideErrorMessage();
}

function onEvaluateExpression(event, expressionText) {
    evaluateExpression(expressionText);
}

function onEvaluateExpressionResponseError(jqxhr) {
    var responseBody = jqxhr.responseJSON;

    if (responseBody && responseBody.error) {
        showErrorMessage(responseBody.error.message);
    }
}

function onEvaluateExpressionResponseSuccess(responseBody) {
    clearExpressionText();
    hideErrorMessage();

    $.gevent.publish('main-expressionevaluated', [responseBody]);
}

function showErrorMessage(message) {
    jQueryMap.$errorMessage.text(message).visible();
}

function toggleHelp() {
    var newHelpVisible,
        oldHelpVisible;

    oldHelpVisible = jQueryMap.$help.is(':visible');
    jQueryMap.$help.toggle(400);

    newHelpVisible = !oldHelpVisible;
    jQueryMap.$toggleHelp.text(newHelpVisible ? 'hide help' : 'help');
}

module.exports = {
    initModule: initModule
};
<commit_msg>Fix intermittently failing client acceptance test<commit_after>/*
 * Copyright (c) 2016 Steven Soloff
 *
 * This is free software: you can redistribute it and/or modify it under the
 * terms of the MIT License (https://opensource.org/licenses/MIT).
 * This software comes with ABSOLUTELY NO WARRANTY.
 */

'use strict';

/**
 * The eval module is used to submit the expression to be evaluated and
 * configure all associated options for the evaluation operation.
 *
 * @module eval/index
 */

var $ = require('jquery'),
    fs = require('fs'),
    jQueryMap = {};

function clearExpressionText() {
    jQueryMap.$expressionText.val('');
}

function evaluateExpression(expressionText) {
    var randomNumberGeneratorJson,
        requestBody;

    if (!expressionText) {
        return;
    }

    requestBody = {
        expression: {
            text: expressionText
        }
    };

    randomNumberGeneratorJson = jQueryMap.$randomNumberGeneratorJson.val();
    if (randomNumberGeneratorJson) {
        requestBody.randomNumberGenerator = JSON.parse(randomNumberGeneratorJson);
    }

    $.postJSON(
        '/expression/evaluate',
        requestBody,
        onEvaluateExpressionResponseSuccess,
        onEvaluateExpressionResponseError
    );
}

function getExpressionText() {
    var expressionText,
        roundingFunction;

    expressionText = jQueryMap.$expressionText.val();
    roundingFunction = $('input[name="roundingMode"]:checked').val();
    if (roundingFunction) {
        expressionText = roundingFunction + '(' + expressionText + ')';
    }
    return expressionText;
}

function hideErrorMessage() {
    jQueryMap.$errorMessage.invisible();
}

function hideHelp() {
    jQueryMap.$help.hide();
}

function initController() {
    jQueryMap.$expressionForm.submit(function (event) {
        evaluateExpression(getExpressionText());
        event.preventDefault();
    });
    jQueryMap.$toggleHelp.click(toggleHelp);
}

function initJQueryMap($container) {
    jQueryMap = {
        $container: $container,
        $errorMessage: $container.find('#main-eval-errorMessage'),
        $expressionForm: $container.find('#main-eval-expressionForm'),
        $expressionText: $container.find('#main-eval-expressionText'),
        $help: $container.find('#main-eval-help'),
        $randomNumberGeneratorJson: $container.find('#main-eval-randomNumberGeneratorJson'),
        $toggleHelp: $container.find('#main-eval-toggleHelp')
    };
}

/**
 * Initializes the eval module.
 *
 * @memberOf module:eval/index
 *
 * @param {Object!} $container - A jQuery collection that represents a
 *      single DOM element to be used as the container for the eval
 *      controls.
 */
function initModule($container) {
    $container.html(fs.readFileSync(__dirname + '/index.html', 'utf8'));

    initJQueryMap($container);
    initView();
    initController();

    $.gevent.subscribe(jQueryMap.$container, 'main-evaluateexpression', onEvaluateExpression);
}

function initView() {
    hideHelp();
    hideErrorMessage();
}

function onEvaluateExpression(event, expressionText) {
    evaluateExpression(expressionText);
}

function onEvaluateExpressionResponseError(jqxhr) {
    var responseBody = jqxhr.responseJSON;

    if (responseBody && responseBody.error) {
        showErrorMessage(responseBody.error.message);
    }
}

function onEvaluateExpressionResponseSuccess(responseBody) {
    clearExpressionText();
    hideErrorMessage();

    $.gevent.publish('main-expressionevaluated', [responseBody]);
}

function showErrorMessage(message) {
    jQueryMap.$errorMessage.text(message).visible();
}

function toggleHelp() {
    var newHelpVisible,
        oldHelpVisible;

    oldHelpVisible = jQueryMap.$help.is(':visible');
    jQueryMap.$help.toggle(400);

    newHelpVisible = !oldHelpVisible;
    jQueryMap.$toggleHelp.text(newHelpVisible ? 'hide help' : 'help');
}

module.exports = {
    initModule: initModule
};
<|endoftext|>


<commit_before>fileUploader: null,

ready: function() {
	var field = this;

	this.fileUploader = new qq.FileUploader({
		element: field.$(".file-uploader").get(0),
		action: "/upload/" + cm.options.siteId + "/?field=" + field.getClass(),
		multiple: !field.getOption("cardinality") || field.getOption("cardinality") > 1,
		allowedExtensions: field.getOption("allowedExtensions"),
		template: field.$(".file-uploader").html(),
		fileTemplate: $.trim(field.$(".previewsTemplate").html()),
		listElement: field.$(".previews").get(0),
		onComplete: function(id, fileName, response) {
			var $item = field.$(".previews").children().filter(function(i) {
				return this.qqFileId == id;
			});
			if (response.success) {
				this.showMessage(null);
				while (field.getOption("cardinality") && field.getOption("cardinality") < field.getCountUploaded()) {
					$item.siblings().first().remove();
				}
				$item.html(response.success.preview + "<input type=\"hidden\" name=\"" +field.getName()+ "[]\" value=\"" +response.success.id+ "\"/>");
			} else {
				$item.remove();
			}
			if (field.fileUploader.getInProgress() == 0 && field.getCountUploaded() > 0) {
				field.trigger("uploadComplete");
			}
		},
		showMessage: function(message) {
			if (message && message.msg) {
				message = message.msg;
			}
			field.error(message);
		}
	});

	this.$(".previews").on("click", ".delete", function() {
		$(this).parent("li").remove();
	});
},

getCountUploaded: function() {
	return this.$(".previews .qq-upload-success").length;
}
<commit_msg>t273: fix delete icon selector in file.js<commit_after>fileUploader: null,

ready: function() {
	var field = this;

	this.fileUploader = new qq.FileUploader({
		element: field.$(".file-uploader").get(0),
		action: "/upload/" + cm.options.siteId + "/?field=" + field.getClass(),
		multiple: !field.getOption("cardinality") || field.getOption("cardinality") > 1,
		allowedExtensions: field.getOption("allowedExtensions"),
		template: field.$(".file-uploader").html(),
		fileTemplate: $.trim(field.$(".previewsTemplate").html()),
		listElement: field.$(".previews").get(0),
		onComplete: function(id, fileName, response) {
			var $item = field.$(".previews").children().filter(function(i) {
				return this.qqFileId == id;
			});
			if (response.success) {
				this.showMessage(null);
				while (field.getOption("cardinality") && field.getOption("cardinality") < field.getCountUploaded()) {
					$item.siblings().first().remove();
				}
				$item.html(response.success.preview + "<input type=\"hidden\" name=\"" +field.getName()+ "[]\" value=\"" +response.success.id+ "\"/>");
			} else {
				$item.remove();
			}
			if (field.fileUploader.getInProgress() == 0 && field.getCountUploaded() > 0) {
				field.trigger("uploadComplete");
			}
		},
		showMessage: function(message) {
			if (message && message.msg) {
				message = message.msg;
			}
			field.error(message);
		}
	});

	this.$(".previews").on("click", ".delete", function() {
		$(this).closest("li").remove();
	});
},

getCountUploaded: function() {
	return this.$(".previews .qq-upload-success").length;
}
<|endoftext|>


<commit_before>/**
 * This provides the markup, styles, and helper functions for all Banner UI Elements
 */

goog.provide('banner');
goog.require('banner_utils');
goog.require('banner_css');
goog.require('banner_html');

goog.require('utils');

var sendSMS = function(doc, branch, options, linkData) {
	var phone = doc.getElementById('branch-sms-phone');
	var sendButton  = doc.getElementById('branch-sms-send');
	var branchLoader = doc.getElementById('branch-loader-wrapper');
	var smsFormContainer = doc.getElementById('branch-sms-form-container');
	var checkmark;

	var disableForm = function() {
		sendButton.setAttribute('disabled', '');
		phone.setAttribute('disabled', '');
		sendButton.style.opacity = '.4';
		phone.style.opacity = '.4';
		branchLoader.style.opacity = '1';
		phone.className = '';
	};

	var enableForm = function() {
		sendButton.removeAttribute('disabled');
		phone.removeAttribute('disabled');
		sendButton.style.opacity = '1';
		phone.style.opacity = '1';
		branchLoader.style.opacity = '0';
	};

	var hideFormShowSuccess = function() {
		checkmark = doc.createElement('div');
		checkmark.className = 'branch-icon-wrapper';
		checkmark.id = 'branch-checkmark';
		checkmark.style = 'opacity: 0;';
		checkmark.innerHTML = banner_html.checkmark();
		smsFormContainer.appendChild(checkmark);

		sendButton.style.opacity = '0';

		phone.style.opacity = '0';

		branchLoader.style.opacity = '0';

		setTimeout(function() {
			checkmark.style.opacity = '1';
		}, banner_utils.animationDelay);

		phone.value = '';
	};

	var errorForm = function() {
		enableForm();
		sendButton.style.background = "#FFD4D4";

		phone.className = 'error';

		setTimeout(function() {
			sendButton.style.background = "#FFFFFF";
			phone.className = '';
		}, banner_utils.error_timeout);
	};

	if (phone) {
		var phone_val = phone.value;
		if ((/^\d{7,}$/).test(phone_val.replace(/[\s()+\-\.]|ext/gi, ''))) {
			branch._publishEvent("willSendBannerSMS");
			disableForm();
			branch["sendSMS"](phone_val, linkData, options, function(err) {
				if (err) {
					branch._publishEvent("sendBannerSMSError");
					errorForm();
				}
				else {
					branch._publishEvent("didSendBannerSMS");
					hideFormShowSuccess();
					setTimeout(function() {
						smsFormContainer.removeChild(checkmark);
						enableForm();
					}, banner_utils.success_timeout);
				}
			 });
		}
		else {
			errorForm();
		}
	}
};

/**
 * @param {Object} branch
 * @param {banner_utils.options} options
 * @param {Object} linkData
 * @param {storage} storage
 */
banner = function(branch, options, linkData, storage) {
	if (banner_utils.shouldAppend(storage, options)) {
		branch._publishEvent("willShowBanner");

		// Create markup
		var element = banner_html.markup(options, storage);

		// Add CSS
		banner_css.css(options, element);

		// Attach actions
		linkData['channel'] = linkData['channel'] || 'app banner';

		var doc = options.iframe ? element.contentWindow.document : document;
		if (utils.mobileUserAgent()) {
			var referring_link = branch._referringLink();
			if (referring_link && !options['make_new_link']) {
				doc.getElementById('branch-mobile-action').href = referring_link;
			}
			else {
				branch["link"](linkData, function(err, url) {
					if (err) {
						// Todo: figure out something good to do here. Maybe a
						// long link? Or why not always a long link?
					}
					else {
						doc.getElementById('branch-mobile-action').href = url;
					}
				});
			}
		}
		else {
			doc.getElementById('sms-form').addEventListener('submit', function(ev) {
				ev.preventDefault();
				sendSMS(doc, branch, options, linkData);
			});
		}

		var bodyMarginTopComputed = banner_utils.getBodyStyle('margin-top'),
			bodyMarginTopInline = document.body.style.marginTop,
			bodyMarginBottomComputed = banner_utils.getBodyStyle('margin-bottom'),
			bodyMarginBottomInline = document.body.style.marginBottom,

			closeButton = doc.getElementById('branch-banner-close'),

			closeBanner = function(callback) {
				setTimeout(function() {
					banner_utils.removeElement(element);
					banner_utils.removeElement(document.getElementById('branch-css'));
					callback();
				}, banner_utils.animationSpeed + banner_utils.animationDelay);

				setTimeout(function() {
					if (options.position == 'top') { document.body.style.marginTop = bodyMarginTopInline; }
					else if (options.position == 'bottom') { document.body.style.marginBottom = bodyMarginBottomInline; }
					banner_utils.removeClass(document.body, 'branch-banner-is-active');
				}, banner_utils.animationDelay);
				if (options.position == 'top') { element.style.top = '-' + banner_utils.bannerHeight; }
				else if (options.position == 'bottom') { element.style.bottom = '-' + banner_utils.bannerHeight; }

				if (typeof options.forgetHide == 'number') { storage.set('hideBanner', banner_utils.getDate(options.forgetHide)); }
				else { storage.set('hideBanner', true); }
			};

		if (closeButton) {
			closeButton.onclick = function(ev) {
				ev.preventDefault();
				branch._publishEvent("willCloseBanner");
				closeBanner(function() {
					branch._publishEvent("didCloseBanner");
				});
			};
		}

		// Trigger animation
		banner_utils.addClass(document.body, 'branch-banner-is-active');
		if (options.position == 'top') { document.body.style.marginTop = banner_utils.addCSSLengths(banner_utils.bannerHeight, bodyMarginTopComputed); }
		else if (options.position == 'bottom') { document.body.style.marginBottom = banner_utils.addCSSLengths(banner_utils.bannerHeight, bodyMarginBottomComputed); }

		setTimeout(function() {
			if (options.position == 'top') { element.style.top = '0'; }
			else if (options.position == 'bottom') { element.style.bottom = '0'; }
			branch._publishEvent("didShowBanner");
		}, banner_utils.animationDelay);

		return closeBanner;
	}
	else { branch._publishEvent("willNotShowBanner"); }
};
<commit_msg>style, save one layer of indent for the if statement<commit_after>/**
 * This provides the markup, styles, and helper functions for all Banner UI Elements
 */

goog.provide('banner');
goog.require('banner_utils');
goog.require('banner_css');
goog.require('banner_html');

goog.require('utils');

var sendSMS = function(doc, branch, options, linkData) {
	var phone = doc.getElementById('branch-sms-phone');
	var sendButton  = doc.getElementById('branch-sms-send');
	var branchLoader = doc.getElementById('branch-loader-wrapper');
	var smsFormContainer = doc.getElementById('branch-sms-form-container');
	var checkmark;

	var disableForm = function() {
		sendButton.setAttribute('disabled', '');
		phone.setAttribute('disabled', '');
		sendButton.style.opacity = '.4';
		phone.style.opacity = '.4';
		branchLoader.style.opacity = '1';
		phone.className = '';
	};

	var enableForm = function() {
		sendButton.removeAttribute('disabled');
		phone.removeAttribute('disabled');
		sendButton.style.opacity = '1';
		phone.style.opacity = '1';
		branchLoader.style.opacity = '0';
	};

	var hideFormShowSuccess = function() {
		checkmark = doc.createElement('div');
		checkmark.className = 'branch-icon-wrapper';
		checkmark.id = 'branch-checkmark';
		checkmark.style = 'opacity: 0;';
		checkmark.innerHTML = banner_html.checkmark();
		smsFormContainer.appendChild(checkmark);

		sendButton.style.opacity = '0';

		phone.style.opacity = '0';

		branchLoader.style.opacity = '0';

		setTimeout(function() {
			checkmark.style.opacity = '1';
		}, banner_utils.animationDelay);

		phone.value = '';
	};

	var errorForm = function() {
		enableForm();
		sendButton.style.background = "#FFD4D4";

		phone.className = 'error';

		setTimeout(function() {
			sendButton.style.background = "#FFFFFF";
			phone.className = '';
		}, banner_utils.error_timeout);
	};

	if (phone) {
		var phone_val = phone.value;
		if ((/^\d{7,}$/).test(phone_val.replace(/[\s()+\-\.]|ext/gi, ''))) {
			branch._publishEvent("willSendBannerSMS");
			disableForm();
			branch["sendSMS"](phone_val, linkData, options, function(err) {
				if (err) {
					branch._publishEvent("sendBannerSMSError");
					errorForm();
				}
				else {
					branch._publishEvent("didSendBannerSMS");
					hideFormShowSuccess();
					setTimeout(function() {
						smsFormContainer.removeChild(checkmark);
						enableForm();
					}, banner_utils.success_timeout);
				}
			 });
		}
		else {
			errorForm();
		}
	}
};

/**
 * @param {Object} branch
 * @param {banner_utils.options} options
 * @param {Object} linkData
 * @param {storage} storage
 */
banner = function(branch, options, linkData, storage) {
  if (!banner_utils.shouldAppend(storage, options)) {
    branch._publishEvent("willNotShowBanner");
    return null;
  }

  branch._publishEvent("willShowBanner");

  // Create markup
  var element = banner_html.markup(options, storage);

  // Add CSS
  banner_css.css(options, element);

  // Attach actions
  linkData['channel'] = linkData['channel'] || 'app banner';

  var doc = options.iframe ? element.contentWindow.document : document;
  if (utils.mobileUserAgent()) {
    var referring_link = branch._referringLink();
    if (referring_link && !options['make_new_link']) {
      doc.getElementById('branch-mobile-action').href = referring_link;
    }
    else {
      branch["link"](linkData, function(err, url) {
        if (err) {
          // Todo: figure out something good to do here. Maybe a
          // long link? Or why not always a long link?
        }
        else {
          doc.getElementById('branch-mobile-action').href = url;
        }
      });
    }
  }
  else {
    doc.getElementById('sms-form').addEventListener('submit', function(ev) {
      ev.preventDefault();
      sendSMS(doc, branch, options, linkData);
    });
  }

  var bodyMarginTopComputed = banner_utils.getBodyStyle('margin-top'),
    bodyMarginTopInline = document.body.style.marginTop,
    bodyMarginBottomComputed = banner_utils.getBodyStyle('margin-bottom'),
    bodyMarginBottomInline = document.body.style.marginBottom,

    closeButton = doc.getElementById('branch-banner-close'),

    closeBanner = function(callback) {
      setTimeout(function() {
        banner_utils.removeElement(element);
        banner_utils.removeElement(document.getElementById('branch-css'));
        callback();
      }, banner_utils.animationSpeed + banner_utils.animationDelay);

      setTimeout(function() {
        if (options.position == 'top') { document.body.style.marginTop = bodyMarginTopInline; }
        else if (options.position == 'bottom') { document.body.style.marginBottom = bodyMarginBottomInline; }
        banner_utils.removeClass(document.body, 'branch-banner-is-active');
      }, banner_utils.animationDelay);
      if (options.position == 'top') { element.style.top = '-' + banner_utils.bannerHeight; }
      else if (options.position == 'bottom') { element.style.bottom = '-' + banner_utils.bannerHeight; }

      if (typeof options.forgetHide == 'number') { storage.set('hideBanner', banner_utils.getDate(options.forgetHide)); }
      else { storage.set('hideBanner', true); }
    };

  if (closeButton) {
    closeButton.onclick = function(ev) {
      ev.preventDefault();
      branch._publishEvent("willCloseBanner");
      closeBanner(function() {
        branch._publishEvent("didCloseBanner");
      });
    };
  }

  // Trigger animation
  banner_utils.addClass(document.body, 'branch-banner-is-active');
  if (options.position == 'top') { document.body.style.marginTop = banner_utils.addCSSLengths(banner_utils.bannerHeight, bodyMarginTopComputed); }
  else if (options.position == 'bottom') { document.body.style.marginBottom = banner_utils.addCSSLengths(banner_utils.bannerHeight, bodyMarginBottomComputed); }

  setTimeout(function() {
    if (options.position == 'top') { element.style.top = '0'; }
    else if (options.position == 'bottom') { element.style.bottom = '0'; }
    branch._publishEvent("didShowBanner");
  }, banner_utils.animationDelay);

  return closeBanner;
};
<|endoftext|>


<commit_before>#!/usr/bin/env node
/**
 *
 *    Copyright (c) 2020 Silicon Labs
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

const scriptUtil = require('./script-util.js')

//workaround: executeCmd()/spawn() fails silently without complaining about missing path to electron
process.env.PATH = process.env.PATH + ':/usr/local/bin/'
let startTime = process.hrtime()
let args = process.argv.slice(2)
let executor = 'electron'

scriptUtil
  .stampVersion()
  .then(() => scriptUtil.rebuildSpaIfNeeded())
  .then(() => {
    let cmdArgs = ['src-electron/main-process/electron-main.js']

    if (executor === 'electron' && process.platform == 'linux') {
      if (!process.env.DISPLAY) {
        console.log(`
⛔ You are on Linux and you are attempting to run zap in UI mode without DISPLAY set.
⛔ Please set your DISPLAY environment variable or run zap-start.js with a command that does not require DISPLAY.`)
        process.exit(1)
      }
    }
    cmdArgs.push(...args)
    return scriptUtil.executeCmd(null, executor, cmdArgs)
  })
  .then(() => {
    let endTime = process.hrtime(startTime)
    console.log(
      `😎 All done: ${endTime[0]}s, ${Math.round(endTime[1] / 1000000)}ms.`
    )
    process.exit(0)
  })
  .catch((err) => {
    console.log(err)
    process.exit(1)
  })
<commit_msg>Use npx to execute proper version of electron.<commit_after>#!/usr/bin/env node
/**
 *
 *    Copyright (c) 2020 Silicon Labs
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

const scriptUtil = require('./script-util.js')

//workaround: executeCmd()/spawn() fails silently without complaining about missing path to electron
process.env.PATH = process.env.PATH + ':/usr/local/bin/'
let startTime = process.hrtime()
let args = process.argv.slice(2)

scriptUtil
  .stampVersion()
  .then(() => scriptUtil.rebuildSpaIfNeeded())
  .then(() => {
    let cmdArgs = ['electron', 'src-electron/main-process/electron-main.js']

    if (process.platform == 'linux') {
      if (!process.env.DISPLAY) {
        console.log(`
⛔ You are on Linux and you are attempting to run zap in UI mode without DISPLAY set.
⛔ Please set your DISPLAY environment variable or run zap-start.js with a command that does not require DISPLAY.`)
        process.exit(1)
      }
    }
    cmdArgs.push(...args)
    return scriptUtil.executeCmd(null, 'npx', cmdArgs)
  })
  .then(() => {
    let endTime = process.hrtime(startTime)
    console.log(
      `😎 All done: ${endTime[0]}s, ${Math.round(endTime[1] / 1000000)}ms.`
    )
    process.exit(0)
  })
  .catch((err) => {
    console.log(err)
    process.exit(1)
  })
<|endoftext|>


<commit_before>define(["jquery", "road", "junction", "utils"], function($, Road, Junction, utils) {
    function Visualizer(world) {
        this.THICKNESS = 15;
        this.world = world;
        this.canvas = $("#canvas")[0];
        this.ctx = this.canvas.getContext("2d");
        this.width = this.canvas.width;
        this.height = this.canvas.height;
        this.mouseDown = false;
        this.tempLine = null;
        this.dragJunction = null;
        this.gridStep = 20;
        this.mousePos = null;
        this.colors = {
            background: "#fdfcfb",
            redLight: "#d03030",
            greenLight: "60a040",
            junction: "#666",
            draggedJunction: "blue",
            road: "#666",
            car: "#333",
            hoveredJunction: "black",
            tempLine: "#aaa",
            grid: "#ddd",
            hoveredGrid: "#eee",
        };
        var self = this;

        $(this.canvas).mousedown(function(e) {
            var point = self.getPoint(e);
            var nearestJunction = self.world.getNearestJunction(point, self.THICKNESS);
            if (e.shiftKey) {
                var gridPoint = self.getClosestGridPoint(point);
                var junction = new Junction(gridPoint);
                self.world.addJunction(junction);
            } else if (e.altKey) {
                self.dragJunction = nearestJunction;
            } else {
                if (nearestJunction) {
                    self.mouseDown = true;
                    self.tempLine = utils.line(nearestJunction, point);
                }
            }
        });

        $(this.canvas).mouseup(function(e) {
            var point = self.getPoint(e);
            self.mouseDown = false;
            if (self.tempLine) {
                var junction = self.world.getNearestJunction(point, self.THICKNESS);
                if (junction) {
                    var road1 = new Road(self.tempLine.source, junction);
                    self.world.addRoad(road1);
                    var road2 = new Road(junction, self.tempLine.source);
                    self.world.addRoad(road2);
                }
                self.tempLine = null;
            }
            if (self.dragJunction) {
                self.dragJunction = null;
            }
        });

        $(this.canvas).mousemove(function(e) {
            var point = self.getPoint(e);
            var nearestJunction = self.world.getNearestJunction(point, self.THICKNESS);
            self.mousePos = point;
            self.world.junctions.each(function(index, junction) { junction.color = null; });
            if (nearestJunction) {
                nearestJunction.color = self.colors.hoveredJunction;
            }

            if (self.tempLine) {
                self.tempLine.target = point;
            }

            if (self.dragJunction) {
                var gridPoint = self.getClosestGridPoint(point);
                self.dragJunction.x = gridPoint.x;
                self.dragJunction.y = gridPoint.y;
            }
        });

        this.canvas.addEventListener("mouseout", function(e) {
            self.mouseDown = false;
            self.tempLine = null;
            self.dragJunction = null;
            self.mousePos = null;
        });

    };

    Visualizer.prototype.getPoint = function(e) {
        return {
            x: e.pageX - this.canvas.offsetLeft,
            y: e.pageY - this.canvas.offsetTop,
        };
    };

    Visualizer.prototype.drawJunction = function(c, color) {
        this.ctx.beginPath();
        if (c.color) {
            color = c.color;
        } else if (c.state == Junction.prototype.STATE.RED) {
            color = this.colors.redLight;
        } else if (c.state == Junction.prototype.STATE.GREEN) {
            color = this.colors.greenLight;
        }
        this.ctx.fillStyle = color;
        this.ctx.fillRect(c.x, c.y, this.gridStep, this.gridStep);
    };

    Visualizer.prototype.drawLine = function(point1, point2, color) {
        this.ctx.beginPath();
        this.ctx.strokeStyle = color;
        var offset = 0;
        // FIXME: dirty hack, should be replaced with graph-drawing library
        len = utils.getDistance(point1, point2);
        dx = 2 * (point2.x - point1.x) / len;
        dy = 2 * (point2.y - point1.y) / len;
        this.ctx.moveTo(point1.x - dy, point1.y + dx);
        this.ctx.lineTo(point2.x - dy, point2.y + dx);
        this.ctx.stroke();
    };

    Visualizer.prototype.getCarPositionOnRoad = function(roadId, position) {
        var road = this.world.getRoad(roadId);
        var source = road.getSource(), target = road.getTarget();
        var dx = target.x - source.x,
            dy = target.y - source.y;
        len = utils.getDistance(source, target);
        off_x = 2 * (target.x - source.x) / len;
        off_y = 2 * (target.y - source.y) / len;
        off_x = off_y = 0;
        return {
            x: source.x + position * dx + off_y,
            y: source.y + position * dy + off_x,
        };
    };

    Visualizer.prototype.drawCar = function(car) {
        var point = this.getCarPositionOnRoad(car.road, car.position);
        this.ctx.beginPath();
        this.ctx.fillStyle = this.colors.car;
        this.ctx.arc(point.x, point.y, 3, 0, Math.PI * 2);
        this.ctx.fill();
    };

    Visualizer.prototype.drawBackground = function() {
        this.ctx.fillStyle = this.colors.background;
        this.ctx.fillRect(0, 0, this.width, this.height);
    };

    Visualizer.prototype.drawGrid = function() {
        this.ctx.fillStyle = this.colors.grid;
        for (var i = 0; i <= this.width; i += this.gridStep) {
            for (var j = 0; j <= this.height; j += this.gridStep) {
                this.ctx.fillRect(i - 1, j - 1, 2, 2);
            }
        }
    };

    Visualizer.prototype.getClosestGridPoint = function(point) {
        var result = {
            x: Math.floor(point.x / this.gridStep) * this.gridStep,
            y: Math.floor(point.y / this.gridStep) * this.gridStep,
        };
        return result;
    };

    Visualizer.prototype.drawHighlightedCell = function() {
        if (this.mousePos) {
            this.ctx.fillStyle = this.colors.hoveredGrid;
            var topLeftCorner = this.getClosestGridPoint(this.mousePos);
            this.ctx.fillRect(topLeftCorner.x, topLeftCorner.y, this.gridStep, this.gridStep);
        }
    };

    Visualizer.prototype.draw = function() {
        var self = this;
        this.drawBackground();
        this.drawGrid();
        this.drawHighlightedCell();
        this.world.roads.each(function(index, road) {
            var source = road.getSource(), target = road.getTarget();
            self.drawLine(source, target, self.colors.road);
        });
        this.world.junctions.each(function(index, junction) {
            self.drawJunction(junction, self.colors.junction);
        });
        this.world.cars.each(function(index, car) {
            self.drawCar(car);
        });
        if (self.tempLine) {
            self.drawLine(self.tempLine.source, self.tempLine.target, self.colors.tempLine);
        }
    };

    return Visualizer;
});
<commit_msg>draw rect when creating multicells junctions<commit_after>define(["jquery", "road", "junction", "utils"], function($, Road, Junction, utils) {
    function Visualizer(world) {
        this.THICKNESS = 15;
        this.world = world;
        this.canvas = $("#canvas")[0];
        this.ctx = this.canvas.getContext("2d");
        this.width = this.canvas.width;
        this.height = this.canvas.height;
        this.mouseDownPos = null;
        this.tempLine = null;
        this.tempRect = false;
        this.dragJunction = null;
        this.gridStep = 20;
        this.mousePos = null;
        this.colors = {
            background: "#fdfcfb",
            redLight: "#d03030",
            greenLight: "60a040",
            junction: "#666",
            draggedJunction: "blue",
            road: "#666",
            car: "#333",
            hoveredJunction: "black",
            tempLine: "#aaa",
            grid: "#ddd",
            hoveredGrid: "#f0f0f0",
            unfinishedJunction: "#eee",
        };
        var self = this;

        $(this.canvas).mousedown(function(e) {
            var point = self.getPoint(e);
            self.mouseDownPos = point;
            var nearestJunction = self.world.getNearestJunction(point, self.THICKNESS);
            if (e.shiftKey) {
                self.tempRect = true;
            } else if (e.altKey) {
                self.dragJunction = nearestJunction;
            } else if (nearestJunction) {
                self.tempLine = utils.line(nearestJunction, point);
            }
        });

        $(this.canvas).mouseup(function(e) {
            var point = self.getPoint(e);
            if (self.tempLine) {
                var junction = self.world.getNearestJunction(point, self.THICKNESS);
                if (junction) {
                    var road1 = new Road(self.tempLine.source, junction);
                    self.world.addRoad(road1);
                    var road2 = new Road(junction, self.tempLine.source);
                    self.world.addRoad(road2);
                }
                self.tempLine = null;
            }
            if (self.tempRect) {
                var gridPoint = self.getClosestGridPoint(point);
                var junction = new Junction(gridPoint);
                self.world.addJunction(junction);
                self.tempRect = false;
            }
            self.mouseDownPos = null;
            self.dragJunction = null;
        });

        $(this.canvas).mousemove(function(e) {
            var point = self.getPoint(e);
            var nearestJunction = self.world.getNearestJunction(point, self.THICKNESS);
            self.mousePos = point;
            self.world.junctions.each(function(index, junction) { junction.color = null; });
            if (nearestJunction) {
                nearestJunction.color = self.colors.hoveredJunction;
            }
            if (self.tempLine) {
                self.tempLine.target = point;
            }
            if (self.dragJunction) {
                var gridPoint = self.getClosestGridPoint(point);
                self.dragJunction.x = gridPoint.x;
                self.dragJunction.y = gridPoint.y;
            }
        });

        this.canvas.addEventListener("mouseout", function(e) {
            self.mouseDownPos = null;
            self.tempLine = null;
            self.dragJunction = null;
            self.mousePos = null;
            this.tempRect = false;
        });

    };

    Visualizer.prototype.getPoint = function(e) {
        return {
            x: e.pageX - this.canvas.offsetLeft,
            y: e.pageY - this.canvas.offsetTop,
        };
    };

    Visualizer.prototype.drawJunction = function(c, color) {
        this.ctx.beginPath();
        if (c.color) {
            color = c.color;
        } else if (c.state == Junction.prototype.STATE.RED) {
            color = this.colors.redLight;
        } else if (c.state == Junction.prototype.STATE.GREEN) {
            color = this.colors.greenLight;
        }
        this.ctx.fillStyle = color;
        this.ctx.fillRect(c.x, c.y, this.gridStep, this.gridStep);
    };

    Visualizer.prototype.drawLine = function(point1, point2, color) {
        this.ctx.beginPath();
        this.ctx.strokeStyle = color;
        var offset = 0;
        // FIXME: dirty hack, should be replaced with graph-drawing library
        len = utils.getDistance(point1, point2);
        dx = 2 * (point2.x - point1.x) / len;
        dy = 2 * (point2.y - point1.y) / len;
        this.ctx.moveTo(point1.x - dy, point1.y + dx);
        this.ctx.lineTo(point2.x - dy, point2.y + dx);
        this.ctx.stroke();
    };

    Visualizer.prototype.getCarPositionOnRoad = function(roadId, position) {
        var road = this.world.getRoad(roadId);
        var source = road.getSource(), target = road.getTarget();
        var dx = target.x - source.x,
            dy = target.y - source.y;
        len = utils.getDistance(source, target);
        off_x = 2 * (target.x - source.x) / len;
        off_y = 2 * (target.y - source.y) / len;
        off_x = off_y = 0;
        return {
            x: source.x + position * dx + off_y,
            y: source.y + position * dy + off_x,
        };
    };

    Visualizer.prototype.drawCar = function(car) {
        var point = this.getCarPositionOnRoad(car.road, car.position);
        this.ctx.beginPath();
        this.ctx.fillStyle = this.colors.car;
        this.ctx.arc(point.x, point.y, 3, 0, Math.PI * 2);
        this.ctx.fill();
    };

    Visualizer.prototype.drawBackground = function() {
        this.ctx.fillStyle = this.colors.background;
        this.ctx.fillRect(0, 0, this.width, this.height);
    };

    Visualizer.prototype.drawGrid = function() {
        this.ctx.fillStyle = this.colors.grid;
        for (var i = 0; i <= this.width; i += this.gridStep) {
            for (var j = 0; j <= this.height; j += this.gridStep) {
                this.ctx.fillRect(i - 1, j - 1, 2, 2);
            }
        }
    };

    Visualizer.prototype.getClosestGridPoint = function(point) {
        var result = {
            x: Math.floor(point.x / this.gridStep) * this.gridStep,
            y: Math.floor(point.y / this.gridStep) * this.gridStep,
        };
        return result;
    };

    Visualizer.prototype.drawHighlightedCell = function() {
        if (this.mousePos) {
            this.ctx.fillStyle = this.colors.hoveredGrid;
            var topLeftCorner = this.getClosestGridPoint(this.mousePos);
            this.ctx.fillRect(topLeftCorner.x, topLeftCorner.y, this.gridStep, this.gridStep);
        }
    };

    Visualizer.prototype.drawTempJunction = function(point1, point2) {
        var gridPoint1 = this.getClosestGridPoint(point1),
            gridPoint2 = this.getClosestGridPoint(point2);
        var x1 = gridPoint1.x, y1 = gridPoint1.y,
            x2 = gridPoint2.x, y2 = gridPoint2.y;
        if (x1 > x2) {
            x1 = x2 + (x2 = x1, 0);
        }
        if (y1 > y2) {
            y1 = y2 + (y2 = y1, 0);
        }
        x2 += this.gridStep;
        y2 += this.gridStep;
        this.ctx.fillStyle = this.colors.unfinishedJunction;
        this.ctx.fillRect(x1, y1, x2 - x1, y2 - y1);
    };

    Visualizer.prototype.draw = function() {
        var self = this;
        this.drawBackground();
        this.drawGrid();
        this.drawHighlightedCell();
        this.world.roads.each(function(index, road) {
            var source = road.getSource(), target = road.getTarget();
            self.drawLine(source, target, self.colors.road);
        });
        this.world.junctions.each(function(index, junction) {
            self.drawJunction(junction, self.colors.junction);
        });
        this.world.cars.each(function(index, car) {
            self.drawCar(car);
        });
        if (self.tempLine) {
            self.drawLine(self.tempLine.source, self.tempLine.target, self.colors.tempLine);
        }
        if (self.tempRect) {
            self.drawTempJunction(self.mouseDownPos, self.mousePos);
        }
    };

    return Visualizer;
});
<|endoftext|>


<commit_before>'use strict';

/**
* ESLint rules specific to stdlib.
*
* @namespace rules
*/
var rules = {};

/**
* Require an empty line before single-line comments.
*
* @name empty-line-before-comment
* @memberof rules
* @type {string}
* @default 'error'
*
* @example
* // Bad...
* function square( x ) {
*     var out;
*     // Square the number:
*     out = x*x;
*     return out;
* }
*
* @example
* // Good...
* function square( x ) {
*     var out;
*
*     // Square the number:
*     out = x*x;
*     return out;
* }
*/
rules[ 'stdlib/empty-line-before-comment' ] = 'error';

/**
* Enforce that require() calls have only string literals as parameters.
*
* @name no-dynamic-require
* @memberof rules
* @type {string}
* @default 'error'
*
* @example
* // Bad...
* var pkg = '@stdlib/math/base/special/betainc';
* var betainc = require( pkg );
*
* @example
* // Good...
* var betainc = require( '@stdlib/math/base/special/betainc' );
*/
rules[ 'stdlib/no-dynamic-require' ] = 'error';

/**
* Disallow require() calls of another package's internals.
*
* @name no-internal-require
* @memberof rules
* @type {string}
* @default 'error'
*
* @example
* // Bad...
* var betainc = require( '@stdlib/math/base/special/betainc/lib/index.js' );
*
* @example
* // Good...
* var betainc = require( '@stdlib/math/base/special/betainc' );
*/
rules[ 'stdlib/no-internal-require' ] = 'error';

/**
* Never allow a variable to be declared multiple times within the same scope or for built-in globals to be redeclared.
*
* @name no-redeclare
* @memberof rules
* @type {Array}
* @default [ 'error', { 'builtinGlobals': false, 'globalsWhitelist': [] } ]
* @see [no-redeclare]{@link http://eslint.org/docs/rules/no-redeclare}
*
* @example
* // Bad...
* var a = 'beep';
* // ...
* var a = 'boop';
*
* @example
* // Good...
* var a = 'beep';
* // ...
* a = 'boop';
*/
rules[ 'stdlib/no-redeclare' ] = [ 'error', {
	'builtinGlobals': true,
	'globalsWhitelist': [
		'ArrayBuffer',
		'Buffer',
		'Float32Array',
		'Float64Array',
		'Int8Array',
		'Int16Array',
		'Int32Array',
		'SharedArrayBuffer',
		'Uint8Array',
		'Uint8ClampedArray',
		'Uint16Array',
		'Uint32Array'
	]
}];

/**
* Enforce that require() calls of files end with a whitelisted file extension.
*
* @name require-file-extensions
* @memberof rules
* @type {Array}
* @default [ 'error', { 'extensionsWhitelist': [ '.js', '.json', '.node' ] } ]
*
* @example
* // Bad...
*
* // Invalid file extension:
* var readme = require( '@stdlib/types/array/int32/README.md' );
*
* // Missing file extension:
* var debug = require( 'debug/src/browser' );
*
* @example
* // Good...
*
* var Int32Array = require( '@stdlib/types/array/int32' );
*
* var debug = require( 'debug/src/browser.js' );
*/
rules[ 'stdlib/require-file-extensions' ] = [ 'off', { // TODO: Enable once all @stdlib/tools packages are moved to @stdlib/_tools
	'extensionsWhitelist': [
		'.js',
		'.json',
		'.node'
	]
}];

/**
* Enforce that typed array constructors are explicitly required.
*
* @name require-typed-arrays
* @memberof rules
* @type {string}
* @default 'error'
*
* @example
* // Bad...
* var arr = new Float32Array();
*
* @example
* // Good...
* var Float32Array = require( '@stdlib/types/array/float32' );
*
* var arr = new Float32Array();
*/
rules[ 'stdlib/require-typed-arrays' ] = 'error';

/**
* Enforce that typed array constructors are explicitly required.
*
* @name section-headers
* @memberof rules
* @type {string}
* @default 'error'
*
* @example
* // Bad... (require two trailing slashes)
*
* // EXPORTS
*
* module.exports = {};
*
* @example
* // Bad... (require a known header type)
*
* // EXPRTS //
*
* module.exports = {};
*
* @example
* // Bad... (require all uppercase letters)
*
* // EXPorts //
*
* module.exports = {};
*
* @example
* // Good...
*
* // EXPORTS //
*
* module.exports = {};
*/
rules[ 'stdlib/section-headers' ] = 'error';

// EXPORTS //

module.exports = rules;
<commit_msg>Add `DataView` to list of exceptions<commit_after>'use strict';

/**
* ESLint rules specific to stdlib.
*
* @namespace rules
*/
var rules = {};

/**
* Require an empty line before single-line comments.
*
* @name empty-line-before-comment
* @memberof rules
* @type {string}
* @default 'error'
*
* @example
* // Bad...
* function square( x ) {
*     var out;
*     // Square the number:
*     out = x*x;
*     return out;
* }
*
* @example
* // Good...
* function square( x ) {
*     var out;
*
*     // Square the number:
*     out = x*x;
*     return out;
* }
*/
rules[ 'stdlib/empty-line-before-comment' ] = 'error';

/**
* Enforce that require() calls have only string literals as parameters.
*
* @name no-dynamic-require
* @memberof rules
* @type {string}
* @default 'error'
*
* @example
* // Bad...
* var pkg = '@stdlib/math/base/special/betainc';
* var betainc = require( pkg );
*
* @example
* // Good...
* var betainc = require( '@stdlib/math/base/special/betainc' );
*/
rules[ 'stdlib/no-dynamic-require' ] = 'error';

/**
* Disallow require() calls of another package's internals.
*
* @name no-internal-require
* @memberof rules
* @type {string}
* @default 'error'
*
* @example
* // Bad...
* var betainc = require( '@stdlib/math/base/special/betainc/lib/index.js' );
*
* @example
* // Good...
* var betainc = require( '@stdlib/math/base/special/betainc' );
*/
rules[ 'stdlib/no-internal-require' ] = 'error';

/**
* Never allow a variable to be declared multiple times within the same scope or for built-in globals to be redeclared.
*
* @name no-redeclare
* @memberof rules
* @type {Array}
* @default [ 'error', { 'builtinGlobals': false, 'globalsWhitelist': [] } ]
* @see [no-redeclare]{@link http://eslint.org/docs/rules/no-redeclare}
*
* @example
* // Bad...
* var a = 'beep';
* // ...
* var a = 'boop';
*
* @example
* // Good...
* var a = 'beep';
* // ...
* a = 'boop';
*/
rules[ 'stdlib/no-redeclare' ] = [ 'error', {
	'builtinGlobals': true,
	'globalsWhitelist': [
		'ArrayBuffer',
		'Buffer',
		'DataView',
		'Float32Array',
		'Float64Array',
		'Int8Array',
		'Int16Array',
		'Int32Array',
		'SharedArrayBuffer',
		'Uint8Array',
		'Uint8ClampedArray',
		'Uint16Array',
		'Uint32Array'
	]
}];

/**
* Enforce that require() calls of files end with a whitelisted file extension.
*
* @name require-file-extensions
* @memberof rules
* @type {Array}
* @default [ 'error', { 'extensionsWhitelist': [ '.js', '.json', '.node' ] } ]
*
* @example
* // Bad...
*
* // Invalid file extension:
* var readme = require( '@stdlib/types/array/int32/README.md' );
*
* // Missing file extension:
* var debug = require( 'debug/src/browser' );
*
* @example
* // Good...
*
* var Int32Array = require( '@stdlib/types/array/int32' );
*
* var debug = require( 'debug/src/browser.js' );
*/
rules[ 'stdlib/require-file-extensions' ] = [ 'off', { // TODO: Enable once all @stdlib/tools packages are moved to @stdlib/_tools
	'extensionsWhitelist': [
		'.js',
		'.json',
		'.node'
	]
}];

/**
* Enforce that typed array constructors are explicitly required.
*
* @name require-typed-arrays
* @memberof rules
* @type {string}
* @default 'error'
*
* @example
* // Bad...
* var arr = new Float32Array();
*
* @example
* // Good...
* var Float32Array = require( '@stdlib/types/array/float32' );
*
* var arr = new Float32Array();
*/
rules[ 'stdlib/require-typed-arrays' ] = 'error';

/**
* Enforce that typed array constructors are explicitly required.
*
* @name section-headers
* @memberof rules
* @type {string}
* @default 'error'
*
* @example
* // Bad... (require two trailing slashes)
*
* // EXPORTS
*
* module.exports = {};
*
* @example
* // Bad... (require a known header type)
*
* // EXPRTS //
*
* module.exports = {};
*
* @example
* // Bad... (require all uppercase letters)
*
* // EXPorts //
*
* module.exports = {};
*
* @example
* // Good...
*
* // EXPORTS //
*
* module.exports = {};
*/
rules[ 'stdlib/section-headers' ] = 'error';

// EXPORTS //

module.exports = rules;
<|endoftext|>