<commit_before>import React, { Component } from 'react'
import TextField from 'material-ui/TextField'
import DatePicker from 'material-ui/DatePicker'
import Checkbox from 'material-ui/Checkbox'
import RaisedButton from '../components/MaterializeRaisedButton'
import Dialog from 'material-ui/Dialog'
import FlatButton from 'material-ui/FlatButton'
import { Link } from 'react-router-dom'
import { Helmet } from 'react-helmet'
import '../styles/inputFile.css'
import '../styles/serviceRequest.css'

const PORT = process.env.UPLOADS_PORT || 9000
const HOST = process.env.UPLOADS_HOST || window.location.host.split(':')[0]
const UPLOAD_URL = `http://${HOST}:${PORT}/uploads`

const styles = {
  block: {
    maxWidth: 250
  },
  checkbox: {
    marginBottom: 16
  },
  button: {
    margin: 12
  },
  exampleImageInput: {
    cursor: 'pointer',
    position: 'absolute',
    top: 0,
    bottom: 0,
    right: 0,
    left: 0,
    width: '100%',
    opacity: 0
  }
}

// https://github.com/Dogfalo/materialize/blob/master/js/forms.js#L192
class ServiceRequest extends Component {
  constructor (props) {
    super(props)
    this.singleLineFields = ['Name', 'Email', 'Phone', 'Department']
    this.multiLineFields = [
      'Project Description',
      'Project Goal',
      'Project Budget',
      'Key Messages',
      'Primary Target Audience',
      'Secondary Target Audience',
      'Project Contact (if other than yourself)',
      'Comments'
    ]
    this.leftCheckboxes = [
      'Simple1',
      'Simple2',
      'Simple3',
      'Simple4',
      'Simple5',
      'Simple6'
    ]
    this.rightCheckboxes = [
      'Simple7',
      'Simple8',
      'Simple9',
      'Simple10',
      'Simple11',
      'Simple12'
    ]
    const stringProps = [
      ...this.singleLineFields,
      ...this.multiLineFields
    ].reduce(
      (acc, label) => ({
        [this.formatLabelToProperty(label)]: '',
        ...acc
      }),
      {}
    )
    const checkboxProps = [
      ...this.leftCheckboxes,
      ...this.rightCheckboxes
    ].reduce(
      (acc, label) => ({
        [this.formatLabelToProperty(label)]: false,
        ...acc
      }),
      {}
    )
    this.state = {
      form: {
        fileInput: null
      },
      loadingDialogOpen: false,
      resultDialogOpen: false,
      resultDialogText: null,
      resultDialogSuccess: true
    }
    Object.assign(this.state.form, stringProps, checkboxProps)
    this.handleInputChange = this.handleInputChange.bind(this)
  }

  formatLabelToProperty = label =>
    label.split(' (')[0].toLowerCase().split(' ').join('-')

  handleInputChange (event) {
    const target = event.target
    const value = target.type === 'checkbox' ? target.checked : target.value
    const name = target.name

    const form = Object.assign({}, this.state.form)
    form[name] = value

    this.setState({ form })
  }

  handleFilePath = event => {
    const target = event.target
    // Array.from converts array-like to array (so that map works)
    const files = Array.from(target.files)
    let fileNames = null
    if (files.length > 0) {
      fileNames = files.map(f => f.name).join(', ')
    }

    const form = Object.assign({}, this.state.form)
    form.fileInput = fileNames
    this.setState({ form })
  }

  handleFormData = async () => {
    const data = new FormData()
    for (const [key, val] of Object.entries(this.state.form)) {
      data.append(key, val)
    }

    for (const file of this.uploadInput.files) data.append('file', file)

    this.setState({ loadingDialogOpen: true })

    try {
      const response = await fetch(UPLOAD_URL, {
        method: 'post',
        body: data
      }).then(res => res.json())

      if (!response.success) throw response.status

      this.setState({
        resultDialogOpen: true,
        resultDialogSuccess: true,
        resultDialogText: 'Your service request was sent successfully.'
      })
    } catch (err) {
      const msg =
        typeof err === 'string'
          ? err
          : 'An error occurred while sending the request.'
      this.setState({
        resultDialogOpen: true,
        resultDialogSuccess: false,
        resultDialogText: msg
      })
    }

    this.setState({ loadingDialogOpen: false })
  }

  handleDialogClose = () => {
    this.setState({ resultDialogOpen: false })
  }

  render () {
    const fileValue = this.state.form.fileInput || 'Select a file to upload'
    const SingleLineField = (label, index) =>

        <TextField
          floatingLabelText={label}
          name={this.formatLabelToProperty(label)}
          value={this.state.form[this.formatLabelToProperty(label)]}
          onChange={this.handleInputChange}
          fullWidth
        />

    const MultiLineField = (label, index) =>

        <TextField
          floatingLabelText={label}
          name={this.formatLabelToProperty(label)}
          value={this.state.form[this.formatLabelToProperty(label)]}
          onChange={this.handleInputChange}
          multiLine
          rows={2}
          fullWidth
        />

    const CheckboxField = (label, index) =>
      <Checkbox
        label={label}
        name={this.formatLabelToProperty(label)}
        checked={this.state.form[this.formatLabelToProperty(label)]}
        key={index}
        onCheck={this.handleInputChange}
        style={styles.checkbox}
      />

    return (

        <Helmet>
          <title>Service Request | Resource Center</title>
        </Helmet>

Please use this form to request services.

          {this.singleLineFields.map((label, index) =>
            SingleLineField(label, index)
          )}
          {this.multiLineFields.map((label, index) =>
            MultiLineField(label, index)
          )}

            <DatePicker hintText='Desired Completion Date' />

                Upload Files
                <input
                  id='upload'
                  name='upload[]'
                  type='file'
                  multiple
                  onChange={this.handleFilePath}
                  ref={input => {
                    this.uploadInput = input
                  }}
                />

                <TextField
                  className='file-path validate'
                  value={fileValue}
                  multiLine
                  rows={1}
                  fullWidth
                  readOnly
                />

            {this.leftCheckboxes.map((label, index) =>
              CheckboxField(label, index)
            )}

            {this.rightCheckboxes.map((label, index) =>
              CheckboxField(label, index)
            )}

            <RaisedButton
              label='Submit'
              id='submit-button'
              onClick={this.handleFormData}
              primary
            />

              <Checkbox
                label={

                    I have read the{' '}
                    <Link
                      to='/planning-guide'
                      target='_blank'
                      style={{ fontWeight: 500 }}
                    >
                      Planning Guide
                    </Link>

                }
                style={styles.checkbox}
                inputStyle={{ width: '35px' }}
              />

        <Dialog title='Loading...' modal open={this.state.loadingDialogOpen}>
          Sending service request
        </Dialog>
        <Dialog
          title={this.state.resultDialogSuccess ? 'Done' : 'Error'}
          modal={false}
          open={this.state.resultDialogOpen}
          onRequestClose={this.handleDialogClose}
          actions={[
            <FlatButton
              label='Ok'
              onTouchTap={this.handleDialogClose}
              keyboardFocused
            />
          ]}
        >
          {this.state.resultDialogText}
        </Dialog>

    )
  }
}

export default ServiceRequest
<commit_msg>added an id to the textfield component to resolve some material-ui errors<commit_after>import React, { Component } from 'react'
import TextField from 'material-ui/TextField'
import DatePicker from 'material-ui/DatePicker'
import Checkbox from 'material-ui/Checkbox'
import RaisedButton from '../components/MaterializeRaisedButton'
import Dialog from 'material-ui/Dialog'
import FlatButton from 'material-ui/FlatButton'
import { Link } from 'react-router-dom'
import { Helmet } from 'react-helmet'
import '../styles/inputFile.css'
import '../styles/serviceRequest.css'

const PORT = process.env.UPLOADS_PORT || 9000
const HOST = process.env.UPLOADS_HOST || window.location.host.split(':')[0]
const UPLOAD_URL = `http://${HOST}:${PORT}/uploads`

const styles = {
  block: {
    maxWidth: 250
  },
  checkbox: {
    marginBottom: 16
  },
  button: {
    margin: 12
  },
  exampleImageInput: {
    cursor: 'pointer',
    position: 'absolute',
    top: 0,
    bottom: 0,
    right: 0,
    left: 0,
    width: '100%',
    opacity: 0
  }
}

// https://github.com/Dogfalo/materialize/blob/master/js/forms.js#L192
class ServiceRequest extends Component {
  constructor (props) {
    super(props)
    this.singleLineFields = ['Name', 'Email', 'Phone', 'Department']
    this.multiLineFields = [
      'Project Description',
      'Project Goal',
      'Project Budget',
      'Key Messages',
      'Primary Target Audience',
      'Secondary Target Audience',
      'Project Contact (if other than yourself)',
      'Comments'
    ]
    this.leftCheckboxes = [
      'Simple1',
      'Simple2',
      'Simple3',
      'Simple4',
      'Simple5',
      'Simple6'
    ]
    this.rightCheckboxes = [
      'Simple7',
      'Simple8',
      'Simple9',
      'Simple10',
      'Simple11',
      'Simple12'
    ]
    const stringProps = [
      ...this.singleLineFields,
      ...this.multiLineFields
    ].reduce(
      (acc, label) => ({
        [this.formatLabelToProperty(label)]: '',
        ...acc
      }),
      {}
    )
    const checkboxProps = [
      ...this.leftCheckboxes,
      ...this.rightCheckboxes
    ].reduce(
      (acc, label) => ({
        [this.formatLabelToProperty(label)]: false,
        ...acc
      }),
      {}
    )
    this.state = {
      form: {
        fileInput: null
      },
      loadingDialogOpen: false,
      resultDialogOpen: false,
      resultDialogText: null,
      resultDialogSuccess: true
    }
    Object.assign(this.state.form, stringProps, checkboxProps)
    this.handleInputChange = this.handleInputChange.bind(this)
  }

  formatLabelToProperty = label =>
    label
      .split(' (')[0]
      .toLowerCase()
      .split(' ')
      .join('-')

  handleInputChange (event) {
    const target = event.target
    const value = target.type === 'checkbox' ? target.checked : target.value
    const name = target.name

    const form = Object.assign({}, this.state.form)
    form[name] = value

    this.setState({ form })
  }

  handleFilePath = event => {
    const target = event.target
    // Array.from converts array-like to array (so that map works)
    const files = Array.from(target.files)
    let fileNames = null
    if (files.length > 0) {
      fileNames = files.map(f => f.name).join(', ')
    }

    const form = Object.assign({}, this.state.form)
    form.fileInput = fileNames
    this.setState({ form })
  }

  handleFormData = async () => {
    const data = new FormData()
    for (const [key, val] of Object.entries(this.state.form)) {
      data.append(key, val)
    }

    for (const file of this.uploadInput.files) data.append('file', file)

    this.setState({ loadingDialogOpen: true })

    try {
      const response = await fetch(UPLOAD_URL, {
        method: 'post',
        body: data
      }).then(res => res.json())

      if (!response.success) throw response.status

      this.setState({
        resultDialogOpen: true,
        resultDialogSuccess: true,
        resultDialogText: 'Your service request was sent successfully.'
      })
    } catch (err) {
      const msg =
        typeof err === 'string'
          ? err
          : 'An error occurred while sending the request.'
      this.setState({
        resultDialogOpen: true,
        resultDialogSuccess: false,
        resultDialogText: msg
      })
    }

    this.setState({ loadingDialogOpen: false })
  }

  handleDialogClose = () => {
    this.setState({ resultDialogOpen: false })
  }

  render () {
    const fileValue = this.state.form.fileInput || 'Select a file to upload'
    const SingleLineField = (label, index) => (

        <TextField
          floatingLabelText={label}
          name={this.formatLabelToProperty(label)}
          value={this.state.form[this.formatLabelToProperty(label)]}
          onChange={this.handleInputChange}
          fullWidth
          id={`${this.formatLabelToProperty(label)}-field`}
        />

    )
    const MultiLineField = (label, index) => (

        <TextField
          floatingLabelText={label}
          name={this.formatLabelToProperty(label)}
          value={this.state.form[this.formatLabelToProperty(label)]}
          onChange={this.handleInputChange}
          multiLine
          rows={2}
          fullWidth
          id={`${this.formatLabelToProperty(label)}-field`}
        />

    )
    const CheckboxField = (label, index) => (
      <Checkbox
        label={label}
        name={this.formatLabelToProperty(label)}
        checked={this.state.form[this.formatLabelToProperty(label)]}
        key={index}
        onCheck={this.handleInputChange}
        style={styles.checkbox}
      />
    )

    return (

        <Helmet>
          <title>Service Request | Resource Center</title>
        </Helmet>

Please use this form to request services.

          {this.singleLineFields.map((label, index) =>
            SingleLineField(label, index)
          )}
          {this.multiLineFields.map((label, index) =>
            MultiLineField(label, index)
          )}

            <DatePicker hintText='Desired Completion Date' />

                Upload Files
                <input
                  id='upload'
                  name='upload[]'
                  type='file'
                  multiple
                  onChange={this.handleFilePath}
                  ref={input => {
                    this.uploadInput = input
                  }}
                />

                <TextField
                  className='file-path validate'
                  value={fileValue}
                  multiLine
                  rows={1}
                  fullWidth
                  readOnly
                  id='file-path-field'
                />

            {this.leftCheckboxes.map((label, index) =>
              CheckboxField(label, index)
            )}

            {this.rightCheckboxes.map((label, index) =>
              CheckboxField(label, index)
            )}

            <RaisedButton
              label='Submit'
              id='submit-button'
              onClick={this.handleFormData}
              primary
            />

              <Checkbox
                label={

                    I have read the{' '}
                    <Link
                      to='/planning-guide'
                      target='_blank'
                      style={{ fontWeight: 500 }}
                    >
                      Planning Guide
                    </Link>

                }
                style={styles.checkbox}
                inputStyle={{ width: '35px' }}
              />

        <Dialog title='Loading...' modal open={this.state.loadingDialogOpen}>
          Sending service request
        </Dialog>
        <Dialog
          title={this.state.resultDialogSuccess ? 'Done' : 'Error'}
          modal={false}
          open={this.state.resultDialogOpen}
          onRequestClose={this.handleDialogClose}
          actions={[
            <FlatButton
              label='Ok'
              onTouchTap={this.handleDialogClose}
              keyboardFocused
            />
          ]}
        >
          {this.state.resultDialogText}
        </Dialog>

    )
  }
}

export default ServiceRequest
<|endoftext|>


<commit_before>function sqlite(args){
    var options = {
        columns: "*",
        table: "sqlite_master WHERE (type='table' OR type='view') AND name NOT LIKE '#_%'  ESCAPE '#'",
        limit: 50,
        offset: 0,
        orderby: null
    }
    $.extend(true, options, args);
    return $.ajax({
        url: "../../sqlite",
        dataType: 'json',
        cache: false,
        data: {
            q: 'SELECT ' + options.columns + ' FROM ' + options.table + ( options.orderby ? ' ORDER BY ' + options.orderby : '' ) + ' LIMIT ' + options.limit + ' OFFSET ' + options.offset
        }
    });
}

function showSlickGrid(table_name){
    sqlite({
        table: table_name
    }).done(function(data){
        var grid;
        var options = {
            enableColumnReorder: true,
            enableTextSelectionOnCells: true
        }
        // create column definitions from first row of data
        var columns = [];
        var names = [];
        for(var key in data[0]){
            columns.push({
                id: key,
                name: key,
                field: key,
                sortable: true
            });
            names.push(key);
        }

        var key = [location.pathname, 'columns', table_name]
        var storedColumns = store.get(JSON.stringify(key));
        var storedNames = [];
        if(storedColumns){
            $.each(storedColumns, function(i, col){
                storedNames.push(col.name);
            });
            names.sort();
            storedNames.sort();
            if(String(names) == String(storedNames)){
                columns = storedColumns;
            }
        }

        // create the table
        grid = new Slick.Grid("#datagrid", data, columns, options);
        var ordercolumn = null;
        var orderdirection = null;

        // handle sorting of data
        grid.onSort.subscribe(function(e, args){
            $('#data h2 small').show();
            grid.scrollRowIntoView(0);
            ordercolumn = args.sortCol.field;
            orderdirection = args.sortAsc;
            sqlite({
                table: table_name,
                orderby: ordercolumn + ' ' + (orderdirection ? 'asc' : 'desc')
            }).done(function(newdata){
                data = newdata;
                grid.setData(data);
                grid.updateRowCount();
                grid.render();
                $('#data h2 small').hide();
            });
        });

        // infinite scrolling
        var loading = false;
        var allDataLoaded = false;
        var rowsToGet = 100;
        grid.onViewportChanged.subscribe(function (e, args) {
            if(!loading && !allDataLoaded && grid.getViewport().bottom + 20 > grid.getDataLength()){
                $('#data h2 small').show();
                loading = true;
                var sqlite_options = {
                    table: table_name,
                    limit: rowsToGet,
                    offset: grid.getDataLength()
                }
                if(ordercolumn && orderdirection){
                    sqlite_options['orderby'] = ordercolumn + ' ' + (orderdirection ? 'asc' : 'desc');
                }
                sqlite(sqlite_options).done(function(newdata){
                    $.each(newdata, function(i,row){
                        data.push(row);
                    });
                    grid.updateRowCount();
                    grid.render();
                    loading = false;
                    $('#data h2 small').hide();
                    if(newdata.length < rowsToGet){
                        allDataLoaded = true;
                    }
                });
            }
        });

        function saveColumnInfo(e, args){
            var key = [location.pathname, 'columns', table_name];
            store.set(JSON.stringify(key), args.grid.getColumns())
        }

        grid.onColumnsReordered.subscribe(saveColumnInfo);
        grid.onColumnsResized.subscribe(saveColumnInfo);

    });
}

$(function(){

    $.ajax({
        url: "README.symlink.md",
        dataType: 'text',
        cache: false,
        success: function(text){
            $('#notes h2 small').hide();
            var converter = new Showdown.converter();
            var html = converter.makeHtml(text);
            $('#notes').append('
' + html + '
');
        }, error: function(jqXHR, textStatus, errorThrown){
            $('#notes h2 small').hide();
            $('
').addClass('alert').html('<button type="button" class="close" data-dismiss="alert">×</button> Sorry! We couldn’t find your project’s README.md file. Are you sure it exists?').appendTo('#notes');
        }
    });

    $.ajax({
        url: "scraperwiki.symlink.json",
        dataType: 'json',
        cache: false,
        success: function(data){
            if('project_name' in data){
                $('#info h1 strong').text(data['project_name']);
                $('title').text(data['project_name'] + ' | powered by ScraperWiki');
            }
            if('customer_name' in data){
                $('#info h1 small').text(data['customer_name']);
            } else {
                $('#info h1 small').hide();
            }
            if('status_message' in data){
                $('#info .lead').html('Latest status: ' + data['status_message']);
            } else {
                $('#info .lead').hide();
            }
        }, error: function(jqXHR, textStatus, errorThrown){
            $('
').addClass('alert').html('<button type="button" class="close" data-dismiss="alert">×</button> Something went wrong! We couldn’t find your project’s scraperwiki.json file. Are you sure it exists?').prependTo('#info');
            $('#info .lead').hide();
            $('#info h1 small').hide();
        }
    });

    sqlite().done(function(tables){
        if(tables.length == 0){
            // no tables
            $('#data').hide();
        } else {
            var key = [location.pathname, 'tab'];
            var storedTableName = store.get(JSON.stringify(key));
            var name = storedTableName || tables[0]['name'];

            var $ul = $('
').addClass('nav nav-tabs');
            $.each(tables, function(i, table){
                $('
').append('' + table['name'] + '').bind('click', function(e){
                    e.preventDefault();
                    $(this).addClass('active').siblings('.active').removeClass('active');
                    showSlickGrid($(this).text());
                    var key = [location.pathname, 'tab'];
                    store.set(JSON.stringify(key), $(this).text());
                }).appendTo($ul);
            });
            $ul.appendTo('#data');
            $('
').appendTo('#data');

            showSlickGrid(name);
        }
        $('#data h2 small').hide();
    }).fail(function(jqXHR, textStatus, errorThrown){
        $('
').addClass('alert').html('<button type="button" class="close" data-dismiss="alert">×</button> Something went wrong! We couldn’t select data from your project’s SQLite API.').appendTo('#data');
        $('#datagrid').hide();
        $('#data h2 small').hide();
    });

    var $hds = $('').addClass('drop-shadow').appendTo('.page-header');
    $(window).scroll(function(){
        var st = $(window).scrollTop();
        var op = 0;
        if(st > 0){
            op = Math.min(1, st/30);
        }
        $hds.css('opacity', op);
    });

});
<commit_msg>table names escaped<commit_after>function sqlite(args){
    var options = {
        columns: "*",
        table: "[sqlite_master] WHERE (type='table' OR type='view') AND name NOT LIKE '#_%'  ESCAPE '#'",
        limit: 50,
        offset: 0,
        orderby: null
    }
    $.extend(true, options, args);
    return $.ajax({
        url: "../../sqlite",
        dataType: 'json',
        cache: false,
        data: {
            q: 'SELECT ' + options.columns + ' FROM ' + options.table + ( options.orderby ? ' ORDER BY ' + options.orderby : '' ) + ' LIMIT ' + options.limit + ' OFFSET ' + options.offset
        }
    });
}

function showSlickGrid(table_name){
    sqlite({
        table: '[' + table_name + ']'
    }).done(function(data){
        var grid;
        var options = {
            enableColumnReorder: true,
            enableTextSelectionOnCells: true
        }
        // create column definitions from first row of data
        var columns = [];
        var names = [];
        for(var key in data[0]){
            columns.push({
                id: key,
                name: key,
                field: key,
                sortable: true
            });
            names.push(key);
        }

        var key = [location.pathname, 'columns', table_name]
        var storedColumns = store.get(JSON.stringify(key));
        var storedNames = [];
        if(storedColumns){
            $.each(storedColumns, function(i, col){
                storedNames.push(col.name);
            });
            names.sort();
            storedNames.sort();
            if(String(names) == String(storedNames)){
                columns = storedColumns;
            }
        }

        // create the table
        grid = new Slick.Grid("#datagrid", data, columns, options);
        var ordercolumn = null;
        var orderdirection = null;

        // handle sorting of data
        grid.onSort.subscribe(function(e, args){
            $('#data h2 small').show();
            grid.scrollRowIntoView(0);
            ordercolumn = args.sortCol.field;
            orderdirection = args.sortAsc;
            sqlite({
                table: table_name,
                orderby: ordercolumn + ' ' + (orderdirection ? 'asc' : 'desc')
            }).done(function(newdata){
                data = newdata;
                grid.setData(data);
                grid.updateRowCount();
                grid.render();
                $('#data h2 small').hide();
            });
        });

        // infinite scrolling
        var loading = false;
        var allDataLoaded = false;
        var rowsToGet = 100;
        grid.onViewportChanged.subscribe(function (e, args) {
            if(!loading && !allDataLoaded && grid.getViewport().bottom + 20 > grid.getDataLength()){
                $('#data h2 small').show();
                loading = true;
                var sqlite_options = {
                    table: table_name,
                    limit: rowsToGet,
                    offset: grid.getDataLength()
                }
                if(ordercolumn && orderdirection){
                    sqlite_options['orderby'] = ordercolumn + ' ' + (orderdirection ? 'asc' : 'desc');
                }
                sqlite(sqlite_options).done(function(newdata){
                    $.each(newdata, function(i,row){
                        data.push(row);
                    });
                    grid.updateRowCount();
                    grid.render();
                    loading = false;
                    $('#data h2 small').hide();
                    if(newdata.length < rowsToGet){
                        allDataLoaded = true;
                    }
                });
            }
        });

        function saveColumnInfo(e, args){
            var key = [location.pathname, 'columns', table_name];
            store.set(JSON.stringify(key), args.grid.getColumns())
        }

        grid.onColumnsReordered.subscribe(saveColumnInfo);
        grid.onColumnsResized.subscribe(saveColumnInfo);

    });
}

$(function(){

    $.ajax({
        url: "README.symlink.md",
        dataType: 'text',
        cache: false,
        success: function(text){
            $('#notes h2 small').hide();
            var converter = new Showdown.converter();
            var html = converter.makeHtml(text);
            $('#notes').append('
' + html + '
');
        }, error: function(jqXHR, textStatus, errorThrown){
            $('#notes h2 small').hide();
            $('
').addClass('alert').html('<button type="button" class="close" data-dismiss="alert">×</button> Sorry! We couldn’t find your project’s README.md file. Are you sure it exists?').appendTo('#notes');
        }
    });

    $.ajax({
        url: "scraperwiki.symlink.json",
        dataType: 'json',
        cache: false,
        success: function(data){
            if('project_name' in data){
                $('#info h1 strong').text(data['project_name']);
                $('title').text(data['project_name'] + ' | powered by ScraperWiki');
            }
            if('customer_name' in data){
                $('#info h1 small').text(data['customer_name']);
            } else {
                $('#info h1 small').hide();
            }
            if('status_message' in data){
                $('#info .lead').html('Latest status: ' + data['status_message']);
            } else {
                $('#info .lead').hide();
            }
        }, error: function(jqXHR, textStatus, errorThrown){
            $('
').addClass('alert').html('<button type="button" class="close" data-dismiss="alert">×</button> Something went wrong! We couldn’t find your project’s scraperwiki.json file. Are you sure it exists?').prependTo('#info');
            $('#info .lead').hide();
            $('#info h1 small').hide();
        }
    });

    sqlite().done(function(tables){
        if(tables.length == 0){
            // no tables
            $('#data').hide();
        } else {
            var key = [location.pathname, 'tab'];
            var storedTableName = store.get(JSON.stringify(key));
            var name = storedTableName || tables[0]['name'];

            var $ul = $('
').addClass('nav nav-tabs');
            $.each(tables, function(i, table){
                $('
').append('' + table['name'] + '').bind('click', function(e){
                    e.preventDefault();
                    $(this).addClass('active').siblings('.active').removeClass('active');
                    showSlickGrid($(this).text());
                    var key = [location.pathname, 'tab'];
                    store.set(JSON.stringify(key), $(this).text());
                }).appendTo($ul);
            });
            $ul.appendTo('#data');
            $('
').appendTo('#data');

            showSlickGrid(name);
        }
        $('#data h2 small').hide();
    }).fail(function(jqXHR, textStatus, errorThrown){
        $('
').addClass('alert').html('<button type="button" class="close" data-dismiss="alert">×</button> Something went wrong! We couldn’t select data from your project’s SQLite API.').appendTo('#data');
        $('#datagrid').hide();
        $('#data h2 small').hide();
    });

    var $hds = $('').addClass('drop-shadow').appendTo('.page-header');
    $(window).scroll(function(){
        var st = $(window).scrollTop();
        var op = 0;
        if(st > 0){
            op = Math.min(1, st/30);
        }
        $hds.css('opacity', op);
    });

});
<|endoftext|>


<commit_before>"use strict";
/* jshint undef: true, unused: true */
/* global Applet, describe, it, expect, beforeEach */

$(function () {
});

describe('Applet:', function () {

  beforeEach(function () {
    $('#THE_STAGE').empty();
    Applet.reset();
  });

  describe('compiling scripts:', function () {

    it('does not re-evaluate scripts', function () {
      $('#THE_STAGE').html('');
      Applet.run('compile scripts');
      Applet.run('compile scripts');
      Applet.run('compile scripts');
      expect($('#THE_STAGE').html()).toEqual('
OK
');
    }); // === it does not re-evaluate scripts

    it('keeps evaulating nested scripts until done', function () {
      $('#THE_STAGE').html(
        '' +
          '</script>' +
        '</script>'
      );

      Applet.run('compile scripts');
      expect(
        $('#THE_STAGE').html()
      ).toEqual('
OK
');
    }); // === it keeps evaulating nested scripts until done
  }); // === describe compiling scripts =================

}); // === describe Applet =================

describe('attrs:', function () {

  beforeEach(Applet.reset);

  it('returns attrs of node', function () {
    var result = Applet.attrs($('

')[0]);
    expect(result).toEqual({id: "000", img: ".png"});
  }); // === it returns attrs of node

}); // === describe attrs =================

describe('node_array:', function () {

  beforeEach(function () {
    $('#THE_STAGE').empty();
    Applet.reset();
  });

  it('returns an Array when passed a String', function () {
    var arr = Applet.node_array('

');

    expect(arr).toEqual([
      {
        tag:   'DIV',
        attrs:  {id: '111', show_if: 'happy?'},
        custom: {},
        childs: [
          {tag: 'SPAN', attrs: {}, custom: {}, childs: []}
        ]
      }
    ]);
  }); // === it returns an Array when passed a String

  it('returns raw text nodes', function () {
    var arr = Applet.node_array('
ab
');

    expect(
      _.pluck(arr[0].childs[0].childs, 'nodeValue')
    ).toEqual(
      ['a', undefined, 'b']
    );
  }); // === it returns raw text nodes

}); // === describe node_array =================
<commit_msg>Added: specs<commit_after>"use strict";
/* jshint undef: true, unused: true */
/* global Applet, describe, it, expect, beforeEach */

$(function () {
});

describe('Applet:', function () {

  beforeEach(function () {
    $('#THE_STAGE').empty();
    Applet.reset();
  });

  describe('id:', function () {

    it('adds ID attr to element', function () {
      var stage = $('#THE_STAGE');
      stage.html('
id
');
      var id = Applet.id($('#THE_STAGE div:first'));
      expect(
        $('#' + id).html()
      ).toEqual('id');
    }); // === it adds ID attr to element

    it('does not override original ID', function () {
      var stage = $('#THE_STAGE');
      stage.html('
override id
');
      var id = Applet.id($('#THE_STAGE div:first'));
      expect(id).toEqual('non_override_1');
    }); // === it does not override original ID

  }); // === describe id =================

  describe('attrs:', function () {

    it('returns attrs of node', function () {
      var result = Applet.attrs($('

')[0]);
      expect(result).toEqual({id: "000", img: ".png"});
    }); // === it returns attrs of node

  }); // === describe attrs =================

  describe('node_array:', function () {

    it('returns an Array when passed a String', function () {
      var arr = Applet.node_array('

');

      expect(arr).toEqual([
        {
        tag:   'DIV',
        attrs:  {id: '111', show_if: 'happy?'},
        custom: {},
        childs: [
          {tag: 'SPAN', attrs: {}, custom: {}, childs: []}
        ]
      }
      ]);
    }); // === it returns an Array when passed a String

    it('returns raw text nodes', function () {
      var arr = Applet.node_array('
ab
');

      expect(
        _.pluck(arr[0].childs[0].childs, 'nodeValue')
      ).toEqual(
      ['a', undefined, 'b']
      );
    }); // === it returns raw text nodes

  }); // === describe node_array =================

  describe('compiling scripts:', function () {

    it('does not re-evaluate scripts', function () {
      $('#THE_STAGE').html('');
      Applet.run('compile scripts');
      Applet.run('compile scripts');
      Applet.run('compile scripts');
      expect($('#THE_STAGE').html()).toEqual('
OK
');
    }); // === it does not re-evaluate scripts

    it('keeps evaulating nested scripts until done', function () {
      $('#THE_STAGE').html(
        '' +
        '</script>' +
        '</script>'
      );

      Applet.run('compile scripts');
      expect(
        $('#THE_STAGE').html()
      ).toEqual('
OK
');
    }); // === it keeps evaulating nested scripts until done
  }); // === describe compiling scripts =================

}); // === describe Applet =================
<|endoftext|>


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

var request = require('request');
var geotrigger = require('geotrigger-js');
var JSONStream = require('JSONStream');
var Mustache = require('Mustache');
var colors = require('colors');
var argv = require('optimist')
    .usage('Usage: $0 -i [clientId] -s [clientSecret] -u [serviceUrl] -t [tags]')
    .demand(['clientId', 'clientSecret', 'tag', 'serviceUrl'])
    .alias('t', 'tag')
    .default('buffer', '250')
    .default('direction', 'enter')
    .describe({
      'clientId': 'client id from an application on developers.arcgis.com',
      'clientSecret': 'client secret from an application on developers.arcgis.com',
      'tag': 'tag to apply to the triggers created in the Geotrigger API',
      'serviceUrl': 'the URL of the Feature Layer you would like to import',
      'buffer': 'if you are importing point features, buffer them by this amount to create the trigger area',
      'trackingProfile':'Changes the devices tracking profile to this at when the trigger is fired',
      'notificationTemplate': 'A Mustache template for the push notification. Feature attributes will be passed into the template context',
      'useFeatureIds': 'use the ids of the feautres as the id of the trigger',
      'callbackUrl': 'when the triggers condition is satisfied a POST request will be sent to this URL'
    })
    .check(function(argv){
      if (!argv.callbackUrl && !argv.notificationTemplate && !argv.trackingProfile) {
        throw 'At least one of --callbackUrl, --notificationTemplate or --trackingProfile is required';
      }
    })
    .check(function(argv){
      if (argv.trackingProfile && !argv.trackingProfile.match(/off|rough|adaptive|fine/)) {
        throw '--trackingProfile must bes off, rough, fine or adaptive';
      }
    })
    .argv;

var geotriggers = new geotrigger.Session({
  clientId: argv.clientId,
  clientSecret: argv.clientSecret
});

console.log("Getting metadata for " + argv.serviceUrl);

request({
  method: "GET",
  url: argv.serviceUrl,
  json: true,
  form: {
    f: 'json'
  }
}, function (error, response, body) {

  if(error || body.error) {
    console.log('Error!'.red.bold + ' Could not get metadata for ' + argv.serviceUrl);
    process.exit(1);
  }

  if(body.geometryType === 'esriGeometryPolyline'){
    console.log('Error!'.red.bold + ' featureservice2geotrigger cannot import Feature Services that contain polylines');
    process.exit(1);
  }

  if(body){
    console.log("Success!".green.bold + " Got metadata for " + argv.serviceUrl);
    console.log("");

    var errors = 0;
    var successes = 0;
    var features = 0;
    var processed = 0;
    var featureIdAttribute = body.objectIdField;
    var featureParser = JSONStream.parse(['features', true]);
    var tags;

    if(Array.isArray(argv.tag)){
      tags = argv.tag;
    } else {
      tags = [argv.tag];
    }

    console.log('Requesting Features...');

    request({
      method: 'GET',
      url: argv.serviceUrl + '/query',
      form: {
        where: '1=1', // 'truthy' query to get all features
        outSR: 4326, // the Geotrigger Service only uses 4326
        outFields: '*', // get all fields as output
        f: 'json' // we want JSON back
      },
      json: true
    }).pipe(featureParser); // send the results of this request to our JSON parser

    featureParser.on('data', function (feature) {
      features++;

      var geo = {};
      var action = {};
      var featureId = feature.attributes[featureIdAttribute] + "";
      var triggerParams;

      if(feature.geometry.rings){
        geo = {
          esrijson: feature.geometry
        };
      }

      if(feature.geometry.x && feature.geometry.y){
        geo = {
          latitude: feature.geometry.y,
          longitude: feature.geometry.x,
          distance: argv.buffer
        };
      }

      if(argv.callbackUrl) {
        action.callbackUrl = argv.callbackUrl;
      }

      if(argv.notificationTemplate) {
        action.notification = {
          text: Mustache.render(argv.notificationTemplate, feature.attributes)
        };
      }

      if(argv.trackingProfile) {
        action.trackingProfile = argv.trackingProfile;
      }

      triggerParams = {
        condition: {
          direction: argv.direction,
          geo: geo
        },
        action: action,
        setTags: tags,
        properties: feature.attributes
      };

      if(argv.useFeatureIds){
        triggerParams.triggerId = featureId;
      }

      geotriggers.request('trigger/create', triggerParams, function(error, response){
        processed++;

        if(error){
          errors++;
          console.log('Error!'.red.bold + ' Could not create trigger from feature with id ' + featureId, error);
        }

        if(response){
          successes++;
          console.log('Success!'.green.bold + ' Trigger tagged ' + JSON.stringify(response.tags) + ' with id ' + response.triggerId + ' created from feature with id '+ featureId);
        }

        if(processed >= features){
          console.log((errors+successes + ' features').bold +' '+ (successes + ' successes').green.bold +' '+ (errors + ' errors').red.bold);
        }
      });
    });
  }
});<commit_msg>update usage<commit_after>#!/usr/bin/env node

var request = require('request');
var geotrigger = require('geotrigger-js');
var JSONStream = require('JSONStream');
var Mustache = require('Mustache');
var colors = require('colors');
var argv = require('optimist')
    .usage('Usage: $0 --clientSecret=[clientId] --clientSecret=[clientSecret] --serviceUrl=[serviceUrl] -t [tag] -t otherTag')
    .demand(['clientId', 'clientSecret', 'tag', 'serviceUrl'])
    .alias('t', 'tag')
    .default('buffer', '250')
    .default('direction', 'enter')
    .describe({
      'clientId': 'client id from an application on developers.arcgis.com',
      'clientSecret': 'client secret from an application on developers.arcgis.com',
      'tag': 'tag to apply to the triggers created in the Geotrigger API',
      'serviceUrl': 'the URL of the Feature Layer you would like to import',
      'buffer': 'if you are importing point features, buffer them by this amount to create the trigger area',
      'trackingProfile':'Changes the devices tracking profile to this at when the trigger is fired',
      'notificationTemplate': 'A Mustache template for the push notification. Feature attributes will be passed into the template context',
      'useFeatureIds': 'use the ids of the feautres as the id of the trigger',
      'callbackUrl': 'when the triggers condition is satisfied a POST request will be sent to this URL'
    })
    .check(function(argv){
      if (!argv.callbackUrl && !argv.notificationTemplate && !argv.trackingProfile) {
        throw 'At least one of --callbackUrl, --notificationTemplate or --trackingProfile is required';
      }
    })
    .check(function(argv){
      if (argv.trackingProfile && !argv.trackingProfile.match(/off|rough|adaptive|fine/)) {
        throw '--trackingProfile must bes off, rough, fine or adaptive';
      }
    })
    .argv;

var geotriggers = new geotrigger.Session({
  clientId: argv.clientId,
  clientSecret: argv.clientSecret
});

console.log("Getting metadata for " + argv.serviceUrl);

request({
  method: "GET",
  url: argv.serviceUrl,
  json: true,
  form: {
    f: 'json'
  }
}, function (error, response, body) {

  if(error || body.error) {
    console.log('Error!'.red.bold + ' Could not get metadata for ' + argv.serviceUrl);
    process.exit(1);
  }

  if(body.geometryType === 'esriGeometryPolyline'){
    console.log('Error!'.red.bold + ' featureservice2geotrigger cannot import Feature Services that contain polylines');
    process.exit(1);
  }

  if(body){
    console.log("Success!".green.bold + " Got metadata for " + argv.serviceUrl);
    console.log("");

    var errors = 0;
    var successes = 0;
    var features = 0;
    var processed = 0;
    var featureIdAttribute = body.objectIdField;
    var featureParser = JSONStream.parse(['features', true]);
    var tags;

    if(Array.isArray(argv.tag)){
      tags = argv.tag;
    } else {
      tags = [argv.tag];
    }

    console.log('Requesting Features...');

    request({
      method: 'GET',
      url: argv.serviceUrl + '/query',
      form: {
        where: '1=1', // 'truthy' query to get all features
        outSR: 4326, // the Geotrigger Service only uses 4326
        outFields: '*', // get all fields as output
        f: 'json' // we want JSON back
      },
      json: true
    }).pipe(featureParser); // send the results of this request to our JSON parser

    featureParser.on('data', function (feature) {
      features++;

      var geo = {};
      var action = {};
      var featureId = feature.attributes[featureIdAttribute] + "";
      var triggerParams;

      if(feature.geometry.rings){
        geo = {
          esrijson: feature.geometry
        };
      }

      if(feature.geometry.x && feature.geometry.y){
        geo = {
          latitude: feature.geometry.y,
          longitude: feature.geometry.x,
          distance: argv.buffer
        };
      }

      if(argv.callbackUrl) {
        action.callbackUrl = argv.callbackUrl;
      }

      if(argv.notificationTemplate) {
        action.notification = {
          text: Mustache.render(argv.notificationTemplate, feature.attributes)
        };
      }

      if(argv.trackingProfile) {
        action.trackingProfile = argv.trackingProfile;
      }

      triggerParams = {
        condition: {
          direction: argv.direction,
          geo: geo
        },
        action: action,
        setTags: tags,
        properties: feature.attributes
      };

      if(argv.useFeatureIds){
        triggerParams.triggerId = featureId;
      }

      geotriggers.request('trigger/create', triggerParams, function(error, response){
        processed++;

        if(error){
          errors++;
          console.log('Error!'.red.bold + ' Could not create trigger from feature with id ' + featureId, error);
        }

        if(response){
          successes++;
          console.log('Success!'.green.bold + ' Trigger tagged ' + JSON.stringify(response.tags) + ' with id ' + response.triggerId + ' created from feature with id '+ featureId);
        }

        if(processed >= features){
          console.log((errors+successes + ' features').bold +' '+ (successes + ' successes').green.bold +' '+ (errors + ' errors').red.bold);
        }
      });
    });
  }
});<|endoftext|>


<commit_before>// An example of how to use Three.js to display a tubular shape.
var request, mesh, renderer, scene, camera, directionalLight, controls, phantom;
var path = "examples/isbi_challenge_2013.txt";

init();

function render() {
  renderer.render(scene, camera);
}

function animate() {
  requestAnimationFrame( animate );
  controls.update();
}

function init() {
  request = new XMLHttpRequest();
  request.overrideMimeType("text/plain");
  request.open("get", path, true);
  request.onreadystatechange = function() {
    if ( (request.readyState === 4) && (request.status === 200) ) {
      show();
    }
  }
  request.send(null);
}

function show() { // The rendering engine is initialized
  renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);

  // It is appended to the div container in the HTML5 tree
  document.getElementById('container').appendChild(renderer.domElement);
  var k=0;

  // We create a scene and a camera. Position is to be corrected further in the code.
  camera = new THREE.PerspectiveCamera(50,
                                       window.innerWidth / window.innerHeight,
                                       1,
                                       10000);
  camera.position.set(0, 0, 0);

  // Create, the scene and add cameras, lights.
  scene = new THREE.Scene();
  scene.add(camera);
  scene.add(new THREE.AmbientLight( 0xffffff, .5 ) );
  // Directional lights are added in all directions
  for (var x = -100; x <= 100; x=x+200) {
    for (var y = -100; y <= 100; y=y+200) {
      for (var z = -100; z <= 100; z=z+20) {
        var directionalLight = new THREE.DirectionalLight(0x555555, .15);
        directionalLight.position.x = x;
        directionalLight.position.y = y;
        directionalLight.position.z = z;
        scene.add(directionalLight);
      }
    }
  }

  // Load phantom and add it in the scene
  phantom = loadPhantom( request );
  phantom.highlightOpacity = .2;
  phantom.addToScene(scene);
  camera.position.z = phantom.radius()*1.5;

  renderer.render(scene, camera);

  // KeyPress consecution loop for features show.

  // Add mouse control to the camera
  controls = new THREE.TrackballControls( camera );
  controls.enableZoom = true;
  controls.rotateSpeed = 2.5;
  controls.zoomSpeed = 1;
  controls.noPan=true;
  controls.addEventListener('change', render);

  var presscount = 0;
  keypress = function() {
    if (presscount/2 < phantom.fibers.source.length) {
      if (presscount % 2 == 0) {
        phantom.addToScene(scene);
        phantom.fiberHighlight(presscount/2);
        presscount++;
      }
      else {
        phantom.addToScene(scene);
        phantom.revealSkeleton(scene, (presscount-1)/2);
        presscount++;
      }
    }
    else if (presscount/2-phantom.fibers.source.length < phantom.isotropicRegions.source.length) {
      phantom.addToScene(scene);
      phantom.regionHighlight(presscount/2-phantom.fibers.source.length);
      presscount+=2;
    }
    else if (presscount/2-phantom.fibers.source.length == phantom.isotropicRegions.source.length) {
      scene.removePhantom();
      phantom.addAsSkeleton(scene)
      presscount++;
    }
    else {
      scene.removePhantom();
      phantom.addToScene(scene);
      phantom.unfadeAll();
      presscount = 0;
    }
  }
  window.addEventListener('keypress', keypress);

  animate();
}
<commit_msg>Added window resize event listener.<commit_after>// An example of how to use Three.js to display a tubular shape.
var request, mesh, renderer, scene, camera, directionalLight, controls, phantom;
var path = "examples/60crossing_3bundles.txt";

init();

function render() {
  renderer.render(scene, camera);
}

function animate() {
  requestAnimationFrame( animate );
  controls.update();
}

function init() {
  request = new XMLHttpRequest();
  request.overrideMimeType("text/plain");
  request.open("get", path, true);
  request.onreadystatechange = function() {
    if ( (request.readyState === 4) && (request.status === 200) ) {
      show();
    }
  }
  request.send(null);
}

function show() { // The rendering engine is initialized
  renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);

  // It is appended to the div container in the HTML5 tree
  document.getElementById('container').appendChild(renderer.domElement);
  var k=0;

  // We create a scene and a camera. Position is to be corrected further in the code.
  camera = new THREE.PerspectiveCamera(50,
                                       window.innerWidth / window.innerHeight,
                                       1,
                                       10000);
  camera.position.set(0, 0, 0);

  // Create, the scene and add cameras, lights.
  scene = new THREE.Scene();
  scene.add(camera);
  scene.add(new THREE.AmbientLight( 0xffffff, .5 ) );
  // Directional lights are added in all directions
  for (var x = -100; x <= 100; x=x+200) {
    for (var y = -100; y <= 100; y=y+200) {
      for (var z = -100; z <= 100; z=z+20) {
        var directionalLight = new THREE.DirectionalLight(0x555555, .15);
        directionalLight.position.x = x;
        directionalLight.position.y = y;
        directionalLight.position.z = z;
        scene.add(directionalLight);
      }
    }
  }

  // Load phantom and add it in the scene
  phantom = loadPhantom( request );
  phantom.highlightOpacity = .2;
  phantom.addToScene(scene);
  camera.position.z = phantom.radius()*1.5;

  renderer.render(scene, camera);

  // KeyPress consecution loop for features show.

  // Add mouse control to the camera
  controls = new THREE.TrackballControls( camera );
  controls.enableZoom = true;
  controls.rotateSpeed = 2.5;
  controls.zoomSpeed = 1;
  controls.noPan=true;
  controls.addEventListener('change', render);

  var presscount = 0;
  keypress = function() {
    if (presscount/2 < phantom.fibers.source.length) {
      if (presscount % 2 == 0) {
        phantom.addToScene(scene);
        phantom.fiberHighlight(presscount/2);
        presscount++;
      }
      else {
        phantom.addToScene(scene);
        phantom.revealSkeleton(scene, (presscount-1)/2);
        presscount++;
      }
    }
    else if (presscount/2-phantom.fibers.source.length < phantom.isotropicRegions.source.length) {
      phantom.addToScene(scene);
      phantom.regionHighlight(presscount/2-phantom.fibers.source.length);
      presscount+=2;
    }
    else if (presscount/2-phantom.fibers.source.length == phantom.isotropicRegions.source.length) {
      scene.removePhantom();
      phantom.addAsSkeleton(scene)
      presscount++;
    }
    else {
      scene.removePhantom();
      phantom.addToScene(scene);
      phantom.unfadeAll();
      presscount = 0;
    }
  }
  window.addEventListener('keypress', keypress);
  window.addEventListener( 'resize', onWindowResize, false );
  function onWindowResize(){
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize( window.innerWidth, window.innerHeight );
    render();
  }

  animate();
}
<|endoftext|>


<commit_before>import jq from 'jquery';
import React from 'react';
import ReactDOM from 'react-dom';
import ReactTestUtils from 'react-addons-test-utils';
import jsdom from 'jsdom';
import chai, { expect } from 'chai';
import chaiJquery from 'chai-jquery';
import createHistory from 'history/lib/createBrowserHistory';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import reducers from '../../src/js/reducers';

// Global prerequisites to make it work in the command line
global.document = jsdom.jsdom('<!doctype html>');
global.window = global.document.defaultView;
const $ = jq(window);

// Set up chai-jquery
chaiJquery(chai, chai.util, $);

function renderComponent(ComponentClass, props = {}, state = {}) {
  const componentInstance = ReactTestUtils.renderIntoDocument(
    <Provider store={createStore(reducers, state)}>
      <ComponentClass {...props} />
    </Provider>
  );

  // Produces HTML
  return $(ReactDOM.findDOMNode(componentInstance));
}

function mockHistory(component) {
  component.childContextTypes = { history: React.PropTypes.object };
  component.prototype.getChildContext = () => ({ history: createHistory() });
}

// Helper for simulating events
$.fn.simulate = function(eventName, value) {
  if (value) {
    this.val(value);
  }
  ReactTestUtils.Simulate[eventName](this[0]);
};

export { renderComponent, mockHistory, expect };
<commit_msg>Load store into the tested components too<commit_after>import jq from 'jquery';
import React from 'react';
import ReactDOM from 'react-dom';
import ReactTestUtils from 'react-addons-test-utils';
import jsdom from 'jsdom';
import chai, { expect } from 'chai';
import chaiJquery from 'chai-jquery';
import createHistory from 'history/lib/createBrowserHistory';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import reducers from '../../src/js/reducers';

// Global prerequisites to make it work in the command line
global.document = jsdom.jsdom('<!doctype html>');
global.window = global.document.defaultView;
const $ = jq(window);

// Set up chai-jquery
chaiJquery(chai, chai.util, $);

function renderComponent(ComponentClass, props = {}, state = {}) {
  const store = createStore(reducers, state);
  props.store = store;
  const componentInstance = ReactTestUtils.renderIntoDocument(
    <Provider store={store}>
      <ComponentClass {...props} />
    </Provider>
  );

  // Produces HTML
  return $(ReactDOM.findDOMNode(componentInstance));
}

function mockHistory(component) {
  component.childContextTypes = { history: React.PropTypes.object };
  component.prototype.getChildContext = () => ({ history: createHistory() });
}

// Helper for simulating events
$.fn.simulate = function(eventName, value) {
  if (value) {
    this.val(value);
  }
  ReactTestUtils.Simulate[eventName](this[0]);
};

export { renderComponent, mockHistory, expect };
<|endoftext|>


<commit_before>define(function (require) {
    var resource_js = require('app/resource'),
        building_js = require('app/building'),
        w2ui = require('w2ui-1.4.2'),
        $ = require('jquery');
});

function write_log(message) {
    $("#log_contents").prepend(message);
}

function display_resources() {
    for (res in resource) {
        if (resource[res].visible) {
            //display the resource
            $("#disp_" + res).html(resource[res].name + ": " + resource[res].value.toFixed(3));
            $("#disp_" + res).show();
        }
    }
}

function update_buttons() {
    for (structure in building) {
        if (!building.hasOwnProperty(structure)) {
            //The current property is not a direct property of p
            continue;
        }
        $("#btn_" + structure).html(building[structure].name + " (" + building[structure].count + ")");
        if (building[structure].count > 0) {
            $("#btn_" + structure).attr("disabled", true);
            $("#btn_" + structure).show();
        } else {
            $("#btn_" + structure).hide();
        }
        if (can_build(structure)) {
            $("#btn_" + structure).removeAttr("disabled");
            $("#btn_" + structure).show();
        }
    }
    if (resource.biomass.value < 5) {
        $("#btn_consume").attr("disabled", true);
    } else {
        $("#btn_consume").removeAttr("disabled");
    }
}

function create_controls() {
    for (structure in building) {
        if (!building.hasOwnProperty(structure)) {
            //The current property is not a direct property
            continue;
        }
        $("#control").append("<button id='btn_" + structure + "' style='display:none'>" + building[structure].name + " (" + building[structure].count + ")</button>");
        $("#btn_" + structure).on("click", {
            structure: structure
        }, build);
    }
    for (minion in minions) {
        if (!minions.hasOwnProperty(minion)) {
            //The current property is not a direct property
            continue;
        }
        $("#minion").append("" + minions[minion].name + " " + minions[minion].current + "\n");
    }
}

function generate_basic_buttons() {
    $("#control").append("<button id='btn_stone'>Rummage for Stone</button>");
    $("#control").append("<button id='btn_biomass'>Scrape up Detritus</button>");
    $("#control").append("<button id='btn_consume' title='Devour Biomass to unlock your potential'>CONSUME</button>");
    //add listeners to buttons
    $("#btn_stone").on("click", collect_stone);
    $("#btn_biomass").on("click", collect_biomass);
    $("#btn_consume").on("click", consume);
}

function switch_panel(panel) {
    if (panel == 'tab_control'){
        $("#minion").hide();
        $("#tech").hide();
        $("#control").show();
    } else if (panel == 'tab_tech'){
        $("#control").hide();
        $("#minion").hide();
        $("#tech").show();
    } else if (panel == 'tab_minion'){
        $("#control").hide();
        $("#tech").hide();
        $("#minion").show();
    }
}

function initialise_gui() {
    var control_divs = '

';
    control_divs += '

';
    control_divs += '

';
    var pstyle = 'border: 1px solid #dfdfdf; padding: 5px;';
    $('#mainwindow').w2layout({
        name: 'mainwindow',
        panels: [
            { type: 'top', size: 30, resizable: false, style: pstyle, content: 'Steam Lizards v0.07' },
            { type: 'left', size: 200, resizable: false, style: pstyle, content: '

' },
            { type: 'main', style: pstyle + 'border-top: 0px;', content: control_divs,
                tabs: {
                    active: 'tab_control',
                    tabs: [
                        { id: 'tab_control', caption: 'Control' },
                        { id: 'tab_tech', caption: 'Technology' },
                        { id: 'tab_minion', caption: 'Minions' },
                    ],
                    onClick: function (event) {
                        switch_panel(event.target);
                    }
                }
            },
            { type: 'right', size: 200, resizable: false, style: pstyle, content: 'Captains "Log":

'}
        ]
    });
    w2ui.mainwindow.panels[2].tabs.hide('tab_tech');
    w2ui.mainwindow.panels[2].tabs.hide('tab_minion');
    generate_basic_buttons();
}

function update_gui() {
    display_resources();
    update_buttons();
    manage_technology();
    fill_housing();
}<commit_msg>v0.08<commit_after>define(function (require) {
    var resource_js = require('app/resource'),
        building_js = require('app/building'),
        w2ui = require('w2ui-1.4.2'),
        $ = require('jquery');
});

function write_log(message) {
    $("#log_contents").prepend(message);
}

function display_resources() {
    for (res in resource) {
        if (resource[res].visible) {
            //display the resource
            $("#disp_" + res).html(resource[res].name + ": " + resource[res].value.toFixed(3));
            $("#disp_" + res).show();
        }
    }
}

function update_buttons() {
    for (structure in building) {
        if (!building.hasOwnProperty(structure)) {
            //The current property is not a direct property of p
            continue;
        }
        $("#btn_" + structure).html(building[structure].name + " (" + building[structure].count + ")");
        if (building[structure].count > 0) {
            $("#btn_" + structure).attr("disabled", true);
            $("#btn_" + structure).show();
        } else {
            $("#btn_" + structure).hide();
        }
        if (can_build(structure)) {
            $("#btn_" + structure).removeAttr("disabled");
            $("#btn_" + structure).show();
        }
    }
    if (resource.biomass.value < 5) {
        $("#btn_consume").attr("disabled", true);
    } else {
        $("#btn_consume").removeAttr("disabled");
    }
}

function create_controls() {
    for (structure in building) {
        if (!building.hasOwnProperty(structure)) {
            //The current property is not a direct property
            continue;
        }
        $("#control").append("<button id='btn_" + structure + "' style='display:none'>" + building[structure].name + " (" + building[structure].count + ")</button>");
        $("#btn_" + structure).on("click", {
            structure: structure
        }, build);
    }
    for (minion in minions) {
        if (!minions.hasOwnProperty(minion)) {
            //The current property is not a direct property
            continue;
        }
        $("#minion").append("" + minions[minion].name + " " + minions[minion].current + "\n");
    }
}

function generate_basic_buttons() {
    $("#control").append("<button id='btn_stone'>Rummage for Stone</button>");
    $("#control").append("<button id='btn_biomass'>Scrape up Detritus</button>");
    $("#control").append("<button id='btn_consume' title='Devour Biomass to unlock your potential'>CONSUME</button>");
    //add listeners to buttons
    $("#btn_stone").on("click", collect_stone);
    $("#btn_biomass").on("click", collect_biomass);
    $("#btn_consume").on("click", consume);
}

function switch_panel(panel) {
    if (panel == 'tab_control'){
        $("#minion").hide();
        $("#tech").hide();
        $("#control").show();
    } else if (panel == 'tab_tech'){
        $("#control").hide();
        $("#minion").hide();
        $("#tech").show();
    } else if (panel == 'tab_minion'){
        $("#control").hide();
        $("#tech").hide();
        $("#minion").show();
    }
}

function initialise_gui() {
    var control_divs = '

';
    control_divs += '

';
    control_divs += '

';
    var pstyle = 'border: 1px solid #dfdfdf; padding: 5px;';
    $('#mainwindow').w2layout({
        name: 'mainwindow',
        panels: [
            { type: 'top', size: 30, resizable: false, style: pstyle, content: 'Steam Lizards v0.08' },
            { type: 'left', size: 200, resizable: false, style: pstyle, content: '

' },
            { type: 'main', style: pstyle + 'border-top: 0px;', content: control_divs,
                tabs: {
                    active: 'tab_control',
                    tabs: [
                        { id: 'tab_control', caption: 'Control' },
                        { id: 'tab_tech', caption: 'Technology' },
                        { id: 'tab_minion', caption: 'Minions' },
                    ],
                    onClick: function (event) {
                        switch_panel(event.target);
                    }
                }
            },
            { type: 'right', size: 200, resizable: false, style: pstyle, content: 'Captains "Log":

'}
        ]
    });
    w2ui.mainwindow.panels[2].tabs.hide('tab_tech');
    w2ui.mainwindow.panels[2].tabs.hide('tab_minion');
    generate_basic_buttons();
}

function update_gui() {
    display_resources();
    update_buttons();
    manage_technology();
    fill_housing();
}<|endoftext|>


<commit_before>var _id = 0,
    _toString = Object.prototype.toString,
    _isTruthy = function(arg) { return !!arg; };

var _ = {
    noop: function() {},

    now: Date.now || function() { return new Date().getTime(); },

    uniqueId: function() {
        return _id++;
    },

    exists: function(obj) {
        return obj !== null && obj !== undefined;
    },

    parseInt: function(num) {
        return parseInt(num, 10);
    },

    coerceToNum: function(val) {
        return _.isNumber(val) ? val || 0 : // Its a number! || 0 to avoid NaN (as NaN's a number)
                _.isString(val) ? (_.parseInt(val) || 0) : // Avoid NaN again
                0; // Default to zero
    },

    toPx: function(num) {
        return num + 'px';
    },

    isElement: function(obj) {
        return !!(obj && obj.nodeType === 1);
    },

    isArray: Array.isArray || function(obj) {
        return _toString.call(obj) === '[object Array]';
    },

    // NodeList check. For our purposes, a node list
    // and an HTMLCollection are the same
    isNodeList: function(obj) {
        return obj instanceof NodeList || obj instanceof HTMLCollection;
    },

    // Window check
    isWindow: function(obj) {
        return obj && obj === obj.window;
    },

    // Flatten that also checks if value is a NodeList
    flatten: function(arr) {
        var result = [];

        var idx = 0, length = arr.length,
            value;
        for (; idx < length; idx++) {
            value = arr[idx];

            if (_.isArray(value) || _.isNodeList(value)) {
                result = result.concat(_.flatten(value));
            } else {
                result.push(value);
            }
        }

        return result;
    },

    // Concat flat for a single array of arrays
    concatFlat: (function(concat) {

        return function(nestedArrays) {
            return concat.apply([], nestedArrays);
        };

    }([].concat)),

    // No-context every; strip each()
    every: function(arr, iterator) {
        if (!_.exists(arr)) { return true; }

        var idx = 0, length = arr.length;
        for (; idx < length; idx++) {
            if (!iterator(value, idx)) { return false; }
        }

        return true;
    },

    // Faster extend; strip each()
    extend: function() {
        var args = arguments,
            obj = args[0],
            idx = 1, length = args.length;

        if (!obj) { return obj; }

        for (; idx < length; idx++) {
            var source = args[idx];
            if (source) {
                for (var prop in source) {
                    obj[prop] = source[prop];
                }
            }
        }

        return obj;
    },

    // Standard map
    map: function(arr, iterator) {
        var results = [];
        if (!arr) { return results; }

        var idx = 0, length = arr.length;
        for (; idx < length; idx++) {
            results.push(iterator(arr[idx], idx));
        }

        return results;
    },

    // Array-preserving map
    // http://jsperf.com/push-map-vs-index-replacement-map
    fastmap: function(arr, iterator) {
        if (!arr) { return []; }

        var idx = 0, length = arr.length;
        for (; idx < length; idx++) {
            arr[idx] = iterator(arr[idx], idx);
        }

        return arr;
    },

    filter: function(arr, iterator) {
        var results = [];
        if (!arr || !arr.length) { return results; }
        iterator = iterator || _isTruthy;

        var idx = 0, length = arr.length;
        for (; idx < length; idx++) {
            if (iterator(arr[idx], idx)) {
                results.push(arr[idx]);
            }
        }

        return results;
    },

    any: function(arr, iterator) {
        var result = false;
        if (!arr || !arr.length) { return result; }

        var idx = 0, length = arr.length;
        for (; idx < length; idx++) {
            if (result || (result = iterator(arr[idx], idx))) { break; }
        }

        return !!result;
    },

    typecast: function(val) {
        var r;
        if (val === null || val === 'null') {
            r = null;
        } else if (val === 'true') {
            r = true;
        } else if (val === 'false') {
            r = false;
        } else if (val === undefined || val === 'undefined') {
            r = undefined;
        } else if (val === '' || isNaN(val)) {
            // isNaN('') returns false
            r = val;
        } else {
            // parseFloat(null || '') returns NaN
            r = parseFloat(val);
        }
        return r;
    }
};

// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
var types = ['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'],
    idx = types.length,
    generateCheck = function(name) {
        return function(obj) {
            return _toString.call(obj) === '[object ' + name + ']';
        };
    },
    name;
while (idx--) {
    name = types[idx];
    _['is' + name] = generateCheck(name);
}

// Optimize `isFunction` if appropriate.
if (typeof (/./) !== 'function') {
    _.isFunction = function(obj) {
        return typeof obj === 'function';
    };
}

// Optimize `isString` if appropriate.
if (typeof ('') === 'string') {
    _.isString = function(obj) {
        return typeof obj === 'string';
    };
}

module.exports = _;
<commit_msg>Added _.toArray()<commit_after>var _id = 0,
    _toString = Object.prototype.toString,
    _isTruthy = function(arg) { return !!arg; };

var _ = {
    noop: function() {},

    now: Date.now || function() { return new Date().getTime(); },

    uniqueId: function() {
        return _id++;
    },

    exists: function(obj) {
        return obj !== null && obj !== undefined;
    },

    parseInt: function(num) {
        return parseInt(num, 10);
    },

    coerceToNum: function(val) {
        return _.isNumber(val) ? val || 0 : // Its a number! || 0 to avoid NaN (as NaN's a number)
                _.isString(val) ? (_.parseInt(val) || 0) : // Avoid NaN again
                0; // Default to zero
    },

    toPx: function(num) {
        return num + 'px';
    },

    isElement: function(obj) {
        return !!(obj && obj.nodeType === 1);
    },

    isArray: Array.isArray || function(obj) {
        return _toString.call(obj) === '[object Array]';
    },

    // NodeList check. For our purposes, a node list
    // and an HTMLCollection are the same
    isNodeList: function(obj) {
        return obj instanceof NodeList || obj instanceof HTMLCollection;
    },

    // Window check
    isWindow: function(obj) {
        return obj && obj === obj.window;
    },

    // Flatten that also checks if value is a NodeList
    flatten: function(arr) {
        var result = [];

        var idx = 0, length = arr.length,
            value;
        for (; idx < length; idx++) {
            value = arr[idx];

            if (_.isArray(value) || _.isNodeList(value)) {
                result = result.concat(_.flatten(value));
            } else {
                result.push(value);
            }
        }

        return result;
    },

    // Concat flat for a single array of arrays
    concatFlat: (function(concat) {

        return function(nestedArrays) {
            return concat.apply([], nestedArrays);
        };

    }([].concat)),

    // No-context every; strip each()
    every: function(arr, iterator) {
        if (!_.exists(arr)) { return true; }

        var idx = 0, length = arr.length;
        for (; idx < length; idx++) {
            if (!iterator(value, idx)) { return false; }
        }

        return true;
    },

    // Faster extend; strip each()
    extend: function() {
        var args = arguments,
            obj = args[0],
            idx = 1, length = args.length;

        if (!obj) { return obj; }

        for (; idx < length; idx++) {
            var source = args[idx];
            if (source) {
                for (var prop in source) {
                    obj[prop] = source[prop];
                }
            }
        }

        return obj;
    },

    // Standard map
    map: function(arr, iterator) {
        var results = [];
        if (!arr) { return results; }

        var idx = 0, length = arr.length;
        for (; idx < length; idx++) {
            results.push(iterator(arr[idx], idx));
        }

        return results;
    },

    // Array-preserving map
    // http://jsperf.com/push-map-vs-index-replacement-map
    fastmap: function(arr, iterator) {
        if (!arr) { return []; }

        var idx = 0, length = arr.length;
        for (; idx < length; idx++) {
            arr[idx] = iterator(arr[idx], idx);
        }

        return arr;
    },

    filter: function(arr, iterator) {
        var results = [];
        if (!arr || !arr.length) { return results; }
        iterator = iterator || _isTruthy;

        var idx = 0, length = arr.length;
        for (; idx < length; idx++) {
            if (iterator(arr[idx], idx)) {
                results.push(arr[idx]);
            }
        }

        return results;
    },

    any: function(arr, iterator) {
        var result = false;
        if (!arr || !arr.length) { return result; }

        var idx = 0, length = arr.length;
        for (; idx < length; idx++) {
            if (result || (result = iterator(arr[idx], idx))) { break; }
        }

        return !!result;
    },

    typecast: function(val) {
        var r;
        if (val === null || val === 'null') {
            r = null;
        } else if (val === 'true') {
            r = true;
        } else if (val === 'false') {
            r = false;
        } else if (val === undefined || val === 'undefined') {
            r = undefined;
        } else if (val === '' || isNaN(val)) {
            // isNaN('') returns false
            r = val;
        } else {
            // parseFloat(null || '') returns NaN
            r = parseFloat(val);
        }
        return r;
    },

    toArray: function(obj) {
        if (!obj) {
            return [];
        }
        if (_.isArray(obj)) {
            return Array.prototype.slice.call(obj);
        }

        var arr,
            len = +obj.length,
            idx = 0;

        if (obj.length === +obj.length) {
            arr = new Array(obj.length);
            for (; idx < len; idx++) {
                arr[idx] = obj[idx];
            }
            return arr;
        }

        for (var key in obj) {
            arr.push(obj[key]);
        }
        return arr;
    }
};

// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
var types = ['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'],
    idx = types.length,
    generateCheck = function(name) {
        return function(obj) {
            return _toString.call(obj) === '[object ' + name + ']';
        };
    },
    name;
while (idx--) {
    name = types[idx];
    _['is' + name] = generateCheck(name);
}

// Optimize `isFunction` if appropriate.
if (typeof (/./) !== 'function') {
    _.isFunction = function(obj) {
        return typeof obj === 'function';
    };
}

// Optimize `isString` if appropriate.
if (typeof ('') === 'string') {
    _.isString = function(obj) {
        return typeof obj === 'string';
    };
}

module.exports = _;
<|endoftext|>


<commit_before>define([
    'common/enum/listItemType',
    'common/model/utility',
    'foreground/collection/contextMenuItems',
    'foreground/view/deleteButtonView',
    'foreground/view/multiSelectListItemView',
    'foreground/view/saveToPlaylistButtonView',
    'foreground/view/playInStreamButtonView',
    'text!template/listItem.html'
], function (ListItemType, Utility, ContextMenuItems, DeleteButtonView, MultiSelectListItemView, SaveToPlaylistButtonView, PlayInStreamButtonView, ListItemTemplate) {
    'use strict';

    var Playlists = chrome.extension.getBackgroundPage().Playlists;
    var StreamItems = chrome.extension.getBackgroundPage().StreamItems;
    var Player = chrome.extension.getBackgroundPage().playedRecently;
    var User = chrome.extension.getBackgroundPage().User;
    var PlayPauseButton = chrome.extension.getBackgroundPage().PlayPauseButton;

    var StreamItemView = MultiSelectListItemView.extend({

        className: MultiSelectListItemView.prototype.className + ' stream-item',

        template: _.template(ListItemTemplate),

        attributes: function () {
            return {
                'data-id': this.model.get('id'),
                'data-type': ListItemType.StreamItem
            };
        },

        events: _.extend({}, MultiSelectListItemView.prototype.events, {
            'dblclick': 'activateOrToggleState'
        }),

        modelEvents: _.extend({}, MultiSelectListItemView.prototype.modelEvents, {
            'change:active': 'setActiveClass'
        }),

        buttonViews: [PlayInStreamButtonView, SaveToPlaylistButtonView, DeleteButtonView],

        onShow: function () {
            //  If the stream item is active -- ensure it is instantly visible.
            if (this.model.get('active')) {
                //  Pass 0 into scrollIntoView to have no animation/show instantly.
                this.$el.scrollIntoView(0);
            }
        },

        onRender: function () {
            this.setActiveClass();

            MultiSelectListItemView.prototype.onRender.call(this, arguments);
        },

        activateOrToggleState: function () {
            if (!this.model.get('active')) {
                this.model.set('active', true);
            } else {
                PlayPauseButton.tryTogglePlayerState();
            }
        },

        //  Force the view to reflect the model's active class. It's important to do this here, and not through render always, because
        //  render will cause the lazy-loaded image to be reset.
        setActiveClass: function () {
            var active = this.model.get('active');
            this.$el.toggleClass('active', active);

            if (active) {
                this.$el.scrollIntoView();
            }
        },

        showContextMenu: function (event) {

            //  Whenever a context menu is shown -- set preventDefault to true to let foreground know to not reset the context menu.
            event.preventDefault();
            var self = this;

            var userSignedIn = User.get('signedIn');

            var activePlaylist = Playlists.getActivePlaylist();
            var areadyExists = false;

            if (userSignedIn) {
                areadyExists = activePlaylist.get('items').hasSong(self.model.get('song'));
            }

            var saveTitle = '';

            if (userSignedIn && areadyExists) {
                saveTitle = chrome.i18n.getMessage('duplicatesNotAllowed');
            } else if (!userSignedIn) {
                saveTitle = chrome.i18n.getMessage('cantSaveNotSignedIn');
            }

            ContextMenuItems.reset([{
                    text: chrome.i18n.getMessage('save'),
                    title: saveTitle,
                    disabled: !userSignedIn || areadyExists,
                    onClick: function () {
                        activePlaylist.addSongs(self.model.get('song'));
                    }
                }, {
                    text: chrome.i18n.getMessage('copyUrl'),
                    onClick: function () {

                        chrome.extension.sendMessage({
                            method: 'copy',
                            text: self.model.get('song').get('url')
                        });

                    }
                }, {
                    text: chrome.i18n.getMessage('copyTitleAndUrl'),
                    onClick: function() {

                        chrome.extension.sendMessage({
                            method: 'copy',
                            text: '"' + self.model.get('title') + '" - ' + self.model.get('song').get('url')
                        });

                    }
                }, {
                    text: chrome.i18n.getMessage('delete'),
                    onClick: function () {
                        self.model.destroy();
                    }
                }, {
                    text: chrome.i18n.getMessage('banUntilClear'),
                    disabled: StreamItems.getRelatedSongs().length < 5,
                    onClick: function () {
                        StreamItems.ban(self.model);
                        self.model.destroy();
                    }
                }, {
                    text: chrome.i18n.getMessage('watchOnYouTube'),
                    onClick: function () {

                        var url = self.model.get('song').get('url');
                        if (Player.get('loadedSongId') === self.model.get('song').get('id')) {
                            url += '?t=' + Player.get('currentTime') + 's';
                        }

                        chrome.tabs.create({
                            url:  url
                        });

                        Player.pause();
                      }
                  }]
            );

        }
    });

    return StreamItemView;
});
<commit_msg>bug fix<commit_after>define([
    'common/enum/listItemType',
    'common/model/utility',
    'foreground/collection/contextMenuItems',
    'foreground/view/deleteButtonView',
    'foreground/view/multiSelectListItemView',
    'foreground/view/saveToPlaylistButtonView',
    'foreground/view/playInStreamButtonView',
    'text!template/listItem.html'
], function (ListItemType, Utility, ContextMenuItems, DeleteButtonView, MultiSelectListItemView, SaveToPlaylistButtonView, PlayInStreamButtonView, ListItemTemplate) {
    'use strict';

    var Playlists = chrome.extension.getBackgroundPage().Playlists;
    var StreamItems = chrome.extension.getBackgroundPage().StreamItems;
    var Player = chrome.extension.getBackgroundPage().YouTubePlayer;
    var User = chrome.extension.getBackgroundPage().User;
    var PlayPauseButton = chrome.extension.getBackgroundPage().PlayPauseButton;

    var StreamItemView = MultiSelectListItemView.extend({

        className: MultiSelectListItemView.prototype.className + ' stream-item',

        template: _.template(ListItemTemplate),

        attributes: function () {
            return {
                'data-id': this.model.get('id'),
                'data-type': ListItemType.StreamItem
            };
        },

        events: _.extend({}, MultiSelectListItemView.prototype.events, {
            'dblclick': 'activateOrToggleState'
        }),

        modelEvents: _.extend({}, MultiSelectListItemView.prototype.modelEvents, {
            'change:active': 'setActiveClass'
        }),

        buttonViews: [PlayInStreamButtonView, SaveToPlaylistButtonView, DeleteButtonView],

        onShow: function () {
            //  If the stream item is active -- ensure it is instantly visible.
            if (this.model.get('active')) {
                //  Pass 0 into scrollIntoView to have no animation/show instantly.
                this.$el.scrollIntoView(0);
            }
        },

        onRender: function () {
            this.setActiveClass();

            MultiSelectListItemView.prototype.onRender.call(this, arguments);
        },

        activateOrToggleState: function () {
            if (!this.model.get('active')) {
                this.model.set('active', true);
            } else {
                PlayPauseButton.tryTogglePlayerState();
            }
        },

        //  Force the view to reflect the model's active class. It's important to do this here, and not through render always, because
        //  render will cause the lazy-loaded image to be reset.
        setActiveClass: function () {
            var active = this.model.get('active');
            this.$el.toggleClass('active', active);

            if (active) {
                this.$el.scrollIntoView();
            }
        },

        showContextMenu: function (event) {

            //  Whenever a context menu is shown -- set preventDefault to true to let foreground know to not reset the context menu.
            event.preventDefault();
            var self = this;

            var userSignedIn = User.get('signedIn');

            var activePlaylist = Playlists.getActivePlaylist();
            var areadyExists = false;

            if (userSignedIn) {
                areadyExists = activePlaylist.get('items').hasSong(self.model.get('song'));
            }

            var saveTitle = '';

            if (userSignedIn && areadyExists) {
                saveTitle = chrome.i18n.getMessage('duplicatesNotAllowed');
            } else if (!userSignedIn) {
                saveTitle = chrome.i18n.getMessage('cantSaveNotSignedIn');
            }

            ContextMenuItems.reset([{
                    text: chrome.i18n.getMessage('save'),
                    title: saveTitle,
                    disabled: !userSignedIn || areadyExists,
                    onClick: function () {
                        activePlaylist.addSongs(self.model.get('song'));
                    }
                }, {
                    text: chrome.i18n.getMessage('copyUrl'),
                    onClick: function () {

                        chrome.extension.sendMessage({
                            method: 'copy',
                            text: self.model.get('song').get('url')
                        });

                    }
                }, {
                    text: chrome.i18n.getMessage('copyTitleAndUrl'),
                    onClick: function() {

                        chrome.extension.sendMessage({
                            method: 'copy',
                            text: '"' + self.model.get('title') + '" - ' + self.model.get('song').get('url')
                        });

                    }
                }, {
                    text: chrome.i18n.getMessage('delete'),
                    onClick: function () {
                        self.model.destroy();
                    }
                }, {
                    text: chrome.i18n.getMessage('banUntilClear'),
                    disabled: StreamItems.getRelatedSongs().length < 5,
                    onClick: function () {
                        StreamItems.ban(self.model);
                        self.model.destroy();
                    }
                }, {
                    text: chrome.i18n.getMessage('watchOnYouTube'),
                    onClick: function () {

                        var url = self.model.get('song').get('url');
                        if (Player.get('loadedSongId') === self.model.get('song').get('id')) {
                            url += '?t=' + Player.get('currentTime') + 's';
                        }

                        chrome.tabs.create({
                            url:  url
                        });

                        Player.pause();
                      }
                  }]
            );

        }
    });

    return StreamItemView;
});
<|endoftext|>


<commit_before>function run($rootScope, SyncService, $transitions, $location, $trace, $uiRouter) {
  'ngInject';

  SyncService.init();

  if ($featureFlags.debugRouter) {
    $trace.enable('TRANSITION');
    $uiRouter.plugin(require('@uirouter/visualizer').Visualizer);
  }

  // Variables for templates that webpack does not automatically correct.
  $rootScope.$DIM_VERSION = $DIM_VERSION;
  $rootScope.$DIM_FLAVOR = $DIM_FLAVOR;
  $rootScope.$DIM_CHANGELOG = $DIM_CHANGELOG;
  $rootScope.$DIM_BUILD_DATE = new Date($DIM_BUILD_DATE).toLocaleString();

  console.log(`DIM v${$DIM_VERSION} (${$DIM_FLAVOR}) - Please report any errors to https://www.reddit.com/r/destinyitemmanager`);
}

export default run;
<commit_msg>Change reporting url in console message<commit_after>function run($rootScope, SyncService, $transitions, $location, $trace, $uiRouter) {
  'ngInject';

  SyncService.init();

  if ($featureFlags.debugRouter) {
    $trace.enable('TRANSITION');
    $uiRouter.plugin(require('@uirouter/visualizer').Visualizer);
  }

  // Variables for templates that webpack does not automatically correct.
  $rootScope.$DIM_VERSION = $DIM_VERSION;
  $rootScope.$DIM_FLAVOR = $DIM_FLAVOR;
  $rootScope.$DIM_CHANGELOG = $DIM_CHANGELOG;
  $rootScope.$DIM_BUILD_DATE = new Date($DIM_BUILD_DATE).toLocaleString();

  console.log(`DIM v${$DIM_VERSION} (${$DIM_FLAVOR}) - Please report any errors to https://www.github.com/DestinyItemManager/DIM/issues`);
}

export default run;
<|endoftext|>