<commit_before>/**
 *
 * Publications
 *
 */

import React, { PropTypes } from 'react';
// import styled from 'styled-components';
import { LinearProgress } from 'material-ui/Progress';
import { MdAddCircleOutline, MdRemoveCircleOutline } from 'react-icons/lib/md';
import ReactGA from 'react-ga';
import Script from 'react-load-script';

import { withStyles } from 'material-ui/styles';

import axios from 'axios';
import { graphQLRoot } from 'utils/constants';

import PublicationSystems from './publicationSystems';
// import PublicationReactions from './publicationReactions';

const styles = (theme) => ({
  publicationEntry: {
    textAlign: 'left',
    [theme.breakpoints.down('sm')]: {
      fontSize: '14px',
    },
  },
  publicationYear: {
    textAlign: 'left',
    [theme.breakpoints.down('sm')]: {
      textAlign: 'center',
    },
  },
});

const restoreSC = (str) => {
  let res = str;
  if (str === null || typeof str === 'undefined') {
    return '';
  }
  if (typeof str === 'object') {
    res = str.join(' ');
  }
  return res
  .replace('{\\o}', 'ø')
  .replace('\\o', 'ø')
  .replace('{"A}', 'Ä')
  .replace('{"U}', 'Ü')
  .replace('{"O}', 'Ö')
  .replace('{"a}', 'ä')
  .replace('{"u}', 'ü')
  .replace('{"o}', 'ö')
  .replace('{\\ss}', 'ß')
  .replace('--', '–')

  .replace('{', '')
  .replace('}', '');
};

const prettyPrintReference = (reference) => {
  if (reference.indexOf('{') > -1) {
    const ref = JSON.parse(reference);
    // TODO Integrate with crossref.org api
    // if (false && typeof ref.doi === 'undefined' || ref.doi === '') {
    return (
      {(ref.title !== '' && ref.title !== null && typeof ref.title !== 'undefined') ? {`"${restoreSC(ref.title)}"`}.  : null }
      {(typeof ref.authors !== 'undefined' && ref.authors !== '' && ref.authors !== null) ? {restoreSC(typeof ref.authors === 'string' ? ref.authors : ref.authors.join('; '))}.  : null }
      {(ref.journal !== '' && typeof ref.journal !== 'undefined' && ref.journal !== null) ? {ref.journal},  : null }
      {(ref.volume !== '' && typeof ref.volume !== 'undefined' && ref.volume !== null) ? {ref.volume}  : null}
      {(ref.year !== '' && typeof ref.year !== 'undefined' && ref.year !== null) ? ({ref.year}):  : null}
      {(ref.pages !== '' && typeof ref.pages !== 'undefined' && ref.pages !== null) ? {ref.pages}.  : null}
    );
  }
  return null;
};

class Publications extends React.Component { // eslint-disable-line react/prefer-stateless-function
  constructor(props) {
    super(props);
    this.state = {
      years: [],
      references: {},
      dois: {},
      titles: {},
      loading: false,
      openedPublication: null,
      systems: [],
      reactionEnergies: [],
    };
    this.clickPublication = this.clickPublication.bind(this);
  }
  componentDidMount() {
    const yearQuery = '{catapp(publication_Year: "~", distinct: true) { edges { node { PublicationYear } } }}';
    axios.post(graphQLRoot, {
      query: yearQuery,
    })
      .then((response) => {
        let years = response.data.data.catapp.edges.map((n) => (n.node.PublicationYear));
        years = [...new Set(years)].sort().reverse().filter((x) => x !== null);
        this.setState({
          years,
        });
        years.map((year) => {
          const query = `{catapp(year: ${year}, publication_Title:"~", distinct: true) { edges { node { year publication doi dftCode dftFunctional PublicationTitle } } }}`;
          return axios.post(graphQLRoot, {
            query,
          })
            .then((yearResponse) => {
              let references = yearResponse.data.data.catapp.edges
                .filter(({ node }) => node.PublicationTitle !== '')
                .map((n) => (n.node.publication));
              references = [...new Set(references)];
              let dois = yearResponse.data.data.catapp.edges.map((n) => (n.node.doi));
              dois = [...new Set(dois)];

              let titles = yearResponse.data.data.catapp.edges.map((n) => (n.node.PublicationTitle));
              titles = [...new Set(titles)];

              const allReferences = this.state.references;
              const allDois = this.state.dois;
              const allTitles = this.state.titles;

              allReferences[year] = references;
              allDois[year] = dois;
              allTitles[year] = titles;

              this.setState({
                references: allReferences,
                dois: allDois,
                titles: allTitles,
              });
            })
            .catch(() => {
            })
          ;
        });
      });
  }
  clickPublication(event, target, key) {
    const splitKey = key.split('_');
    const year = parseInt(splitKey[1], 10);
    const count = parseInt(splitKey[2], 10);
    const title = JSON.parse(this.state.references[year][count]).title;
    /* reference = reference.split('"').join('\\"'); */
    this.setState({
      loading: true,
    });
    if (this.state.openedPublication === key) {
      this.setState({
        openedPublication: null,
      });
    } else {
      this.setState({
        openedPublication: key,
      });
    }
    this.setState({
      systems: [],
      reactionEnergies: [],
    });
    let query = `query{systems(last:500, keyValuePairs: "~publication_Title\\": \\"${title}") { edges { node { natoms Formula Facet uniqueId energy DftCode DftFunctional PublicationTitle PublicationAuthors PublicationYear PublicationDoi Cifdata } } }}`;
    axios.post(graphQLRoot, { query })
      .then((response) => {
        if (response.data.data.systems.edges.length > 0) {
          this.setState({
            systems: response.data.data.systems.edges,
            loading: false,
          });
        }
        const searchTitle = this.state.titles[year][count];
        query = `{catapp ( last: 500, publication_Title: "${searchTitle}") { edges { node { id dftCode dftFunctional reactants products aseIds facet chemicalComposition reactionEnergy activationEnergy surfaceComposition } } }}`;
        axios.post(graphQLRoot, { query })
            .then((response1) => {
              this.setState({
                reactionEnergies: response1.data.data.catapp.edges,
                loading: false,
              });
            });
      })
      .catch(() => {
      });
  }

  render() {
    return (


<commit_before>/**
 *
 * Publications
 *
 */

import React from 'react';
// import styled from 'styled-components';

import axios from 'axios';
import { graphQLRoot } from 'utils/constants';

const prettyPrintReference = (reference) => {
  const ref = JSON.parse(reference);
  // TODO Integrate with crossref.org api
  // if (false && typeof ref.doi === 'undefined' || ref.doi === '') {
  return (
    {ref.title !== '' ? <emph>{ref.title}. </emph> : null }
    {typeof ref.authors !== 'undefined' ? {ref.authors.join('; ')}.  : null }
    {ref.journal !== '' ? {ref.journal},  : null }
    {ref.volume !== '' ? {ref.volume},  : null}
    {ref.pages !== '' ? {ref.pages},  : null}
    {ref.year !== '' ? {ref.year}. : null}
  );
};

class Publications extends React.Component { // eslint-disable-line react/prefer-stateless-function
  constructor(props) {
    super(props);
    this.state = {
      years: [],
      references: {},
    };
  }
  componentDidMount() {
    axios.post(graphQLRoot, {
      query: '{numberKeys(key:"publication_year", distinct: true) { edges { node { value } } }}',
    })
      .then((response) => {
        const years = response.data.data.numberKeys.edges.map((n) => (n.node.value));
        this.setState({
          years,
        });
        years.map((year) => (
          axios.post(graphQLRoot, {
            query: `{catapp(year: ${year}, reference: "~", distinct: true) { edges { node { reference } } }}`,
          })
          .then((yearResponse) => {
            const references = yearResponse.data.data.catapp.edges.map((n) => (n.node.reference));
            const allReferences = this.state.references;
            allReferences[year] = references;
            this.setState({
              references: allReferences,
            });
          })
        ));
      });
  }
  render() {
    return (

        {this.state.years.map((year, i) => (
          <div key={`div_year_${i}`}>
            <h2 key={`pyear_${year}`}>{year}

            {(this.state.references[year] || []).map((reference, j) => (
              <div key={`pdiv_${i}_${j}`}>
                <li key={`pli_${i}_${j}`}>{prettyPrintReference(reference)}

            ))}

        ))
        }

    );
  }
}

Publications.propTypes = {

};

export default Publications;
<commit_msg>Added new handlers in preparation for showing publication centered data<commit_after>/**
 *
 * Publications
 *
 */

import React from 'react';
// import styled from 'styled-components';
import { LinearProgress } from 'material-ui/Progress';
import IconButton from 'material-ui/IconButton';
import { MdAddCircleOutline } from 'react-icons/lib/md';

import axios from 'axios';
import { graphQLRoot } from 'utils/constants';

const prettyPrintReference = (reference) => {
  const ref = JSON.parse(reference);
  // TODO Integrate with crossref.org api
  // if (false && typeof ref.doi === 'undefined' || ref.doi === '') {
  return (
    {ref.title !== '' ? <emph>{ref.title}. </emph> : null }
    {typeof ref.authors !== 'undefined' ? {ref.authors.join('; ')}.  : null }
    {ref.journal !== '' ? {ref.journal},  : null }
    {ref.volume !== '' ? {ref.volume},  : null}
    {ref.pages !== '' ? {ref.pages},  : null}
    {ref.year !== '' ? {ref.year}.  : null}
  );
};

class Publications extends React.Component { // eslint-disable-line react/prefer-stateless-function
  constructor(props) {
    super(props);
    this.state = {
      years: [],
      references: {},
      loading: false,
    };
    this.clickPublication = this.clickPublication.bind(this);
  }
  componentDidMount() {
    axios.post(graphQLRoot, {
      query: '{numberKeys(key:"publication_year", distinct: true) { edges { node { value } } }}',
    })
      .then((response) => {
        const years = response.data.data.numberKeys.edges.map((n) => (n.node.value));
        this.setState({
          years,
        });
        years.map((year) => (
          axios.post(graphQLRoot, {
            query: `{catapp(year: ${year}, reference: "~", distinct: true) { edges { node { reference } } }}`,
          })
          .then((yearResponse) => {
            const references = yearResponse.data.data.catapp.edges.map((n) => (n.node.reference));
            const allReferences = this.state.references;
            allReferences[year] = references;
            this.setState({
              references: allReferences,
            });
          })
        ));
      });
  }
  clickPublication(event, target, key) {
    const splitKey = key.split('_');
    const year = parseInt(splitKey[1], 10);
    const count = parseInt(splitKey[2], 10);
    let reference = this.state.references[year][count];
    reference = reference.split('"').join('\\"');
    console.log(reference);
    const query = `query{catapp(reference: "${reference}") { edges { node { aseIds } } }}`;
    axios.post(graphQLRoot, { query })
      .then((response) => {
        console.log(response.data.data.catapp);
      });
  }

  render() {
    return (

        {this.state.references === {} ? <LinearProgress color="primary" /> : null }
        {this.state.years.map((year, i) => (
          <div key={`div_year_${i}`}>
            <h2 key={`pyear_${year}`}>{year}

            {(this.state.references[year] || []).map((reference, j) => (
              <div key={`pli_${i}_${j}`}>
                <IconButton key={`pdiv_${i}_${j}`} onClick={(target, event) => this.clickPublication(event, target, `elem_${year}_${j}`)}> <MdAddCircleOutline /> </IconButton>
                 {prettyPrintReference(reference)}

            ))}

        ))
        }

    );
  }
}

Publications.propTypes = {

};

export default Publications;
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import Relay from 'react-relay/classic';
import { second, seconds } from 'metrick/duration';
import throttle from 'throttleit';

import Panel from '../../shared/Panel';
import SearchField from '../../shared/SearchField';
import ShowMoreFooter from '../../shared/ShowMoreFooter';
import Spinner from '../../shared/Spinner';
import { formatNumber } from '../../../lib/number';

import PusherStore from '../../../stores/PusherStore';

import AgentRow from './row';

const PAGE_SIZE = 100;

class Agents extends React.PureComponent {
  static propTypes = {
    organization: PropTypes.shape({
      allAgents: PropTypes.shape({
        count: PropTypes.number.isRequired
      }),
      agents: PropTypes.shape({
        count: PropTypes.number.isRequired,
        edges: PropTypes.array.isRequired
      })
    }).isRequired,
    relay: PropTypes.object.isRequired
  };

  state = {
    loading: false,
    searchingRemotely: false,
    searchingRemotelyIsSlow: false,
    localSearchQuery: null
  };

  componentDidMount() {
    // We've marked the data requirements for this compoent with `@include(if:
    // $isMounted)` which allows us to defer the actual loading of the data
    // until we're ready. This keeps the page speedy to load and we can load
    // the Agents in after this component has mounted.
    //
    // We use `forceFetch` instead of `setVariables` because we want to re-grab
    // the entire agent list when we come to/from the Agents page whether it's
    // via react-router or the back/forward button in the browser.
    this.props.relay.forceFetch({ isMounted: true }, (readyState) => {
      if (readyState.done) {
        PusherStore.on('organization_stats:change', this.fetchUpdatedData);
        this.startTimeout();
      }
    });
  }

  componentWillUnmount() {
    PusherStore.off('organization_stats:change', this.fetchUpdatedData);
    clearTimeout(this._agentListRefreshTimeout);
  }

  // We refresh the data under 2 circumstances. The refresh happens on what
  // ever happens first.
  //
  // 1. We receive an `organization_stats:change` push event
  // 2. 10 seconds have passed
  startTimeout = () => {
    this._agentListRefreshTimeout = setTimeout(
      this.fetchUpdatedData,
      10::seconds
    );
  };

  // Throttle the `fetchUpdatedData` function so we don't ever reload the
  // entire list more than once every 3 seconds
  fetchUpdatedData = throttle(
    () => {
      this.props.relay.forceFetch(
        true,
        (readyState) => {
          if (readyState.done) {
            // Start a timeout that will cause the data to be refreshed again
            // in a few seconds time
            this.startTimeout();
          }
        }
      );
    },
    3::seconds
  );

  render() {
    // grab (potentially) filtered agent list here, as we need it in several places
    const agents = this.getRelevantAgents();

    return (
      <Panel>
        <Panel.Row>
          <SearchField
            placeholder="Search agents…"
            onChange={this.handleSearch}
            searching={this.state.searchingRemotelyIsSlow}
          />
        </Panel.Row>
        {this.renderSearchInfo(agents)}
        {this.renderAgentList(agents)}
        <ShowMoreFooter
          connection={this.props.organization.agents}
          label="agents"
          loading={this.state.loading}
          searching={!!this.state.localSearchQuery}
          onShowMore={this.handleShowMoreAgents}
        />
      </Panel>
    );
  }

  getRelevantAgents() {
    const { organization: { agents: { edges: agents } = { } } } = this.props;
    const { localSearchQuery } = this.state;

    if (!localSearchQuery) {
      return agents;
    }

    // Parse the search. We only want to do this once, outside of the agent
    // loop, in case they have lots of agents
    const queries = localSearchQuery.map((string) => {
      return {
        string: string.toLowerCase(),
        metaDataKey: string.split('=')[0],
        metaDataValue: string.split('=')[1] // may be undefined
      };
    });

    const anyQueryMatchesName = (agent) => {
      const lowercaseName = agent.name.toLowerCase();

      return queries.some((query) => lowercaseName.indexOf(query.string) !== -1);
    };

    const anyQueryMatchesMetaData = (agent) => {
      return agent.metaData.some((metaDataKeyValue) => {
        const [key, value] = metaDataKeyValue.toLowerCase().split('=');

        return queries.some((query) => {
          // Simple string match
          //
          // 'mo' matches 'moo=true'
          // 'tru' matches 'moo=true'
          // 'bark' does not match 'moo=true'
          if (!query.metaDataValue && key.indexOf(query.metaDataKey) !== -1 || value.indexOf(query.metaDataKey) !== -1) {
            return true;
          }

          // Wildcard matching
          //
          // 'moo=*' matches 'moo=true'
          // 'moo=*' doesn't match 'bark=true'
          if (query.metaDataKey === key && query.metaDataValue === '*') {
            return true;
          }

          // Key=Value matching
          //
          // 'moo=tr' matches 'moo=true'
          // 'moo=true' matches 'moo=true'
          // 'moo=rue' doesn't match 'moo=true'
          // 'moo=false' doesn't match 'moo=true'
          if (query.metaDataKey === key && value.indexOf(query.metaDataValue) === 0) {
            return true;
          }
        });
      });
    };

    return agents.filter(({ node: agent }) => {
      return anyQueryMatchesName(agent) || anyQueryMatchesMetaData(agent);
    });
  }

  renderSearchInfo(relevantAgents) {
    const { organization: { agents }, relay: { variables: { search: remoteSearchQuery } } } = this.props;
    const { localSearchQuery } = this.state;

    if ((localSearchQuery && relevantAgents) || remoteSearchQuery && agents) {
      return (

            {formatNumber(localSearchQuery ? relevantAgents.length : agents.count)} matching agents

      );
    }
  }

  renderAgentList(relevantAgents) {
    const { relay: { variables: { search: remoteSearchQuery } } } = this.props;
    const { localSearchQuery } = this.state;

    const isContextFiltered = !!(remoteSearchQuery || localSearchQuery);

    if (!relevantAgents) {
      return (
        <Panel.Section className="center">
          <Spinner />
        </Panel.Section>
      );
    } else if (relevantAgents.length > 0) {
      return relevantAgents.map(({ node: agent }) => <AgentRow key={agent.id} agent={agent} />);
    } else if (!isContextFiltered) {
      return (
        <Panel.Section className="dark-gray">
          No agents connected
        </Panel.Section>
      );
    }
  }

  get useLocalSearch() {
    return this.props.organization.agents &&
      this.props.organization.allAgents.count <= PAGE_SIZE;
  }

  get useRemoteSearch() {
    return !this.useLocalSearch;
  }

  handleSearch = (query) => {
    if (this.useLocalSearch) {
      return this.handleLocalSearch(query);
    }

    return this.handleRemoteSearch(query);
  };

  handleLocalSearch = (query) => {
    // if there's a remote search active we make doubly sure to
    // reset it this shouldn't happen but stranger things have!
    const shouldResetSearch = !!this.props.relay.variables.search;

    // remove leading and trailing whitespace
    query = query.trim();

    const newState = {
      localSearchQuery: query ? query.split(/\s+/g) : null
    };

    if (shouldResetSearch) {
      newState.searchingRemotely = true;
    }

    this.setState(newState);

    if (shouldResetSearch) {
      this.props.relay.setVariables(
        {
          search: null
        },
        (readyState) => {
          if (readyState.done) {
            this.setState({ searchingRemotely: false });
          }
        }
      );
    }
  };

  handleRemoteSearch = (query) => {
    this.setState({ localSearchQuery: null, searchingRemotely: true });

    if (this.remoteSearchIsSlowTimeout) {
      clearTimeout(this.remoteSearchIsSlowTimeout);
    }

    this.remoteSearchIsSlowTimeout = setTimeout(() => {
      this.setState({ searchingRemotelyIsSlow: true });
    }, 1::second);

    this.props.relay.forceFetch(
      {
        search: query
      },
      (readyState) => {
        if (readyState.done) {
          if (this.remoteSearchIsSlowTimeout) {
            clearTimeout(this.remoteSearchIsSlowTimeout);
          }
          this.setState({
            searchingRemotely: false,
            searchingRemotelyIsSlow: false
          });
        }
      }
    );
  };

  handleShowMoreAgents = () => {
    this.setState({ loading: true });

    this.props.relay.setVariables(
      {
        pageSize: this.props.relay.variables.pageSize + PAGE_SIZE
      },
      (readyState) => {
        if (readyState.done) {
          this.setState({ loading: false });
        }
      }
    );
  };
}

export default Relay.createContainer(Agents, {
  initialVariables: {
    isMounted: false,
    search: null,
    pageSize: PAGE_SIZE
  },

  fragments: {
    organization: () => Relay.QL`
      fragment on Organization {
        allAgents: agents @include(if: $isMounted) {
          count
        }
        agents(first: $pageSize, search: $search) @include(if: $isMounted) {
          ${ShowMoreFooter.getFragment('connection')}
          count
          edges {
            node {
              id
              metaData
              name
              ${AgentRow.getFragment('agent')}
            }
          }
        }
      }
    `
  }
});
<commit_msg>Make agent tag searching case sensitive<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import Relay from 'react-relay/classic';
import { second, seconds } from 'metrick/duration';
import throttle from 'throttleit';

import Panel from '../../shared/Panel';
import SearchField from '../../shared/SearchField';
import ShowMoreFooter from '../../shared/ShowMoreFooter';
import Spinner from '../../shared/Spinner';
import { formatNumber } from '../../../lib/number';

import PusherStore from '../../../stores/PusherStore';

import AgentRow from './row';

const PAGE_SIZE = 100;

class Agents extends React.PureComponent {
  static propTypes = {
    organization: PropTypes.shape({
      allAgents: PropTypes.shape({
        count: PropTypes.number.isRequired
      }),
      agents: PropTypes.shape({
        count: PropTypes.number.isRequired,
        edges: PropTypes.array.isRequired
      })
    }).isRequired,
    relay: PropTypes.object.isRequired
  };

  state = {
    loading: false,
    searchingRemotely: false,
    searchingRemotelyIsSlow: false,
    localSearchQuery: null
  };

  componentDidMount() {
    // We've marked the data requirements for this compoent with `@include(if:
    // $isMounted)` which allows us to defer the actual loading of the data
    // until we're ready. This keeps the page speedy to load and we can load
    // the Agents in after this component has mounted.
    //
    // We use `forceFetch` instead of `setVariables` because we want to re-grab
    // the entire agent list when we come to/from the Agents page whether it's
    // via react-router or the back/forward button in the browser.
    this.props.relay.forceFetch({ isMounted: true }, (readyState) => {
      if (readyState.done) {
        PusherStore.on('organization_stats:change', this.fetchUpdatedData);
        this.startTimeout();
      }
    });
  }

  componentWillUnmount() {
    PusherStore.off('organization_stats:change', this.fetchUpdatedData);
    clearTimeout(this._agentListRefreshTimeout);
  }

  // We refresh the data under 2 circumstances. The refresh happens on what
  // ever happens first.
  //
  // 1. We receive an `organization_stats:change` push event
  // 2. 10 seconds have passed
  startTimeout = () => {
    this._agentListRefreshTimeout = setTimeout(
      this.fetchUpdatedData,
      10::seconds
    );
  };

  // Throttle the `fetchUpdatedData` function so we don't ever reload the
  // entire list more than once every 3 seconds
  fetchUpdatedData = throttle(
    () => {
      this.props.relay.forceFetch(
        true,
        (readyState) => {
          if (readyState.done) {
            // Start a timeout that will cause the data to be refreshed again
            // in a few seconds time
            this.startTimeout();
          }
        }
      );
    },
    3::seconds
  );

  render() {
    // grab (potentially) filtered agent list here, as we need it in several places
    const agents = this.getRelevantAgents();

    return (
      <Panel>
        <Panel.Row>
          <SearchField
            placeholder="Search agents…"
            onChange={this.handleSearch}
            searching={this.state.searchingRemotelyIsSlow}
          />
        </Panel.Row>
        {this.renderSearchInfo(agents)}
        {this.renderAgentList(agents)}
        <ShowMoreFooter
          connection={this.props.organization.agents}
          label="agents"
          loading={this.state.loading}
          searching={!!this.state.localSearchQuery}
          onShowMore={this.handleShowMoreAgents}
        />
      </Panel>
    );
  }

  getRelevantAgents() {
    const { organization: { agents: { edges: agents } = { } } } = this.props;
    const { localSearchQuery } = this.state;

    if (!localSearchQuery) {
      return agents;
    }

    // Parse the search. We only want to do this once, outside of the agent
    // loop, in case they have lots of agents
    const queries = localSearchQuery.map((string) => {
      const [key, value] = string.split('=');

      return {
        string: string.toLowerCase(),
        metaDataKey: key,
        metaDataValue: value // may be undefined
      };
    });

    const anyQueryMatchesName = (agent) => {
      const lowercaseName = agent.name.toLowerCase();

      return queries.some((query) => lowercaseName.indexOf(query.string) !== -1);
    };

    const anyQueryMatchesMetaData = (agent) => {
      return agent.metaData.some((metaDataKeyValue) => {
        const [key, value] = metaDataKeyValue.split('=');

        return queries.some((query) => {
          // Simple string match
          //
          // 'mo' matches 'moo=true'
          // 'tru' matches 'moo=true'
          // 'bark' does not match 'moo=true'
          if (!query.metaDataValue && key.indexOf(query.metaDataKey) !== -1 || value.indexOf(query.metaDataKey) !== -1) {
            return true;
          }

          // Wildcard matching
          //
          // 'moo=*' matches 'moo=true'
          // 'moo=*' doesn't match 'bark=true'
          if (query.metaDataKey === key && query.metaDataValue === '*') {
            return true;
          }

          // Key=Value matching
          //
          // 'moo=tr' matches 'moo=true'
          // 'moo=true' matches 'moo=true'
          // 'moo=rue' doesn't match 'moo=true'
          // 'moo=false' doesn't match 'moo=true'
          if (query.metaDataKey === key && value.indexOf(query.metaDataValue) === 0) {
            return true;
          }
        });
      });
    };

    return agents.filter(({ node: agent }) => {
      return anyQueryMatchesName(agent) || anyQueryMatchesMetaData(agent);
    });
  }

  renderSearchInfo(relevantAgents) {
    const { organization: { agents }, relay: { variables: { search: remoteSearchQuery } } } = this.props;
    const { localSearchQuery } = this.state;

    if ((localSearchQuery && relevantAgents) || remoteSearchQuery && agents) {
      return (

            {formatNumber(localSearchQuery ? relevantAgents.length : agents.count)} matching agents

      );
    }
  }

  renderAgentList(relevantAgents) {
    const { relay: { variables: { search: remoteSearchQuery } } } = this.props;
    const { localSearchQuery } = this.state;

    const isContextFiltered = !!(remoteSearchQuery || localSearchQuery);

    if (!relevantAgents) {
      return (
        <Panel.Section className="center">
          <Spinner />
        </Panel.Section>
      );
    } else if (relevantAgents.length > 0) {
      return relevantAgents.map(({ node: agent }) => <AgentRow key={agent.id} agent={agent} />);
    } else if (!isContextFiltered) {
      return (
        <Panel.Section className="dark-gray">
          No agents connected
        </Panel.Section>
      );
    }
  }

  get useLocalSearch() {
    return this.props.organization.agents &&
      this.props.organization.allAgents.count <= PAGE_SIZE;
  }

  get useRemoteSearch() {
    return !this.useLocalSearch;
  }

  handleSearch = (query) => {
    if (this.useLocalSearch) {
      return this.handleLocalSearch(query);
    }

    return this.handleRemoteSearch(query);
  };

  handleLocalSearch = (query) => {
    // if there's a remote search active we make doubly sure to
    // reset it this shouldn't happen but stranger things have!
    const shouldResetSearch = !!this.props.relay.variables.search;

    // remove leading and trailing whitespace
    query = query.trim();

    const newState = {
      localSearchQuery: query ? query.split(/\s+/g) : null
    };

    if (shouldResetSearch) {
      newState.searchingRemotely = true;
    }

    this.setState(newState);

    if (shouldResetSearch) {
      this.props.relay.setVariables(
        {
          search: null
        },
        (readyState) => {
          if (readyState.done) {
            this.setState({ searchingRemotely: false });
          }
        }
      );
    }
  };

  handleRemoteSearch = (query) => {
    this.setState({ localSearchQuery: null, searchingRemotely: true });

    if (this.remoteSearchIsSlowTimeout) {
      clearTimeout(this.remoteSearchIsSlowTimeout);
    }

    this.remoteSearchIsSlowTimeout = setTimeout(() => {
      this.setState({ searchingRemotelyIsSlow: true });
    }, 1::second);

    this.props.relay.forceFetch(
      {
        search: query
      },
      (readyState) => {
        if (readyState.done) {
          if (this.remoteSearchIsSlowTimeout) {
            clearTimeout(this.remoteSearchIsSlowTimeout);
          }
          this.setState({
            searchingRemotely: false,
            searchingRemotelyIsSlow: false
          });
        }
      }
    );
  };

  handleShowMoreAgents = () => {
    this.setState({ loading: true });

    this.props.relay.setVariables(
      {
        pageSize: this.props.relay.variables.pageSize + PAGE_SIZE
      },
      (readyState) => {
        if (readyState.done) {
          this.setState({ loading: false });
        }
      }
    );
  };
}

export default Relay.createContainer(Agents, {
  initialVariables: {
    isMounted: false,
    search: null,
    pageSize: PAGE_SIZE
  },

  fragments: {
    organization: () => Relay.QL`
      fragment on Organization {
        allAgents: agents @include(if: $isMounted) {
          count
        }
        agents(first: $pageSize, search: $search) @include(if: $isMounted) {
          ${ShowMoreFooter.getFragment('connection')}
          count
          edges {
            node {
              id
              metaData
              name
              ${AgentRow.getFragment('agent')}
            }
          }
        }
      }
    `
  }
});
<|endoftext|>


<commit_before>import './lib/style';
import './main.scss';

import { sine, cosine } from './lib/wave';
import Puppet from './lib/puppet';

const canvas = document.getElementById('js-canvas');
const ctx = canvas.getContext('2d');

let fts, pts, dts;
let w, h, hw, hh;

const puppet = new Puppet({
    // _x: sine(hw - 20, hw + 20, 1000),

    _y(ts) {
        return hh - this.height / 2;
    },

    _z(ts) { return 1; },

    _width(ts) {
        return 40;
    },

    _height(ts) {
        return 100;
    },
});

puppet.addChild(new Puppet({
    _x(ts) { return this.parent.width - 10; },

    _y(ts) { return this.parent.height - 10; },

    _width(ts) {
        return 20;
    },

    _height(ts) {
        return 20;
    },
}));

puppet.addChild(new Puppet({
    _x(ts) { return -10; },

    _y(ts) { return this.parent.height - 10; },

    _z(ts) { return 2; },

    _width(ts) {
        return 20;
    },

    _height(ts) {
        return 20;
    },
}));

function onResize(/*event*/) {
    const {
        innerHeight: height,
        innerWidth: width,
    } = window;

    canvas.height = h = height;
    canvas.width = w = width;
    hh = h / 2;
    hw = w / 2;

    puppet._x = sine(hw - 20, hw + 20, 1000);
}

window.addEventListener('resize', onResize);
onResize();

(function tick(ts = Date.now()) {
    window.requestAnimationFrame(tick);

    fts || (fts = ts);
    pts || (pts = fts);

    ts -= fts;
    dts = ts - pts;

    ctx.clearRect(0, 0, w, h);
    puppet.update(ts);
    puppet
        .flat()
        .forEach(part => part.draw(ctx));

    pts = ts;
})();
<commit_msg>refactor: dink<commit_after>import './lib/style';
import './main.scss';

import { sine, cosine } from './lib/wave';
import Puppet from './lib/puppet';

const canvas = document.getElementById('js-canvas');
const ctx = canvas.getContext('2d');

let fts, pts, dts;
let w, h, hw, hh;

const puppet = new Puppet({
    // _x: sine(hw - 20, hw + 20, 1000),

    _y(ts) {
        return hh - this.height / 2;
    },

    _z(ts) { return 1; },

    _width(ts) {
        return 40;
    },

    _height(ts) {
        return 100;
    },
});

puppet.addChild(new Puppet({
    _x(ts) { return this.parent.width - 10; },

    _y(ts) { return this.parent.height - 10; },

    _width(ts) {
        return 20;
    },

    _height(ts) {
        return 20;
    },
}));

puppet.addChild(new Puppet({
    _x(ts) { return -10; },

    _y(ts) { return -10; },

    _z(ts) { return 2; },

    _width(ts) {
        return 20;
    },

    _height(ts) {
        return 20;
    },
}));

function onResize(/*event*/) {
    const {
        innerHeight: height,
        innerWidth: width,
    } = window;

    canvas.height = h = height;
    canvas.width = w = width;
    hh = h / 2;
    hw = w / 2;

    puppet._x = sine(hw / 2, hw + hw / 2, 5000);
}

window.addEventListener('resize', onResize);
onResize();

(function tick(ts = Date.now()) {
    window.requestAnimationFrame(tick);

    fts || (fts = ts);
    pts || (pts = fts);

    ts -= fts;
    dts = ts - pts;

    ctx.clearRect(0, 0, w, h);
    puppet.update(ts);
    puppet
        .flat()
        .forEach(part => part.draw(ctx));

    pts = ts;
})();
<|endoftext|>


<commit_before>var React = require('react');
var ReactDOM = require('react-dom');

var StoryInput = require('./StoryInput.js');
var GoButton = require('./GoButton.js');

var io = require('socket.io-client');
var socket = io.connect();

module.exports = React.createClass({

  getInitialState: function() {
    return {secondsElapsed: 600};
  },

  componentDidMount: function() {
    this.interval = setInterval(this.tick, 1000);
  },

  componentWillUnmount: function() {
    clearInterval(this.interval);
  },

  startTimer: function() {
  	if (!this.interval) {
      this.interval = setInterval(this.update, this.props.options.delay); // 100 is delay
    }
  },

  tick: function() {
    this.setState({secondsElapsed: this.state.secondsElapsed - 1});
  },

  pauseTimer: function() {
  	 if (this.interval) {
      clearInterval(this.interval);
      this.interval = null;
    }

  },

  endTimer: function() {

  },

  render: function() {
  	return (

      Seconds Elapsed: {this.state.secondsElapsed}

    );
  }
});

<commit_msg>Basic game timer component completed<commit_after>var React = require('react');
var ReactDOM = require('react-dom');

module.exports = React.createClass({

  getInitialState: function() {
    return {secondsElapsed: 600};
  },

  componentDidMount: function() {
    this.interval = setInterval(this.tick, 1000);
  },

  componentWillUnmount: function() {
    clearInterval(this.interval);
  },
  //sets interval to one second again
  startTimer: function() {
  	if (!this.interval) {
      this.interval = setInterval(this.tick, 1000);
    }
  },
  //normal tick of one second
  tick: function() {
    if (this.state.secondsElapsed > 0){
      this.setState({secondsElapsed: this.state.secondsElapsed - 1});
    }
  },
  //sets this interval to nothing, pausing timer
  pauseTimer: function() {
  	 if (this.interval) {
      clearInterval(this.interval);
      this.interval = null;
    }
  },

  render: function() {
  	return (

      Seconds Elapsed: {this.state.secondsElapsed}

    );
  }
});

<|endoftext|>


<commit_before>/*

The MIT License (MIT)

Copyright (c) 2013 Rémi Arnaud - Advanced Micro Devices, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.*/
//
setViewer6Upload=function(upload){
    var header;
    var index;
    var buttonToReplace;
    upload.callOnClick(function(){
        header = upload.header();
        index=0;
    });
    var url = '/rest3d/upload',
        uploadButton = $('<button/>')
            .addClass('btn')
            .prop('disabled', true)
            .on('click', function (){
                var $this = $(this),
                    data = $this.data();
                $this
                    .off('click')
                    .on('click', function () {
                        $this.remove();
                        data.abort();
                    });
                data.submit();
                buttonToReplace=$(this);
                //.always(function () {
                //     $this.remove();
                // });
        }),
        // show the name of the file nicely
        formatName = function(data,file){
            var i = file.name.lastIndexOf('/');
            return file.name.substring(i+1);
        },
        convertButton = $('<button/>')
            .addClass('btn')
            .prop('disabled', true)
            .on('click', function () {
                var $this = $(this),
                    data = $this.data();
                $this
                    .off('click')
                    .prop('disabled',true)
                // user rest to convert dae into glTF
                var callback = function(data) {
                    $this.prop('disabled',true);
                    if(data.result.output){console.debug(data.result.output);}
                    if(data.result.code){console.debug("Exit code: "+data.result.code);}
                    if (data.error){
                        var span = $('
Error code='+data.error.code+' :: '+data.error.message+'
');
                        data.context.append(span);
                    } else {
                        // ennumerate all resulting files
                        var $conve = upload.header(data.file.name);
                        $.each(data.result.files, function (index, file) {
                            var href = $('');
                            upload.filesArea.append(href);
                            var $download = $("<button>Download</button>").on("click",function(){
                                href[0].click();
                            });

                        var url = decodeURIComponent(file.url);
                        var ext = url.match(/\.[^.]+$/);
                        if(ext==".json"){
                            var $dialog = $("<button>Launch your model</button>").on("click",function(){
                                glTF.load(url, viewer.parse_gltf);
                                window.notif(url);
                            });
                            var $preview = $("<button>Peview</button>").on("click",function(){
                                var gitHtml = '

';
                                gitPanel = $('body').append(gitHtml);
                                $("#dialog").dialog({
                                    autoOpen: true,
                                    width: 800,
                                    height: 600,
                                    open: function (ev, ui) {
                                        $('#myIframe').attr('src', '/viewer/easy-viewer.html?file=/rest3d/upload/'+decodeURIComponent(file.name));
                                    }
                                });
                            });
                                upload.convert($conve,formatName(data,file),$dialog,$download,$preview);
                        }
                        else{
                            upload.download($conve,formatName(data,file),$download);//
                        }
                        });
                    }
                }

                rest3d.convert(data,callback);
            });

    upload.object.on('fileuploadadd', function (e, data) {
        upload.object=$(this);
        data.context = header;
        $.each(data.files, function (index, file) {
            // if (!index) {
                var $dialog = $("<button>Launch your model</button>").on("click",function(){
                                glTF.load(url, viewer.parse_gltf);
                                window.notif(url);
                            });
                 var $preview = $("<button>Peview</button>").on("click",function(){
                                var gitHtml = '

';
                                gitPanel = $('body').append(gitHtml);
                                $("#dialog").dialog({
                                    autoOpen: true,
                                    width: 800,
                                    height: 600,
                                    open: function (ev, ui) {
                                        $('#myIframe').attr('src', '/viewer/easy-viewer.html?file=/rest3d/upload/'+decodeURIComponent(file.name));
                                    }
                                });
                            });
                upload.upload(header,file.name,$dialog,$preview,uploadButton.clone(true).data(data));
            // else{this.upload(header,file.name);}
        });
    }).on('fileuploadprocessalways', function (e, data) {
            var indexI = data.index,
            file = data.files[indexI],
             node = $(data.context.children('div')[index+1]);
        if (file.preview) {
            node
                .prepend('
')
                .prepend(file.preview);
        }
        if (file.error) {
          GUI.addTooltip({
                    parent: node.find('button'),
                    content: file.error,
                });//
        }
        if (indexI + 1 === data.files.length) {
            node.find('button')
                .prop('disabled', !!data.files.error);
        }
        index++;
    }).on('fileuploadprogressall', function (e, data) {
        var progress = parseInt(data.loaded / data.total * 100, 10);
        upload.progress.setValue(progress);
    }).on('fileuploaddone', function (e, data) {
        $.each(data.result.files, function (index, file) {
            file.assetName = data.result.files[index].name;
            var $node = convertButton.clone(true).data({file: file, context: data.context})
                .prop('disabled', !/dae$/i.test(file.url));
            buttonToReplace
                .replaceWith($node);
        });
    }).on('fileuploadfail', function (e, data) {
        if (!data.result) {
            $(data.context.children()[0])
                .append('
')
                .append('error communicating with server')
                .find('button').remove();
        } else
        $.each(data.result.files, function (index, file) {
            var error = $('').text(file.error);
            $(data.context.children()[index])
                .append('
')
                .append(error)
                .find('button').remove();
        });
    });
}
<commit_msg>Upload widget modified<commit_after>/*

The MIT License (MIT)

Copyright (c) 2013 Rémi Arnaud - Advanced Micro Devices, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.*/
//
setViewer6Upload=function(upload){
    var header;
    var index;
    var buttonToReplace;
    upload.callOnClick(function(){
        header = upload.header();
        index=0;
    });
    var url = '/rest3d/upload',
        uploadButton = $('<button/>')
            .addClass('btn')
            .prop('disabled', true)
            .on('click', function (){
                var $this = $(this),
                    data = $this.data();
                $this
                    .off('click')
                    .on('click', function () {
                        $this.remove();
                        data.abort();
                    });
                data.submit();
                buttonToReplace=$(this);
                //.always(function () {
                //     $this.remove();
                // });
        }),
        // show the name of the file nicely
        formatName = function(data,file){
            var i = file.name.lastIndexOf('/');
            return file.name.substring(i+1);
        },
        convertButton = $('<button/>')
            .addClass('btn')
            .prop('disabled', true)
            .on('click', function () {
                var $this = $(this),
                    data = $this.data();
                $this
                    .off('click')
                    .prop('disabled',true)
                // user rest to convert dae into glTF
                var callback = function(data) {
                    $this.prop('disabled',true);
                    if(data.result.output){console.debug(data.result.output);}
                    if(data.result.code){console.debug("Exit code: "+data.result.code);}
                    if (data.error){
                        var span = $('
Error code='+data.error.code+' :: '+data.error.message+'
');
                        data.context.append(span);
                    } else {
                        // ennumerate all resulting files
                        var $conve = upload.header(data.file.name);
                        $.each(data.result.files, function (index, file) {
                            var href = $('');
                            upload.filesArea.append(href);
                            var $download = $("<button>Download</button>").on("click",function(){
                                href[0].click();
                            });

                        var url = decodeURIComponent(file.url);
                        var ext = url.match(/\.[^.]+$/);
                        if(ext==".json"){
                            var $dialog = $("<button>Launch your model</button>").on("click",function(){
                                glTF.load(url, viewer.parse_gltf);
                                window.notif(url);
                            });
                            var $preview = $("<button>Peview</button>").on("click",function(){
                                var gitHtml = '

';
                                gitPanel = $('body').append(gitHtml);
                                $("#dialog").dialog({
                                    autoOpen: true,
                                    width: 800,
                                    height: 600,
                                    open: function (ev, ui) {
                                        $('#myIframe').attr('src', '/viewer/easy-viewer.html?file=/rest3d/upload/'+decodeURIComponent(file.name));
                                    }
                                });
                            });
                                upload.convert($conve,formatName(data,file),$dialog,$download,$preview);
                        }
                        else{
                            upload.download($conve,formatName(data,file),$download);//
                        }
                        });
                    }
                }

                rest3d.convert(data,callback);
            });

    upload.object.on('fileuploadadd', function (e, data) {
        upload.object=$(this);
        data.context = header;
        $.each(data.files, function (index, file) {
            // if (!index) {
                var $dialog = $("<button>Launch your model</button>").on("click",function(){
                                glTF.load(url, viewer.parse_gltf);
                                window.notif(url);
                            });
                 var $preview = $("<button>Peview</button>").on("click",function(){
                                var gitHtml = '

';
                                gitPanel = $('body').append(gitHtml);
                                $("#dialog").dialog({
                                    autoOpen: true,
                                    width: 800,
                                    height: 600,
                                    open: function (ev, ui) {
                                        $('#myIframe').attr('src', '/viewer/easy-viewer.html?file=/rest3d/upload/'+decodeURIComponent(file.name));
                                    }
                                });
                            });
                upload.upload(header,file.name,$preview,$dialog,uploadButton.clone(true).data(data));
            // else{this.upload(header,file.name);}
        });
    }).on('fileuploadprocessalways', function (e, data) {
            var indexI = data.index,
            file = data.files[indexI],
             node = $(data.context.children('div')[index+1]);
        if (file.preview) {
            node
                .prepend('
')
                .prepend(file.preview);
        }
        if (file.error) {
          GUI.addTooltip({
                    parent: node.find('button'),
                    content: file.error,
                });//
        }
        if (indexI + 1 === data.files.length) {
            node.find('button')
                .prop('disabled', !!data.files.error);
        }
        index++;
    }).on('fileuploadprogressall', function (e, data) {
        var progress = parseInt(data.loaded / data.total * 100, 10);
        upload.progress.setValue(progress);
    }).on('fileuploaddone', function (e, data) {
        $.each(data.result.files, function (index, file) {
            file.assetName = data.result.files[index].name;
            var $node = convertButton.clone(true).data({file: file, context: data.context})
                .prop('disabled', !/dae$/i.test(file.url));
                .text('abort');
            buttonToReplace
                .replaceWith($node);
        });
    }).on('fileuploadfail', function (e, data) {
        if (!data.result) {
            $(data.context.children()[0])
                .append('
')
                .append('error communicating with server')
                .find('button').remove();
        } else
        $.each(data.result.files, function (index, file) {
            var error = $('').text(file.error);
            $(data.context.children()[index])
                .append('
')
                .append(error)
                .find('button').remove();
        });
    });
}
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.Component.extend({
});
<commit_msg>action for adding yet more optional info<commit_after>import Ember from 'ember';

export default Ember.Component.extend({
  actions: {
    addOptionalInfo: function () {
      var optional = this.get('model.statement.extraOptionalInfo');
      optional.pushObject(Ember.A({}));
    }
  },
});
<|endoftext|>


<commit_before>/*global define, window */
/*jshint indent:4 */

define(["AppParams", "jquery", "underscore", "models/search", "text!templates/search/facets.html"],
    function (AppParams, $, underscore, searchModel, facetsTemplate) {
        "use strict";

        if (! document.getElementById("aside-similar-offers")) {
            //there is no aside-similar-offers navbar
            return;
        }

        //@todo only load this if the screen has the necessary space to show it (it is not hidden)

        var $asideSimilarOffers = $("#aside-similar-offers");

        var formSerialized = "q=*";

        if (AppParams.postUsername !== undefined) {
            formSerialized += "&u=" + encodeURIComponent(AppParams.postUsername);
        }

        var xhr = $.ajax({
            data: formSerialized,
            url: AppParams.webroot + "/search-engine?facets",
            type: "GET",
            cache: true
        });

        var loadFacets = function (facets) {
            var compiledFacets = underscore.template(facetsTemplate);

            var facetsHtml = compiledFacets(
                {
                    termListHtmlElements : searchModel.termListHtmlElements,
                    termListHtmlElementsType : searchModel.termListHtmlElementsType,
                    termListHtmlElementsBool : searchModel.termListHtmlElementsBool,
                    formSerialized : formSerialized,
                    transmissionTranslation : searchModel.transmissionTranslation,
                    tractionTranslation : searchModel.tractionTranslation,
                    facets : facets,
                    searchParamsTotal : 0,
                    currentQueryStringParams : searchModel.parseQueryString(formSerialized)
                }
            );

            $asideSimilarOffers.html(facetsHtml);
        };

        xhr.done(function (response) {
            loadFacets(response.facets);
        });
    }
);<commit_msg>make the price filtering on the facets work when not on the search page<commit_after>/*global define, window */
/*jshint indent:4 */

define(["AppParams", "jquery", "underscore", "models/search", "text!templates/search/facets.html"],
    function (AppParams, $, underscore, searchModel, facetsTemplate) {
        "use strict";

        if (! document.getElementById("aside-similar-offers")) {
            //there is no aside-similar-offers navbar
            return;
        }

        //@todo only load this if the screen has the necessary space to show it (it is not hidden)

        var $asideSimilarOffers = $("#aside-similar-offers");

        var formSerialized = "q=*";

        if (AppParams.postUsername !== undefined) {
            formSerialized += "&u=" + encodeURIComponent(AppParams.postUsername);
        }

        var xhr = $.ajax({
            data: formSerialized,
            url: AppParams.webroot + "/search-engine?facets",
            type: "GET",
            cache: true
        });

        var loadFacets = function (facets) {
            var compiledFacets = underscore.template(facetsTemplate);

            var facetsHtml = compiledFacets(
                {
                    termListHtmlElements : searchModel.termListHtmlElements,
                    termListHtmlElementsType : searchModel.termListHtmlElementsType,
                    termListHtmlElementsBool : searchModel.termListHtmlElementsBool,
                    formSerialized : formSerialized,
                    transmissionTranslation : searchModel.transmissionTranslation,
                    tractionTranslation : searchModel.tractionTranslation,
                    facets : facets,
                    searchParamsTotal : 0,
                    currentQueryStringParams : searchModel.parseQueryString(formSerialized)
                }
            );

            $asideSimilarOffers.html(facetsHtml);

            var $priceInputs = $(".price-inputs", $asideSimilarOffers);
            var $priceMinInput = $(".price-min-input", $asideSimilarOffers);
            var $priceMaxInput = $(".price-max-input", $asideSimilarOffers);

            $priceInputs.on("keyup", function (e) {
                if (e.keyCode === 13) {
                    var priceMin = $priceMinInput.val().replace(/[^0-9]/g, '');
                    var priceMax = $priceMaxInput.val().replace(/[^0-9]/g, '');

                    var linkParamsArray = [];

                    linkParamsArray.push("q=*");

                    if (AppParams.postUsername !== undefined) {
                        linkParamsArray.push("u=" + encodeURIComponent(AppParams.postUsername));
                    }

                    if (priceMin) {
                        linkParamsArray.push("price-min=" + encodeURIComponent(priceMin));
                    }

                    if (priceMax) {
                        linkParamsArray.push("price-max=" + encodeURIComponent(priceMax));
                    }

                    window.location = AppParams.webroot + "/search?" + linkParamsArray.join("&");
                }
            });

            $priceInputs.tooltip();

            searchModel.maskMoney($priceMinInput);
            searchModel.maskMoney($priceMaxInput);
        };

        xhr.done(function (response) {
            loadFacets(response.facets);
        });
    }
);<|endoftext|>


<commit_before>/* global Errors */
/* global QUnit */

// Strip stack of rows with unittests.html.
function cleanStack(stack) {
    if (!stack) return null;
    return stack.map(function (item) {
        return item.replace(/.*localhost.*/, "")
            .replace(/.*azurewebsites.*/, "")
            .replace(/.*\.\.\/Scripts\/.*/, "")
            .replace(/\n+/, "\n")
            .replace(/^.*?\.(.*)@/, "$1@")
            .replace(/^.*\/<\(\)@http/, "Anonymous function()@http")
            .replace(/{anonymous}/, "Anonymous function")
            .replace(/:\d*$/, "");
    }).filter(function (item) {
        return !!item;
    });
}

QUnit.assert.errorsEqual = function (value, expectedValues, message) {
    var found = expectedValues.some(function (expected) {
        if (value === expected) {
            this.pushResult({
                result: true,
                actual: value,
                expected: expected,
                message: message
            });

            return true;
        }
    }, this);

    if (!found) {
        this.pushResult({
            result: false,
            actual: value,
            expected: expectedValues,
            message: message
        });
    }
};

QUnit.test("Errors.parse Tests", function (assert) {

    assert.expect(20); // Count of assert calls in the tests below
    var done = assert.async(10); // Count of asynchronous calls below

    Errors.parse("stringError", "message", function (eventName, stack) {
        assert.equal(eventName, "message : stringError", "Errors.parse 1 error");
        assert.deepEqual(cleanStack(stack), [
            "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
            "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
            "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
            "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
        ], "Errors.parse 1 stack");
        done();
    });

    try {
        document.notAFunction();
    }
    catch (error) {
        Errors.parse(error, "message", function (eventName, stack) {
            assert.errorsEqual(eventName, ["message : Object doesn't support property or method 'notAFunction'",
                "message : document.notAFunction is not a function"], "Try 1 error");
            assert.deepEqual(cleanStack(stack), [
                "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
                "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
                "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
                "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
            ], "Try 1 stack");
            done();
        });
    }

    try {
        document.notAFunction();
    }
    catch (error) {
        Errors.parse(error, null, function (eventName, stack) {
            assert.errorsEqual(eventName, ["Object doesn't support property or method 'notAFunction'",
                "document.notAFunction is not a function"], "Try 2 error");
            assert.deepEqual(cleanStack(stack), [
                "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
                "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
                "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
                "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
            ], "Try 2 stack");
            done();
        });
    }

    try {
        throw 42;
    }
    catch (error) {
        Errors.parse(error, "message", function (eventName, stack) {
            assert.equal(eventName, "message : 42", "Try 3 error");
            assert.deepEqual(cleanStack(stack), [
                "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
                "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
                "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
                "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
            ], "Try 3 stack");
            done();
        });
    }

    try {
        throw { one: 1, two: 2, three: "three" };
    }
    catch (error) {
        Errors.parse(error, null, function (eventName, stack) {
            assert.equal(eventName, "{\n" +
                "  \"one\": 1,\n" +
                "  \"two\": 2,\n" +
                "  \"three\": \"three\"\n" +
                "}",
                "Try 4 error");
            assert.deepEqual(cleanStack(stack), [
                "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
                "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
                "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
                "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
            ], "Try 4 stack");
            done();
        });
    }

    try {
        throw null;
    }
    catch (error) {
        Errors.parse(error, null, function (eventName, stack) {
            assert.equal(eventName, "Unknown exception", "Try 5 error");
            assert.deepEqual(cleanStack(stack), [
                "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
                "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
                "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
                "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
            ], "Try 5 stack");
            done();
        });
    }

    Errors.parse(null, "message", function (eventName, stack) {
        assert.equal(eventName, "message", "Errors.parse 2 error");
        assert.deepEqual(cleanStack(stack), [
            "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
            "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
            "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
            "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
        ], "Errors.parse 2 stack");
        done();
    });

    Errors.parse(null, null, function (eventName, stack) {
        assert.equal(eventName, "Unknown exception", "Errors.parse 3 error");
        assert.deepEqual(cleanStack(stack), [
            "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
            "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
            "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
            "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
        ], "Errors.parse 3 stack");
        done();
    });

    var brokenError = new Error();
    Errors.parse(brokenError, "message", function (eventName, stack) {
        assert.equal(eventName, "message", "brokenError event");
        assert.deepEqual(cleanStack(stack), [
            "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
            "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
            "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
            "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
        ], "brokenError stack");
        done();
    });

    Errors.parse(42, "message", function (eventName, stack) {
        assert.equal(eventName, "message : 42", "Errors.parse 4 error");
        assert.deepEqual(cleanStack(stack), [
            "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
            "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
            "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
            "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
        ], "Errors.parse 4 stack");
        done();
    });
});

QUnit.test("getError* Tests", function (assert) {
    try {
        document.notAFunction();
    }
    catch (error) {
        assert.errorsEqual(Errors.getErrorMessage(error), ["Object doesn't support property or method 'notAFunction'",
            "document.notAFunction is not a function"]);
        assert.ok(Errors.getErrorStack(error).length > 0);
    }

    try {
        throw "string";
    }
    catch (error) {
        assert.equal(Errors.getErrorMessage(error), "string");
        assert.equal(Errors.getErrorStack(error), "string thrown as error");
    }

    try {
        throw 42;
    }
    catch (error) {
        assert.equal(Errors.getErrorMessage(error), "42");
        assert.ok(Errors.getErrorStack(error).length === 0);
    }

    try {
        throw { one: 1, two: 2, three: "three" };
    }
    catch (error) {
        assert.equal(Errors.getErrorMessage(error), "{\n" +
            "  \"one\": 1,\n" +
            "  \"two\": 2,\n" +
            "  \"three\": \"three\"\n" +
            "}");
        assert.ok(Errors.getErrorStack(error).length == 0);
    }

    assert.equal(Errors.getErrorMessage(null), "");
    assert.equal(Errors.getErrorStack(null), "");

    assert.equal(Errors.getErrorMessage("stringError"), "stringError");
    assert.equal(Errors.getErrorStack("stringError"), "string thrown as error");

    assert.equal(Errors.getErrorMessage(42), "42");
    assert.equal(Errors.getErrorStack(42), "");
});

QUnit.test("joinArray Tests", function (assert) {
    assert.equal(Errors.joinArray(null, " : "), null);
    assert.equal(Errors.joinArray(["1"], " : "), "1");
    assert.equal(Errors.joinArray(["1", "2"], " : "), "1 : 2");
    assert.equal(Errors.joinArray([null, "2"], " : "), "2");
    assert.equal(Errors.joinArray(["1", null], " : "), "1");
    assert.equal(Errors.joinArray(["1", null, "3"], " : "), "1 : 3");
    assert.equal(Errors.joinArray([1, 2], " : "), "1 : 2");
});

QUnit.test("isError Tests", function (assert) {
    try { document.notAFunction(); } catch (error) { assert.ok(Errors.isError(error)); }
    try { throw null; } catch (error) { assert.notOk(Errors.isError(error)); }
    try { throw "string"; } catch (error) { assert.notOk(Errors.isError(error)); }
    try { throw 42; } catch (error) { assert.notOk(Errors.isError(error)); }
    assert.notOk(Errors.isError("string"));
    assert.notOk(Errors.isError(42));
    assert.notOk(Errors.isError(null));
});<commit_msg>small tweak to test stack normalization<commit_after>/* global Errors */
/* global QUnit */

// Strip stack of rows with unittests.html.
function cleanStack(stack) {
    if (!stack) return null;
    return stack.map(function (item) {
        return item.replace(/.*localhost.*/, "")
            .replace(/.*azurewebsites.*/, "")
            .replace(/.*\.\.\/Scripts\/.*/, "")
            .replace(/\n+/, "\n")
            .replace(/^.*?\.(.*)@/, "$1@")
            .replace(/^.*\/<\(\)@http/, "Anonymous function()@http")
            .replace(/{anonymous}/, "Anonymous function")
            .replace(/(js:\d+):\d*/, "$1"); // remove column # since they may vary by browser
    }).filter(function (item) {
        return !!item;
    });
}

QUnit.assert.errorsEqual = function (value, expectedValues, message) {
    var found = expectedValues.some(function (expected) {
        if (value === expected) {
            this.pushResult({
                result: true,
                actual: value,
                expected: expected,
                message: message
            });

            return true;
        }
    }, this);

    if (!found) {
        this.pushResult({
            result: false,
            actual: value,
            expected: expectedValues,
            message: message
        });
    }
};

QUnit.test("Errors.parse Tests", function (assert) {

    assert.expect(20); // Count of assert calls in the tests below
    var done = assert.async(10); // Count of asynchronous calls below

    Errors.parse("stringError", "message", function (eventName, stack) {
        assert.equal(eventName, "message : stringError", "Errors.parse 1 error");
        assert.deepEqual(cleanStack(stack), [
            "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
            "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
            "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
            "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
        ], "Errors.parse 1 stack");
        done();
    });

    try {
        document.notAFunction();
    }
    catch (error) {
        Errors.parse(error, "message", function (eventName, stack) {
            assert.errorsEqual(eventName, ["message : Object doesn't support property or method 'notAFunction'",
                "message : document.notAFunction is not a function"], "Try 1 error");
            assert.deepEqual(cleanStack(stack), [
                "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
                "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
                "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
                "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
            ], "Try 1 stack");
            done();
        });
    }

    try {
        document.notAFunction();
    }
    catch (error) {
        Errors.parse(error, null, function (eventName, stack) {
            assert.errorsEqual(eventName, ["Object doesn't support property or method 'notAFunction'",
                "document.notAFunction is not a function"], "Try 2 error");
            assert.deepEqual(cleanStack(stack), [
                "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
                "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
                "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
                "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
            ], "Try 2 stack");
            done();
        });
    }

    try {
        throw 42;
    }
    catch (error) {
        Errors.parse(error, "message", function (eventName, stack) {
            assert.equal(eventName, "message : 42", "Try 3 error");
            assert.deepEqual(cleanStack(stack), [
                "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
                "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
                "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
                "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
            ], "Try 3 stack");
            done();
        });
    }

    try {
        throw { one: 1, two: 2, three: "three" };
    }
    catch (error) {
        Errors.parse(error, null, function (eventName, stack) {
            assert.equal(eventName, "{\n" +
                "  \"one\": 1,\n" +
                "  \"two\": 2,\n" +
                "  \"three\": \"three\"\n" +
                "}",
                "Try 4 error");
            assert.deepEqual(cleanStack(stack), [
                "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
                "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
                "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
                "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
            ], "Try 4 stack");
            done();
        });
    }

    try {
        throw null;
    }
    catch (error) {
        Errors.parse(error, null, function (eventName, stack) {
            assert.equal(eventName, "Unknown exception", "Try 5 error");
            assert.deepEqual(cleanStack(stack), [
                "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
                "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
                "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
                "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
                "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
            ], "Try 5 stack");
            done();
        });
    }

    Errors.parse(null, "message", function (eventName, stack) {
        assert.equal(eventName, "message", "Errors.parse 2 error");
        assert.deepEqual(cleanStack(stack), [
            "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
            "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
            "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
            "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
        ], "Errors.parse 2 stack");
        done();
    });

    Errors.parse(null, null, function (eventName, stack) {
        assert.equal(eventName, "Unknown exception", "Errors.parse 3 error");
        assert.deepEqual(cleanStack(stack), [
            "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
            "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
            "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
            "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
        ], "Errors.parse 3 stack");
        done();
    });

    var brokenError = new Error();
    Errors.parse(brokenError, "message", function (eventName, stack) {
        assert.equal(eventName, "message", "brokenError event");
        assert.deepEqual(cleanStack(stack), [
            "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
            "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
            "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
            "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
        ], "brokenError stack");
        done();
    });

    Errors.parse(42, "message", function (eventName, stack) {
        assert.equal(eventName, "message : 42", "Errors.parse 4 error");
        assert.deepEqual(cleanStack(stack), [
            "runTest()@https://code.jquery.com/qunit/qunit-2.4.0.js:1471",
            "run()@https://code.jquery.com/qunit/qunit-2.4.0.js:1457",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:1663",
            "advance()@https://code.jquery.com/qunit/qunit-2.4.0.js:1116",
            "begin()@https://code.jquery.com/qunit/qunit-2.4.0.js:2928",
            "Anonymous function()@https://code.jquery.com/qunit/qunit-2.4.0.js:2888"
        ], "Errors.parse 4 stack");
        done();
    });
});

QUnit.test("getError* Tests", function (assert) {
    try {
        document.notAFunction();
    }
    catch (error) {
        assert.errorsEqual(Errors.getErrorMessage(error), ["Object doesn't support property or method 'notAFunction'",
            "document.notAFunction is not a function"]);
        assert.ok(Errors.getErrorStack(error).length > 0);
    }

    try {
        throw "string";
    }
    catch (error) {
        assert.equal(Errors.getErrorMessage(error), "string");
        assert.equal(Errors.getErrorStack(error), "string thrown as error");
    }

    try {
        throw 42;
    }
    catch (error) {
        assert.equal(Errors.getErrorMessage(error), "42");
        assert.ok(Errors.getErrorStack(error).length === 0);
    }

    try {
        throw { one: 1, two: 2, three: "three" };
    }
    catch (error) {
        assert.equal(Errors.getErrorMessage(error), "{\n" +
            "  \"one\": 1,\n" +
            "  \"two\": 2,\n" +
            "  \"three\": \"three\"\n" +
            "}");
        assert.ok(Errors.getErrorStack(error).length == 0);
    }

    assert.equal(Errors.getErrorMessage(null), "");
    assert.equal(Errors.getErrorStack(null), "");

    assert.equal(Errors.getErrorMessage("stringError"), "stringError");
    assert.equal(Errors.getErrorStack("stringError"), "string thrown as error");

    assert.equal(Errors.getErrorMessage(42), "42");
    assert.equal(Errors.getErrorStack(42), "");
});

QUnit.test("joinArray Tests", function (assert) {
    assert.equal(Errors.joinArray(null, " : "), null);
    assert.equal(Errors.joinArray(["1"], " : "), "1");
    assert.equal(Errors.joinArray(["1", "2"], " : "), "1 : 2");
    assert.equal(Errors.joinArray([null, "2"], " : "), "2");
    assert.equal(Errors.joinArray(["1", null], " : "), "1");
    assert.equal(Errors.joinArray(["1", null, "3"], " : "), "1 : 3");
    assert.equal(Errors.joinArray([1, 2], " : "), "1 : 2");
});

QUnit.test("isError Tests", function (assert) {
    try { document.notAFunction(); } catch (error) { assert.ok(Errors.isError(error)); }
    try { throw null; } catch (error) { assert.notOk(Errors.isError(error)); }
    try { throw "string"; } catch (error) { assert.notOk(Errors.isError(error)); }
    try { throw 42; } catch (error) { assert.notOk(Errors.isError(error)); }
    assert.notOk(Errors.isError("string"));
    assert.notOk(Errors.isError(42));
    assert.notOk(Errors.isError(null));
});<|endoftext|>


<commit_before>/*
* overried
* */
!function (name, context, definition) {
  if (typeof define == 'function') define(definition)
  else if (typeof module != 'undefined') module.exports = definition()
  else context[name] = definition()
}('utils', this, function(){
  /*
  * set base rem
  * */
  document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';

  var _ = window._ || (window._ = {});

  /*
  * iterator for array and object
  * */
  _.each = function(obj, iteratee, context){
    var i, length;
    if ($.isArr(obj)) {
      for (i = 0, length = obj.length; i < length; i++) {
        iteratee.call(context, obj[i], i, obj);
      }
    } else {
      for (key in obj) {
        iteratee.call(context, obj[key]);
      }
    }
    return obj;
  }
  /*
  * extend first level key value
  * @param {object} object
  * @param {object} object
  * */
  _.extend = function (object) {
    // Takes an unlimited number of extenders.
    var args = Array.prototype.slice.call(arguments, 1);

    // For each extender, copy their properties on our object.
    for (var i = 0, source; source = args[i]; i++) {
        if (!source) continue;
        for (var property in source) {
            object[property] = source[property];
        }
    }

    return object;
  }
  /*
  * extend all level key value
  * @param {object} object
  * @param {object} object
  * */
  _.extendDeep = function(a, b){
    if ("_" in window) {
      for (var k in b) {
        if ( $.isObj(b[k]) )
          arguments.callee(a[k], b[k]);
        else
          (a[k] = b[k]);
      }
      return a
    }
  }

  _.isFunc = function(a){
    return toString.call(a) === "[object Function]"
  }

  _.isArr = function(a){
    return toString.call(a) === "[object Array]"
  }

  _.isObj = function(a){
    return toString.call(a) === "[object Object]"
  }

  _.isNum = function(a){
    return toString.call(a) === "[object Number]" && a.toString() != "NaN"
  }

  _.isCH = function(a){
    return /[\u4E00-\u9FFF]+/.test(a)
  }
  /*
  * device pixel ratio
  * */
  _.isRetina = (function(){
    var mediaQuery = "(-webkit-min-device-pixel-ratio: 1.5),\
    (min--moz-device-pixel-ratio: 1.5),\
    (-o-min-device-pixel-ratio: 3/2),\
    (min-resolution: 1.5dppx)";
    if (window.devicePixelRatio > 1)
      return true;
    if (window.matchMedia && window.matchMedia(mediaQuery).matches)
      return true;
    return false;
  })();
  /*
  * simple XSS replace
  * */
  _.strXSSCheck = function(str){
    return str.replace(/[\'\"\>\<\s]/g, "");
  };

  /*
  * escape functional for html
  * */
  (function(){
    var htmlEscapes = {
      '&': '&',
      '<': '<',
      '>': '>',
      '"': '"',
      "'": ''',
      '`': '`'
    },
    htmlUnEscapes = {
      '&': '&',
      '<': '<',
      '>': '>',
      '"': '"',
      ''': "'",
      '`': '`'
    };

    var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g,
        reUnescapedHtml = /[&<>"'`]/g;

    function escapeHtmlChar(chr) {
      return htmlEscapes[chr];
    }

    function escape(string) {
      // reset `lastIndex` because in IE < 9 `String#replace` does not
      string = (string == null) ? '' : String(string);
      return string && (reUnescapedHtml.lastIndex = 0, reUnescapedHtml.test(string))
        ? string.replace(reUnescapedHtml, escapeHtmlChar)
        : string;
    }
    function unescape(string) {
      string = (string == null) ? '' : String(string);
      return string && (reEscapedHtml.lastIndex = 0, reEscapedHtml.test(string))
        ? string.replace(reEscapedHtml, htmlUnEscapes)
        : string;
    }

    var _ = root._ || {};
    _.escape = _.escape || window.escape || escape;
    _.unescape = _.unescape || window.unescape || unescape;
  })();
});<commit_msg>update<commit_after>/*
* overried
* */
!function (name, context, definition) {
  if (typeof define == 'function') define(definition)
  else if (typeof module != 'undefined') module.exports = definition()
  else context[name] = definition()
}('utils', this, function(){
  /*
  * set base rem
  * */
  document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';

  var _ = window._ || (window._ = {});

  /*
  * iterator for array and object
  * */
  _.each = function(obj, iteratee, context){
    var i, length;
    if ($.isArr(obj)) {
      for (i = 0, length = obj.length; i < length; i++) {
        iteratee.call(context, obj[i], i, obj);
      }
    } else {
      for (key in obj) {
        iteratee.call(context, obj[key]);
      }
    }
    return obj;
  }
  /*
  * extend first level key value
  * @param {object} object
  * @param {object} object
  * */
  _.extend = function (object) {
    // Takes an unlimited number of extenders.
    var args = Array.prototype.slice.call(arguments, 1);

    // For each extender, copy their properties on our object.
    for (var i = 0, source; source = args[i]; i++) {
        if (!source) continue;
        for (var property in source) {
            object[property] = source[property];
        }
    }

    return object;
  }
  /*
  * extend all level key value
  * @param {object} object
  * @param {object} object
  * */
  _.extendDeep = function(a, b){
    if ("_" in window) {
      for (var k in b) {
        if ( $.isObj(b[k]) )
          arguments.callee(a[k], b[k]);
        else
          (a[k] = b[k]);
      }
      return a
    }
  }

  _.isFunc = function(a){
    return toString.call(a) === "[object Function]"
  }

  _.isArr = function(a){
    return toString.call(a) === "[object Array]"
  }

  _.isObj = function(a){
    return toString.call(a) === "[object Object]"
  }

  _.isNum = function(a){
    return toString.call(a) === "[object Number]" && a.toString() != "NaN"
  }

  _.isCH = function(a){
    return /[\u4E00-\u9FFF]+/.test(a)
  }
  /*
  * device pixel ratio
  * */
  _.isRetina = (function(){
    var mediaQuery = "(-webkit-min-device-pixel-ratio: 1.5),\
    (min--moz-device-pixel-ratio: 1.5),\
    (-o-min-device-pixel-ratio: 3/2),\
    (min-resolution: 1.5dppx)";
    if (window.devicePixelRatio > 1)
      return true;
    if (window.matchMedia && window.matchMedia(mediaQuery).matches)
      return true;
    return false;
  })();
  /*
  * simple XSS replace
  * */
  _.strXSSCheck = function(str){
    return str.replace(/[\'\"\>\<\s]/g, "");
  };

  /*
  * escape functional for html
  * */
  (function(){
    var htmlEscapes = {
      '&': '&',
      '<': '<',
      '>': '>',
      '"': '"',
      "'": ''',
      '`': '`'
    },
    htmlUnEscapes = {
      '&': '&',
      '<': '<',
      '>': '>',
      '"': '"',
      ''': "'",
      '`': '`'
    };

    var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g,
        reUnescapedHtml = /[&<>"'`]/g;

    function escapeHtmlChar(chr) {
      return htmlEscapes[chr];
    }

    function escape(string) {
      // reset `lastIndex` because in IE < 9 `String#replace` does not
      string = (string == null) ? '' : String(string);
      return string && (reUnescapedHtml.lastIndex = 0, reUnescapedHtml.test(string))
        ? string.replace(reUnescapedHtml, escapeHtmlChar)
        : string;
    }
    function unescape(string) {
      string = (string == null) ? '' : String(string);
      return string && (reEscapedHtml.lastIndex = 0, reEscapedHtml.test(string))
        ? string.replace(reEscapedHtml, htmlUnEscapes)
        : string;
    }

    var _ = window._ || {};
    _.escape = _.escape || window.escape || escape;
    _.unescape = _.unescape || window.unescape || unescape;
  })();
});<|endoftext|>