<commit_before>import React, { Component } from 'react'
import Helmet from 'react-helmet'
import styled, { injectGlobal, withComponent } from 'react-emotion'
import { ThemeProvider } from 'emotion-theming'
import { topography } from 'hero-patterns'
import theme from '../utils/theme'
import { Box, Flex, Text } from '../components/Layout'
import Navigation from '../components/Navigation'
import Footer from '../components/Footer'

import normalize from 'normalize.css'
injectGlobal`
  html {
    box-sizing: border-box;
    background-color: ${theme.colors.orange};
  }
  *, *:before, *:after {
    box-sizing: inherit;
  }
  svg {
    fill: currentColor;
  }
  a {
    text-decoration: none;
  }

  @media print {
    nav, footer {
      display: none !important;
    }
  }
`

const Backdrop = styled(Box)`
  background-image: ${({ theme }) => topography(theme.colors.white)};
  background-position: center top;
  @media (min-width: ${({ theme }) => theme.breakpoints[0]}em) {
    background-size: 1200px;
  }
`
// the min-height stuff here is kind of gross,
// but I'm not sure of a way of accessing these values inside styled-system like this
// just gotta update the step on the scale here if it's updated in <Layout />
const Content = styled(Box)`
  min-height: calc(100vh - ${({ theme }) => theme.space[2]} * 2);
  @media (min-width: ${({ theme }) => theme.breakpoints[0]}em) {
    min-height: calc(100vh - ${({ theme }) => theme.space[3]} * 2);
  }
`
// have to set min-height here too
// because otherwise the flex container isn't as tall as the content container
// preventing the auto footer stuff from happening.
const Constraint = styled(Flex)`
  max-width: 64rem;
  margin-left: auto;
  margin-right: auto;
  min-height: calc(100vh - ${({ theme }) => theme.space[2]} * 4);
  @media (min-width: ${({ theme }) => theme.breakpoints[0]}em) {
    min-height: calc(100vh - ${({ theme }) => theme.space[3]} * 4);
  }
`

const Main = Box.withComponent('main')

const Layout = ({ children, location, data }) => (
  <ThemeProvider theme={theme}>
    <Backdrop p={[2, 3]} bg="orange">
      <Helmet>
        <title>{data.site.siteMetadata.title}</title>
        <meta name="description" content={data.site.siteMetadata.description} />
        <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
        <link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32" />
        <link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16" />
        <link rel="manifest" href="/manifest.json" />
        <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#F2930D" />
        <meta name="theme-color" content="#F2930D" />
      </Helmet>
      <Content color="black" bg="white" py={3} px={[3, 4]} borderRadius={2} fontFamily="sansSerif">
        <Constraint flexDirection="column">
          <Navigation location={location} />
          {children()}

        </Constraint>
      </Content>
    </Backdrop>
  </ThemeProvider>
)

export const pageQuery = graphql`
  query LayoutQuery {
    site {
      siteMetadata {
        title
        description
        siteUrl
      }
    }
    allMarkdownRemark(sort: { order: DESC, fields: [frontmatter___date] }, limit: 1) {
      edges {
        node {
          frontmatter {
            title
          }
          fields {
            slug
          }
        }
      }
    }
  }
`

export default Layout
<commit_msg>:lipstick: ok fine slightly increase pattern size on mobile<commit_after>import React, { Component } from 'react'
import Helmet from 'react-helmet'
import styled, { injectGlobal, withComponent } from 'react-emotion'
import { ThemeProvider } from 'emotion-theming'
import { topography } from 'hero-patterns'
import theme from '../utils/theme'
import { Box, Flex, Text } from '../components/Layout'
import Navigation from '../components/Navigation'
import Footer from '../components/Footer'

import normalize from 'normalize.css'
injectGlobal`
  html {
    box-sizing: border-box;
    background-color: ${theme.colors.orange};
  }
  *, *:before, *:after {
    box-sizing: inherit;
  }
  svg {
    fill: currentColor;
  }
  a {
    text-decoration: none;
  }

  @media print {
    nav, footer {
      display: none !important;
    }
  }
`

const Backdrop = styled(Box)`
  background-image: ${({ theme }) => topography(theme.colors.white)};
  background-position: center top;
  background-size: 900px;
  @media (min-width: ${({ theme }) => theme.breakpoints[0]}em) {
    background-size: 1200px;
  }
`
// the min-height stuff here is kind of gross,
// but I'm not sure of a way of accessing these values inside styled-system like this
// just gotta update the step on the scale here if it's updated in <Layout />
const Content = styled(Box)`
  min-height: calc(100vh - ${({ theme }) => theme.space[2]} * 2);
  @media (min-width: ${({ theme }) => theme.breakpoints[0]}em) {
    min-height: calc(100vh - ${({ theme }) => theme.space[3]} * 2);
  }
`
// have to set min-height here too
// because otherwise the flex container isn't as tall as the content container
// preventing the auto footer stuff from happening.
const Constraint = styled(Flex)`
  max-width: 64rem;
  margin-left: auto;
  margin-right: auto;
  min-height: calc(100vh - ${({ theme }) => theme.space[2]} * 4);
  @media (min-width: ${({ theme }) => theme.breakpoints[0]}em) {
    min-height: calc(100vh - ${({ theme }) => theme.space[3]} * 4);
  }
`

const Main = Box.withComponent('main')

const Layout = ({ children, location, data }) => (
  <ThemeProvider theme={theme}>
    <Backdrop p={[2, 3]} bg="orange">
      <Helmet>
        <title>{data.site.siteMetadata.title}</title>
        <meta name="description" content={data.site.siteMetadata.description} />
        <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
        <link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32" />
        <link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16" />
        <link rel="manifest" href="/manifest.json" />
        <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#F2930D" />
        <meta name="theme-color" content="#F2930D" />
      </Helmet>
      <Content color="black" bg="white" py={3} px={[3, 4]} borderRadius={2} fontFamily="sansSerif">
        <Constraint flexDirection="column">
          <Navigation location={location} />
          {children()}

        </Constraint>
      </Content>
    </Backdrop>
  </ThemeProvider>
)

export const pageQuery = graphql`
  query LayoutQuery {
    site {
      siteMetadata {
        title
        description
        siteUrl
      }
    }
    allMarkdownRemark(sort: { order: DESC, fields: [frontmatter___date] }, limit: 1) {
      edges {
        node {
          frontmatter {
            title
          }
          fields {
            slug
          }
        }
      }
    }
  }
`

export default Layout
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { Autobind } from 'es-decorators';
import debounce from 'lodash/debounce';
import isEqual from 'lodash/isEqual';
import MediaQuery from 'react-responsive';
import 'isomorphic-fetch';
import ReactDOM from 'react-dom'
import DropdownTreeSelect from 'react-dropdown-tree-select'

// Redux
import withRedux from 'next-redux-wrapper';
import { initStore } from 'store';
import {
  toggleLayerGroupVisibility,
  toggleLayerGroup,
  setLayerGroupsOrder,
  setLayerGroupActiveLayer,
  setLayerGroups,
  getDatasets,
  setDatasetsPage,
  setDatasetsSearchFilter,
  setDatasetsIssueFilter,
  getVocabularies
} from 'redactions/explore';
import { redirectTo } from 'redactions/common';
import { toggleModal, setModalOptions } from 'redactions/modal';

// Selectors
import getpaginatedDatasets from 'selectors/explore/datasetsPaginatedExplore';
import getFilteredDatasets from 'selectors/explore/filterDatasets';
import getLayerGroups from 'selectors/explore/layersExplore';

// Components
import Sidebar from 'components/app/layout/Sidebar';
import DatasetListHeader from 'components/app/explore/DatasetListHeader';
import DatasetList from 'components/app/explore/DatasetList';
import Paginator from 'components/ui/Paginator';
import Map from 'components/vis/Map';
import ShareModalExplore from 'components/modal/ShareModalExplore';
import Legend from 'components/ui/Legend';
import CustomSelect from 'components/ui/CustomSelect';
import Spinner from 'components/ui/Spinner';
import Icon from 'components/ui/Icon';
import SearchInput from 'components/ui/SearchInput';

// Layout
import Page from 'components/app/layout/Page';
import Layout from 'components/app/layout/Layout';

// Utils
import LayerManager from 'utils/layers/LayerManager';

const mapConfig = {
  zoom: 3,
  latLng: {
    lat: 0,
    lng: 0
  }
};

class Explore extends Page {
  constructor(props) {
    super(props);

    this.state = {
      vocabularies: props.explore.vocabularies.list || [],
      knowledgeGraph: {}
    };

    // BINDINGS
    this.handleFilterDatasetsSearch = debounce(this.handleFilterDatasetsSearch.bind(this), 500);
    this.handleFilterDatasetsIssue = this.handleFilterDatasetsIssue.bind(this);
  }

  componentWillMount() {
    const query = this.props.url.query;
    if (query.page) {
      this.props.setDatasetsPage(+query.page);
    }

    if (query.layers) {
      try {
        const layerGroups = JSON.parse(decodeURIComponent(query.layers));
        this.props.setLayerGroups(layerGroups);
      } catch (e) {
        this.props.setLayerGroups([]);
      }
    }

    if (query.search) {
      this.props.setDatasetsSearchFilter({ value: query.search, key: 'name' });
    }

    if (query.issue) {
      this.props.setDatasetsIssueFilter(JSON.parse(query.issue));
    }

    this.props.getDatasets();
    this.props.getVocabularies();
    this.loadKnowledgeGraph();
  }

  componentWillReceiveProps(nextProps) {
    this.setState({
      vocabularies: nextProps.explore.vocabularies.list
    });
  }

  shouldComponentUpdate(nextProps, nextState) {
    return !isEqual(nextProps.explore, this.props.explore)
      || !isEqual(nextState, this.state);
  }

  loadKnowledgeGraph() {
    fetch(new Request('/static/data/knowledgeGraphLite.json'))
      .then(response => response.json())
      .then((response) => {
        this.setState({ knowledgeGraph: response });
        const element = document.getElementsByClassName('knowledge-graph-selector')[0];

        const onChange = (currentNode, selectedNodes) => { console.log('onChange::', currentNode, selectedNodes) }
        const onAction = ({action, node}) => { console.log(`onAction:: [${action}]`, node) }
        const onNodeToggle = (currentNode) => { console.log('onNodeToggle::', currentNode) }
        console.log(response);
        ReactDOM.render(<DropdownTreeSelect data={response} onChange={onChange} onAction={onAction} onNodeToggle={onNodeToggle} />, element);
      });
  }

  @Autobind
  handleRedirect(item) {
    if (item && item.value) {
      this.props.redirectTo(`explore/${item.value}`);
    }
  }

  handleFilterDatasetsSearch(value) {
    const filter = { value: value || '', key: 'name' };
    this.props.setDatasetsSearchFilter(filter);

    // We move the user to the first page
    this.props.setDatasetsPage(1);
  }

  handleFilterDatasetsIssue(item, levels, key) {
    const filter = item ? [{ levels, value: item.value, key }] : null;
    this.props.setDatasetsIssueFilter(filter);

    // We move the user to the first page
    this.props.setDatasetsPage(1);
  }

  handleShareModal() {
    const options = {
      children: ShareModalExplore,
      childrenProps: {
        url: window.location.href,
        layerGroups: this.props.rawLayerGroups,
        toggleModal: this.props.toggleModal
      }
    };
    this.props.toggleModal(true);
    this.props.setModalOptions(options);
  }

  /**
   * Event handler executed when the user toggles the visibility
   * of a layer group in the legend
   * @param {LayerGroup} layerGroup
   */
  @Autobind
  onToggleLayerGroupVisibility(layerGroup) {
    this.props.toggleLayerGroupVisibility(layerGroup.dataset, !layerGroup.visible);
  }

  /**
   * Event handler executed when the user removes a layer
   * group from the map
   * @param {LayerGroup} layerGroup
   */
  @Autobind
  onRemoveLayerGroup(layerGroup) {
    this.props.removeLayerGroup(layerGroup.dataset);
  }

  /**
   * Event handler executed when the user re-orders the
   * layer groups
   * @param {string[]} datasets - List of datasets IDs
   */
  @Autobind
  onSetLayerGroupsOrder(datasets) {
    this.props.setLayerGroupsOrder(datasets);
  }

  /**
   * Event handler executed when the user change the active
   * layer of a layer group
   * @param {string} dataset - Dataset ID
   * @param {string} layer - Layer ID
   */
  @Autobind
  onSetLayerGroupActiveLayer(dataset, layer) {
    this.props.setLayerGroupActiveLayer(dataset, layer);
  }

  /**
   * Return the current value of the vocabulary filter
   * @returns {string}
   */
  getCurrentVocabularyFilter() {
    const filters = this.props.explore.filters;
    if (!filters.length) return null;

    const filter = filters.find(f => f.key === 'vocabulary');

    return filter && filter.value;
  }

  /**
   * Return the current search made on the name of the
   * datasets
   * @returns {string}
   */
  getCurrentNameFilter() {
    const filters = this.props.explore.filters;
    if (!filters.length) return null;

    const filter = filters.find(f => f.key === 'name');

    return filter && filter.value;
  }

  render() {
    const { vocabularies } = this.state;
    const { explore, paginatedDatasets } = this.props;
    const { search, issue } = explore.filters;

    // TEMPORAL only whilst the knowledge graph is not used
    const dataTypesVocabulary = vocabularies.length > 0 ? vocabularies.find(elem => elem.value === 'dataset_type').items : [];
    const geographiesVocabulary = vocabularies.length > 0 ? vocabularies.find(elem => elem.value === 'location').items : [];

    return (
      <Layout
        title="Explore"
        description="Explore description"
        url={this.props.url}
        user={this.props.user}
      >

            <Sidebar>

Explore

                <SearchInput
                  onSearch={this.handleFilterDatasetsSearch}
                  input={{
                    value: search && search.value,
                    placeholder: 'Search dataset'
                  }}
                />

                <CustomSelect
                  options={geographiesVocabulary}
                  onValueChange={this.handleFilterDatasetsIssue}
                  placeholder="Geographies"
                  value={issue && issue.length > 0 && issue[0].value}
                />
                <CustomSelect
                  options={dataTypesVocabulary}
                  onValueChange={this.handleFilterDatasetsIssue}
                  placeholder="Data types"
                  value={issue && issue.length > 0 && issue[0].value}
                />

              <DatasetListHeader
                list={explore.datasets.list}
                mode={explore.datasets.mode}
              />
              <Spinner
                isLoading={explore.datasets.loading}
                className="-light"
              />

                  <DatasetList
                    list={paginatedDatasets}
                    mode={explore.datasets.mode}
                    showActions
                  />

              <Paginator
                options={{
                  page: explore.datasets.page,
                  limit: explore.datasets.limit,
                  size: explore.datasets.list.length
                }}
                onChange={(page) => {
                  this.props.setDatasetsPage(page);
                  // Scroll to the top of the list
                  document.getElementsByClassName('sidebar-content')[0].scrollTop = 0;
                }}
              />
            </Sidebar>
            <MediaQuery minDeviceWidth={720} values={{ deviceWidth: 720 }}>

                <Map
                  LayerManager={LayerManager}
                  mapConfig={mapConfig}
                  layerGroups={this.props.layerGroups}
                />

                <button className="share-button" onClick={() => this.handleShareModal()}>
                  <Icon name="icon-share" className="-small" />
                </button>

                {this.props.layerGroups && this.props.layerGroups.length &&
                  <Legend
                    layerGroups={this.props.layerGroups}
                    className={{ color: '-dark' }}
                    toggleLayerGroupVisibility={this.onToggleLayerGroupVisibility}
                    setLayerGroupsOrder={this.onSetLayerGroupsOrder}
                    removeLayerGroup={this.onRemoveLayerGroup}
                    setLayerGroupActiveLayer={this.onSetLayerGroupActiveLayer}
                  />
                }

            </MediaQuery>

      </Layout>
    );
  }
}

Explore.propTypes = {
  // ROUTER
  url: PropTypes.object,

  // STORE
  explore: PropTypes.object,
  paginatedDatasets: PropTypes.array,
  layerGroups: PropTypes.array,
  toggledDataset: PropTypes.string,

  // ACTIONS

  getDatasets: PropTypes.func,
  getVocabularies: PropTypes.func,
  setDatasetsPage: PropTypes.func,
  redirectTo: PropTypes.func,
  setDatasetsFilters: PropTypes.func,
  toggleModal: PropTypes.func,
  setModalOptions: PropTypes.func,

  // Toggle the visibility of a layer group based on the layer passed as argument
  toggleLayerGroupVisibility: PropTypes.func.isRequired,
  // Remove the layer group
  removeLayerGroup: PropTypes.func.isRequired,
  // Set the active layer of a layer group
  setLayerGroupActiveLayer: PropTypes.func.isRequired,
  // Set the layer groups
  setLayerGroups: PropTypes.func.isRequired
};

const mapStateToProps = (state) => {
  const datasets = (state.explore.filters.search || state.explore.filters.issue)
    ? Object.assign({}, state.explore.datasets, { list: getFilteredDatasets(state) })
    : state.explore.datasets;

  const explore = Object.assign({}, state.explore, { datasets });

  return {
    explore,
    paginatedDatasets: getpaginatedDatasets(explore),
    allDatasets: state.explore.datasets.list,
    layerGroups: getLayerGroups(state),
    rawLayerGroups: state.explore.layers
  };
};

const mapDispatchToProps = dispatch => ({
  getDatasets: () => { dispatch(getDatasets()); },
  getVocabularies: () => { dispatch(getVocabularies()); },
  setDatasetsSearchFilter: search => dispatch(setDatasetsSearchFilter(search)),
  setDatasetsIssueFilter: issue => dispatch(setDatasetsIssueFilter(issue)),
  redirectTo: (url) => { dispatch(redirectTo(url)); },
  toggleModal: (open, options) => dispatch(toggleModal(open, options)),
  setModalOptions: (options) => { dispatch(setModalOptions(options)); },
  setDatasetsPage: page => dispatch(setDatasetsPage(page)),
  toggleLayerGroupVisibility: (dataset, visible) => {
    dispatch(toggleLayerGroupVisibility(dataset, visible));
  },
  removeLayerGroup: dataset => dispatch(toggleLayerGroup(dataset, false)),
  setLayerGroupsOrder: datasets => dispatch(setLayerGroupsOrder(datasets)),
  setLayerGroupActiveLayer: (dataset, layer) => dispatch(setLayerGroupActiveLayer(dataset, layer)),
  setLayerGroups: layerGroups => dispatch(setLayerGroups(layerGroups))
});

export default withRedux(initStore, mapStateToProps, mapDispatchToProps)(Explore);
<commit_msg>update graph version userd<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { Autobind } from 'es-decorators';
import debounce from 'lodash/debounce';
import isEqual from 'lodash/isEqual';
import MediaQuery from 'react-responsive';
import 'isomorphic-fetch';
import ReactDOM from 'react-dom'
import DropdownTreeSelect from 'react-dropdown-tree-select'

// Redux
import withRedux from 'next-redux-wrapper';
import { initStore } from 'store';
import {
  toggleLayerGroupVisibility,
  toggleLayerGroup,
  setLayerGroupsOrder,
  setLayerGroupActiveLayer,
  setLayerGroups,
  getDatasets,
  setDatasetsPage,
  setDatasetsSearchFilter,
  setDatasetsIssueFilter,
  getVocabularies
} from 'redactions/explore';
import { redirectTo } from 'redactions/common';
import { toggleModal, setModalOptions } from 'redactions/modal';

// Selectors
import getpaginatedDatasets from 'selectors/explore/datasetsPaginatedExplore';
import getFilteredDatasets from 'selectors/explore/filterDatasets';
import getLayerGroups from 'selectors/explore/layersExplore';

// Components
import Sidebar from 'components/app/layout/Sidebar';
import DatasetListHeader from 'components/app/explore/DatasetListHeader';
import DatasetList from 'components/app/explore/DatasetList';
import Paginator from 'components/ui/Paginator';
import Map from 'components/vis/Map';
import ShareModalExplore from 'components/modal/ShareModalExplore';
import Legend from 'components/ui/Legend';
import CustomSelect from 'components/ui/CustomSelect';
import Spinner from 'components/ui/Spinner';
import Icon from 'components/ui/Icon';
import SearchInput from 'components/ui/SearchInput';

// Layout
import Page from 'components/app/layout/Page';
import Layout from 'components/app/layout/Layout';

// Utils
import LayerManager from 'utils/layers/LayerManager';

const mapConfig = {
  zoom: 3,
  latLng: {
    lat: 0,
    lng: 0
  }
};

class Explore extends Page {
  constructor(props) {
    super(props);

    this.state = {
      vocabularies: props.explore.vocabularies.list || [],
      knowledgeGraph: {}
    };

    // BINDINGS
    this.handleFilterDatasetsSearch = debounce(this.handleFilterDatasetsSearch.bind(this), 500);
    this.handleFilterDatasetsIssue = this.handleFilterDatasetsIssue.bind(this);
  }

  componentWillMount() {
    const query = this.props.url.query;
    if (query.page) {
      this.props.setDatasetsPage(+query.page);
    }

    if (query.layers) {
      try {
        const layerGroups = JSON.parse(decodeURIComponent(query.layers));
        this.props.setLayerGroups(layerGroups);
      } catch (e) {
        this.props.setLayerGroups([]);
      }
    }

    if (query.search) {
      this.props.setDatasetsSearchFilter({ value: query.search, key: 'name' });
    }

    if (query.issue) {
      this.props.setDatasetsIssueFilter(JSON.parse(query.issue));
    }

    this.props.getDatasets();
    this.props.getVocabularies();
    this.loadKnowledgeGraph();
  }

  componentWillReceiveProps(nextProps) {
    this.setState({
      vocabularies: nextProps.explore.vocabularies.list
    });
  }

  shouldComponentUpdate(nextProps, nextState) {
    return !isEqual(nextProps.explore, this.props.explore)
      || !isEqual(nextState, this.state);
  }

  loadKnowledgeGraph() {
    fetch(new Request('/static/data/knowledgeGraph.json'))
      .then(response => response.json())
      .then((response) => {
        this.setState({ knowledgeGraph: response });
        const element = document.getElementsByClassName('knowledge-graph-selector')[0];

        const onChange = (currentNode, selectedNodes) => { console.log('onChange::', currentNode, selectedNodes) }
        const onAction = ({action, node}) => { console.log(`onAction:: [${action}]`, node) }
        const onNodeToggle = (currentNode) => { console.log('onNodeToggle::', currentNode) }
        console.log(response);
        ReactDOM.render(<DropdownTreeSelect data={response} onChange={onChange} onAction={onAction} onNodeToggle={onNodeToggle} />, element);
      });
  }

  @Autobind
  handleRedirect(item) {
    if (item && item.value) {
      this.props.redirectTo(`explore/${item.value}`);
    }
  }

  handleFilterDatasetsSearch(value) {
    const filter = { value: value || '', key: 'name' };
    this.props.setDatasetsSearchFilter(filter);

    // We move the user to the first page
    this.props.setDatasetsPage(1);
  }

  handleFilterDatasetsIssue(item, levels, key) {
    const filter = item ? [{ levels, value: item.value, key }] : null;
    this.props.setDatasetsIssueFilter(filter);

    // We move the user to the first page
    this.props.setDatasetsPage(1);
  }

  handleShareModal() {
    const options = {
      children: ShareModalExplore,
      childrenProps: {
        url: window.location.href,
        layerGroups: this.props.rawLayerGroups,
        toggleModal: this.props.toggleModal
      }
    };
    this.props.toggleModal(true);
    this.props.setModalOptions(options);
  }

  /**
   * Event handler executed when the user toggles the visibility
   * of a layer group in the legend
   * @param {LayerGroup} layerGroup
   */
  @Autobind
  onToggleLayerGroupVisibility(layerGroup) {
    this.props.toggleLayerGroupVisibility(layerGroup.dataset, !layerGroup.visible);
  }

  /**
   * Event handler executed when the user removes a layer
   * group from the map
   * @param {LayerGroup} layerGroup
   */
  @Autobind
  onRemoveLayerGroup(layerGroup) {
    this.props.removeLayerGroup(layerGroup.dataset);
  }

  /**
   * Event handler executed when the user re-orders the
   * layer groups
   * @param {string[]} datasets - List of datasets IDs
   */
  @Autobind
  onSetLayerGroupsOrder(datasets) {
    this.props.setLayerGroupsOrder(datasets);
  }

  /**
   * Event handler executed when the user change the active
   * layer of a layer group
   * @param {string} dataset - Dataset ID
   * @param {string} layer - Layer ID
   */
  @Autobind
  onSetLayerGroupActiveLayer(dataset, layer) {
    this.props.setLayerGroupActiveLayer(dataset, layer);
  }

  /**
   * Return the current value of the vocabulary filter
   * @returns {string}
   */
  getCurrentVocabularyFilter() {
    const filters = this.props.explore.filters;
    if (!filters.length) return null;

    const filter = filters.find(f => f.key === 'vocabulary');

    return filter && filter.value;
  }

  /**
   * Return the current search made on the name of the
   * datasets
   * @returns {string}
   */
  getCurrentNameFilter() {
    const filters = this.props.explore.filters;
    if (!filters.length) return null;

    const filter = filters.find(f => f.key === 'name');

    return filter && filter.value;
  }

  render() {
    const { vocabularies } = this.state;
    const { explore, paginatedDatasets } = this.props;
    const { search, issue } = explore.filters;

    // TEMPORAL only whilst the knowledge graph is not used
    const dataTypesVocabulary = vocabularies.length > 0 ? vocabularies.find(elem => elem.value === 'dataset_type').items : [];
    const geographiesVocabulary = vocabularies.length > 0 ? vocabularies.find(elem => elem.value === 'location').items : [];

    return (
      <Layout
        title="Explore"
        description="Explore description"
        url={this.props.url}
        user={this.props.user}
      >

            <Sidebar>

Explore

                <SearchInput
                  onSearch={this.handleFilterDatasetsSearch}
                  input={{
                    value: search && search.value,
                    placeholder: 'Search dataset'
                  }}
                />

                <CustomSelect
                  options={geographiesVocabulary}
                  onValueChange={this.handleFilterDatasetsIssue}
                  placeholder="Geographies"
                  value={issue && issue.length > 0 && issue[0].value}
                />
                <CustomSelect
                  options={dataTypesVocabulary}
                  onValueChange={this.handleFilterDatasetsIssue}
                  placeholder="Data types"
                  value={issue && issue.length > 0 && issue[0].value}
                />

              <DatasetListHeader
                list={explore.datasets.list}
                mode={explore.datasets.mode}
              />
              <Spinner
                isLoading={explore.datasets.loading}
                className="-light"
              />

                  <DatasetList
                    list={paginatedDatasets}
                    mode={explore.datasets.mode}
                    showActions
                  />

              <Paginator
                options={{
                  page: explore.datasets.page,
                  limit: explore.datasets.limit,
                  size: explore.datasets.list.length
                }}
                onChange={(page) => {
                  this.props.setDatasetsPage(page);
                  // Scroll to the top of the list
                  document.getElementsByClassName('sidebar-content')[0].scrollTop = 0;
                }}
              />
            </Sidebar>
            <MediaQuery minDeviceWidth={720} values={{ deviceWidth: 720 }}>

                <Map
                  LayerManager={LayerManager}
                  mapConfig={mapConfig}
                  layerGroups={this.props.layerGroups}
                />

                <button className="share-button" onClick={() => this.handleShareModal()}>
                  <Icon name="icon-share" className="-small" />
                </button>

                {this.props.layerGroups && this.props.layerGroups.length &&
                  <Legend
                    layerGroups={this.props.layerGroups}
                    className={{ color: '-dark' }}
                    toggleLayerGroupVisibility={this.onToggleLayerGroupVisibility}
                    setLayerGroupsOrder={this.onSetLayerGroupsOrder}
                    removeLayerGroup={this.onRemoveLayerGroup}
                    setLayerGroupActiveLayer={this.onSetLayerGroupActiveLayer}
                  />
                }

            </MediaQuery>

      </Layout>
    );
  }
}

Explore.propTypes = {
  // ROUTER
  url: PropTypes.object,

  // STORE
  explore: PropTypes.object,
  paginatedDatasets: PropTypes.array,
  layerGroups: PropTypes.array,
  toggledDataset: PropTypes.string,

  // ACTIONS

  getDatasets: PropTypes.func,
  getVocabularies: PropTypes.func,
  setDatasetsPage: PropTypes.func,
  redirectTo: PropTypes.func,
  setDatasetsFilters: PropTypes.func,
  toggleModal: PropTypes.func,
  setModalOptions: PropTypes.func,

  // Toggle the visibility of a layer group based on the layer passed as argument
  toggleLayerGroupVisibility: PropTypes.func.isRequired,
  // Remove the layer group
  removeLayerGroup: PropTypes.func.isRequired,
  // Set the active layer of a layer group
  setLayerGroupActiveLayer: PropTypes.func.isRequired,
  // Set the layer groups
  setLayerGroups: PropTypes.func.isRequired
};

const mapStateToProps = (state) => {
  const datasets = (state.explore.filters.search || state.explore.filters.issue)
    ? Object.assign({}, state.explore.datasets, { list: getFilteredDatasets(state) })
    : state.explore.datasets;

  const explore = Object.assign({}, state.explore, { datasets });

  return {
    explore,
    paginatedDatasets: getpaginatedDatasets(explore),
    allDatasets: state.explore.datasets.list,
    layerGroups: getLayerGroups(state),
    rawLayerGroups: state.explore.layers
  };
};

const mapDispatchToProps = dispatch => ({
  getDatasets: () => { dispatch(getDatasets()); },
  getVocabularies: () => { dispatch(getVocabularies()); },
  setDatasetsSearchFilter: search => dispatch(setDatasetsSearchFilter(search)),
  setDatasetsIssueFilter: issue => dispatch(setDatasetsIssueFilter(issue)),
  redirectTo: (url) => { dispatch(redirectTo(url)); },
  toggleModal: (open, options) => dispatch(toggleModal(open, options)),
  setModalOptions: (options) => { dispatch(setModalOptions(options)); },
  setDatasetsPage: page => dispatch(setDatasetsPage(page)),
  toggleLayerGroupVisibility: (dataset, visible) => {
    dispatch(toggleLayerGroupVisibility(dataset, visible));
  },
  removeLayerGroup: dataset => dispatch(toggleLayerGroup(dataset, false)),
  setLayerGroupsOrder: datasets => dispatch(setLayerGroupsOrder(datasets)),
  setLayerGroupActiveLayer: (dataset, layer) => dispatch(setLayerGroupActiveLayer(dataset, layer)),
  setLayerGroups: layerGroups => dispatch(setLayerGroups(layerGroups))
});

export default withRedux(initStore, mapStateToProps, mapDispatchToProps)(Explore);
<|endoftext|>


<commit_before>"use strict";

function centered_modal(message) {
    var result = new Modal();
    result.message = message;
    var screen_frame = Screen.mainScreen().frameInRectangle();
    var result_frame = result.frame();
    result.origin = {
        x: 0.5 * (screen_frame.width - result_frame.width),
        y: 0.5 * (screen_frame.height - result_frame.height),
    };
    return result;
}

var h_reload = Phoenix.bind('r', ['alt'], function () {
    Phoenix.reload();
});

/* Window Handling */

function move_window(rect, screen) {
    screen = screen || Screen.mainScreen();
    var scr = screen.visibleFrameInRectangle();
    var r = {
        x: Math.round(scr.x + rect.x*scr.width),
        y: Math.round(scr.y + rect.y*scr.height),
        width: Math.round(scr.width * rect.width),
        height: Math.round(scr.height * rect.height),
    };
    Window.focusedWindow().setFrame(r);
}

function move_window_to_next_screen() {
    var currW = Window.focusedWindow();
    var cwFrame = currW.frame();
    var currScreen = currW.screen();
    var nextScreen = currScreen.next();
    var currScreenSize = currScreen.visibleFrameInRectangle();
    var relative = {
        x: (cwFrame.x - currScreenSize.x) / currScreenSize.width,
        y: (cwFrame.y - currScreenSize.y) / currScreenSize.height,
        width: cwFrame.width / currScreenSize.width,
        height: cwFrame.height / currScreenSize.height,
    };
    move_window(relative, nextScreen);
}

/* Spaces */

/* Support a prefix key with multiple suffix keys */

function PrefixKey(key, modifiers, description) {
    this.modal = centered_modal(description);
    this.suffixes = [];
    this.handlers = [];
    var that = this;
    this.prefix = Phoenix.bind(key, modifiers, function () {
        that.enableSuffixes();
        that.modal.show();
    });
}

PrefixKey.prototype.enableSuffixes = function () {
    var that = this;
    this.suffixes.forEach(function (x) {
        var h = Phoenix.bind(x.key, x.modifiers, function () {
            that.disableSuffixes();
            x.cb();
            that.modal.close();
            Phoenix.reload();
        });
        h.enable();
        that.handlers.push(h);
    });
};
PrefixKey.prototype.disableSuffixes = function () {
    this.handlers.forEach( function (x) {
        x.disable();
    });
    this.handlers = [];
};
PrefixKey.prototype.addSuffix = function (key, modifiers, cb) {
    this.suffixes.push({key: key, modifiers: modifiers, cb: cb});
};

/* Window handling prefix key */

var wPrefix = new PrefixKey('space', ['ctrl', 'alt', 'cmd'],
    "h - Left Half\nl - Right Half\ng - Wide Center\nm - Max\no - big left\np - big right\nO/P - medium left/right\ns - next screen\nesc - Abort");
wPrefix.addSuffix('h', [], function () {
    move_window({x: 0, y: 0, width: 0.5, height: 1.0});
});
wPrefix.addSuffix('l', [], function () {
    move_window({x: 0.5, y: 0, width: 0.5, height: 1.0});
});
wPrefix.addSuffix('g', [], function () {
    move_window({x: 0.15, y: 0, width: 0.7, height: 1.0});
});
wPrefix.addSuffix('m', [], function () {
    move_window({x: 0, y: 0, width: 1.0, height: 1.0});
});
wPrefix.addSuffix('c', [], function () {
    move_window({x: 0.2, y: 0.2, width: 0.6, height: 0.6});
});
wPrefix.addSuffix('o', [], function () {
    move_window({x: 0, y: 0, width: 0.9, height: 1.0});
});
wPrefix.addSuffix('o', ['shift'], function () {
    move_window({x: 0, y: 0, width: 0.8, height: 1.0});
});
wPrefix.addSuffix('p', [], function () {
    move_window({x: 0.1, y: 0, width: 0.9, height: 1.0});
});
wPrefix.addSuffix('p', ['shift'], function () {
    move_window({x: 0.2, y: 0, width: 0.8, height: 1.0});
});
wPrefix.addSuffix('s', [], function () {
    move_window_to_next_screen();
});
wPrefix.addSuffix('escape', [], function () {});
wPrefix.addSuffix('space', ['ctrl', 'alt', 'cmd'], function () {});

<commit_msg>Simplistic update for Phoenix 2.3.<commit_after>"use strict";

function centered_modal(message) {
    var result = new Modal();
    result.message = message;
    var screen_frame = Screen.main().frameInRectangle();
    var result_frame = result.frame();
    result.origin = {
        x: 0.5 * (screen_frame.width - result_frame.width),
        y: 0.5 * (screen_frame.height - result_frame.height),
    };
    return result;
}

var h_reload = new Key('r', ['alt'], function () {
    Phoenix.reload();
});

/* Window Handling */

function move_window(rect, screen) {
    screen = screen || Screen.main();
    var scr = screen.visibleFrameInRectangle();
    var r = {
        x: Math.round(scr.x + rect.x*scr.width),
        y: Math.round(scr.y + rect.y*scr.height),
        width: Math.round(scr.width * rect.width),
        height: Math.round(scr.height * rect.height),
    };
    Window.focused().setFrame(r);
}

function move_window_to_next_screen() {
    var currW = Window.focused();
    var cwFrame = currW.frame();
    var currScreen = currW.screen();
    var nextScreen = currScreen.next();
    var currScreenSize = currScreen.visibleFrameInRectangle();
    var relative = {
        x: (cwFrame.x - currScreenSize.x) / currScreenSize.width,
        y: (cwFrame.y - currScreenSize.y) / currScreenSize.height,
        width: cwFrame.width / currScreenSize.width,
        height: cwFrame.height / currScreenSize.height,
    };
    move_window(relative, nextScreen);
}

/* Spaces */

/* Support a prefix key with multiple suffix keys */

function PrefixKey(key, modifiers, description) {
    this.modal = centered_modal(description);
    this.suffixes = [];
    this.handlers = [];
    var that = this;
    this.prefix = new Key(key, modifiers, function () {
        that.enableSuffixes();
        that.modal.show();
    });
}

PrefixKey.prototype.enableSuffixes = function () {
    var that = this;
    this.suffixes.forEach(function (x) {
        var h = new Key(x.key, x.modifiers, function () {
            that.disableSuffixes();
            x.cb();
            that.modal.close();
            Phoenix.reload();
        });
        h.enable();
        that.handlers.push(h);
    });
};
PrefixKey.prototype.disableSuffixes = function () {
    this.handlers.forEach( function (x) {
        x.disable();
    });
    this.handlers = [];
};
PrefixKey.prototype.addSuffix = function (key, modifiers, cb) {
    this.suffixes.push({key: key, modifiers: modifiers, cb: cb});
};

/* Window handling prefix key */

var wPrefix = new PrefixKey('space', ['ctrl', 'alt', 'cmd'],
    "h/l - Left/Right Half\nc - Center\ng - Wide Center\nm - Max\no/p - big left/right\nO/P - medium left/right\ns - next screen\nesc - Abort");
wPrefix.addSuffix('h', [], function () {
    move_window({x: 0, y: 0, width: 0.5, height: 1.0});
});
wPrefix.addSuffix('l', [], function () {
    move_window({x: 0.5, y: 0, width: 0.5, height: 1.0});
});
wPrefix.addSuffix('g', [], function () {
    move_window({x: 0.15, y: 0, width: 0.7, height: 1.0});
});
wPrefix.addSuffix('m', [], function () {
    move_window({x: 0, y: 0, width: 1.0, height: 1.0});
});
wPrefix.addSuffix('c', [], function () {
    move_window({x: 0.2, y: 0.2, width: 0.6, height: 0.6});
});
wPrefix.addSuffix('o', [], function () {
    move_window({x: 0, y: 0, width: 0.9, height: 1.0});
});
wPrefix.addSuffix('o', ['shift'], function () {
    move_window({x: 0, y: 0, width: 0.8, height: 1.0});
});
wPrefix.addSuffix('p', [], function () {
    move_window({x: 0.1, y: 0, width: 0.9, height: 1.0});
});
wPrefix.addSuffix('p', ['shift'], function () {
    move_window({x: 0.2, y: 0, width: 0.8, height: 1.0});
});
wPrefix.addSuffix('s', [], function () {
    move_window_to_next_screen();
});
wPrefix.addSuffix('escape', [], function () {});
wPrefix.addSuffix('space', ['ctrl', 'alt', 'cmd'], function () {});

<|endoftext|>


<commit_before>//index.js
//获取应用实例
var app = getApp()
Page({
  data: {
    motto: 'coming soon!',
    userInfo: {}
  },
  //事件处理函数
  bindViewTap: function() {
    wx.navigateTo({
      url: '../logs/logs'
    })
  },
  onLoad: function () {
    console.log('onLoad')
    var that = this
    //调用应用实例的方法获取全局数据
    app.getUserInfo(function(userInfo){
      //更新数据
      that.setData({
        userInfo:userInfo
      })
    })
  }
})
<commit_msg>helloword<commit_after>//index.js
//获取应用实例
var app = getApp()
Page({
  data: {
    motto: 'coming soon! ',
    userInfo: {}
  },
  //事件处理函数
  bindViewTap: function() {
    wx.navigateTo({
      url: '../logs/logs'
    })
  },
  onLoad: function () {
    console.log('onLoad')
    var that = this
    //调用应用实例的方法获取全局数据
    app.getUserInfo(function(userInfo){
      //更新数据
      that.setData({
        userInfo:userInfo
      })
    })
  }
})
<|endoftext|>


<commit_before>"use strict";
var fs = require("fs"),
	path = require("path"),
	exec = require("child_process").exec;

var gpioAdmin = "gpio-admin",
	sysFsPath = "/sys/devices/virtual/gpio";

var pinMapping = {
	"3": 0,
	"5": 1,
	"7": 4,
	"8": 14,
	"10": 15,
	"11": 17,
	"12": 18,
	"13": 21,
	"15": 22,
	"16": 23,
	"18": 24,
	"19": 10,
	"21": 9,
	"22": 25,
	"23": 11,
	"24": 8,
	"26": 7
};

function isNumber(number) {
	return !isNaN(parseInt(number, 10));
}

function noop(){}

function handleExecResponse(method, pinNumber, callback) {
	return function(err, stdout, stderr) {
		if(err) {
			console.error("Error when trying to", method, "pin", pinNumber);
			console.error(stderr);
			callback(err);
		} else {
			callback();
		}
	}
}

function sanitizePinNumber(pinNumber) {
	if(!isNumber(pinNumber) || !isNumber(pinMapping[pinNumber])) {
		throw new Error("Pin number isn't valid");
	}

	return parseInt(pinNumber, 10);
}

function sanitizeDirection(direction) {
	direction = (direction || "").toLowerCase().trim();
	if(direction === "in" || direction === "input") {
		return "in";
	} else if(direction === "out" || direction === "output" || !direction) {
		return "out";
	} else {
		throw new Error("Direction must be 'input' or 'output'");
	}
}

var gpio = {
	open: function(pinNumber, direction, callback) {
		pinNumber = sanitizePinNumber(pinNumber);

		if(!callback && typeof direction === "function") {
			callback = direction;
			direction = "out";
		}

		direction = sanitizeDirection(direction);

		exec(gpioAdmin + " export " + pinMapping[pinNumber], handleExecResponse("open", pinNumber, function(err) {
			if(err) return (callback || noop)(err);

			gpio.setDirection(pinNumber, direction, callback);
		}));
	},

	setDirection: function(pinNumber, direction, callback) {
		pinNumber = sanitizePinNumber(pinNumber);
		direction = sanitizeDirection(direction);

		fs.writeFile(sysFsPath + "/gpio" + pinMapping[pinNumber] + "/direction", direction, callback);
	},

	getDirection: function(pinNumber, callback) {
		pinNumber = sanitizePinNumber(pinNumber);

		fs.readFile(sysFsPath + "/gpio" + pinMapping[pinNumber] + "/direction", "utf8", function(err, direction) {
			if(err) return done(err);
			callback(null, sanitizeDirection(direction.trim()));
		});
	},

	close: function(pinNumber, callback) {
		pinNumber = sanitizePinNumber(pinNumber);

		exec(gpioAdmin + " unexport " + pinMapping[pinNumber], handleExecResponse("close", pinNumber, callback || noop));
	},

	read: function(pinNumber, callback) {
		pinNumber = sanitizePinNumber(pinNumber);

		fs.readFile(sysFsPath + "/gpio" + pinMapping[pinNumber] + "/value", function(err, data) {
			if(err) return (callback || noop)(err);

			(callback || noop)(null, parseInt(data, 10));
		});
	},

	write: function(pinNumber, value, callback) {
		pinNumber = sanitizePinNumber(pinNumber);

		value = !!value?"1":"0";

		fs.writeFile(sysFsPath + "/gpio" + pinMapping[pinNumber] + "/value", value, "utf8", callback);
	}
};

gpio.export = gpio.open;
gpio.unexport = gpio.close;

module.exports = gpio;
<commit_msg>Fixed bug with error handling when setting direction.<commit_after>"use strict";
var fs = require("fs"),
	path = require("path"),
	exec = require("child_process").exec;

var gpioAdmin = "gpio-admin",
	sysFsPath = "/sys/devices/virtual/gpio";

var pinMapping = {
	"3": 0,
	"5": 1,
	"7": 4,
	"8": 14,
	"10": 15,
	"11": 17,
	"12": 18,
	"13": 21,
	"15": 22,
	"16": 23,
	"18": 24,
	"19": 10,
	"21": 9,
	"22": 25,
	"23": 11,
	"24": 8,
	"26": 7
};

function isNumber(number) {
	return !isNaN(parseInt(number, 10));
}

function noop(){}

function handleExecResponse(method, pinNumber, callback) {
	return function(err, stdout, stderr) {
		if(err) {
			console.error("Error when trying to", method, "pin", pinNumber);
			console.error(stderr);
			callback(err);
		} else {
			callback();
		}
	}
}

function sanitizePinNumber(pinNumber) {
	if(!isNumber(pinNumber) || !isNumber(pinMapping[pinNumber])) {
		throw new Error("Pin number isn't valid");
	}

	return parseInt(pinNumber, 10);
}

function sanitizeDirection(direction) {
	direction = (direction || "").toLowerCase().trim();
	if(direction === "in" || direction === "input") {
		return "in";
	} else if(direction === "out" || direction === "output" || !direction) {
		return "out";
	} else {
		throw new Error("Direction must be 'input' or 'output'");
	}
}

var gpio = {
	open: function(pinNumber, direction, callback) {
		pinNumber = sanitizePinNumber(pinNumber);

		if(!callback && typeof direction === "function") {
			callback = direction;
			direction = "out";
		}

		direction = sanitizeDirection(direction);

		exec(gpioAdmin + " export " + pinMapping[pinNumber], handleExecResponse("open", pinNumber, function(err) {
			if(err) return (callback || noop)(err);

			gpio.setDirection(pinNumber, direction, callback);
		}));
	},

	setDirection: function(pinNumber, direction, callback) {
		pinNumber = sanitizePinNumber(pinNumber);
		direction = sanitizeDirection(direction);

		fs.writeFile(sysFsPath + "/gpio" + pinMapping[pinNumber] + "/direction", direction, callback);
	},

	getDirection: function(pinNumber, callback) {
		pinNumber = sanitizePinNumber(pinNumber);

		fs.readFile(sysFsPath + "/gpio" + pinMapping[pinNumber] + "/direction", "utf8", function(err, direction) {
			if(err) return callback(err);
			callback(null, sanitizeDirection(direction.trim()));
		});
	},

	close: function(pinNumber, callback) {
		pinNumber = sanitizePinNumber(pinNumber);

		exec(gpioAdmin + " unexport " + pinMapping[pinNumber], handleExecResponse("close", pinNumber, callback || noop));
	},

	read: function(pinNumber, callback) {
		pinNumber = sanitizePinNumber(pinNumber);

		fs.readFile(sysFsPath + "/gpio" + pinMapping[pinNumber] + "/value", function(err, data) {
			if(err) return (callback || noop)(err);

			(callback || noop)(null, parseInt(data, 10));
		});
	},

	write: function(pinNumber, value, callback) {
		pinNumber = sanitizePinNumber(pinNumber);

		value = !!value?"1":"0";

		fs.writeFile(sysFsPath + "/gpio" + pinMapping[pinNumber] + "/value", value, "utf8", callback);
	}
};

gpio.export = gpio.open;
gpio.unexport = gpio.close;

module.exports = gpio;
<|endoftext|>


<commit_before>const WXAPI = require('apifm-wxapi')
const CONFIG = require('../../config.js')
const TOOLS = require('../../utils/tools.js')

//获取应用实例
var app = getApp()
Page({
  data: {
    inputVal: "", // 搜索框内容
    goodsRecommend: [], // 推荐商品
    kanjiaList: [], //砍价商品列表
    pingtuanList: [], //拼团商品列表

    loadingHidden: false, // loading
    selectCurrent: 0,
    categories: [],
    activeCategoryId: 0,
    goods: [],

    scrollTop: 0,
    loadingMoreHidden: true,

    coupons: [],

    curPage: 1,
    pageSize: 20,
    cateScrollTop: 0
  },

  tabClick: function(e) {
    wx.navigateTo({
      url: '/pages/goods/list?categoryId=' + e.currentTarget.id,
    })
  },
  toDetailsTap: function(e) {
    wx.navigateTo({
      url: "/pages/goods-details/index?id=" + e.currentTarget.dataset.id
    })
  },
  tapBanner: function(e) {
    if (e.currentTarget.dataset.id != 0) {
      wx.navigateTo({
        url: "/pages/goods-details/index?id=" + e.currentTarget.dataset.id
      })
    }
  },
  bindTypeTap: function(e) {
    this.setData({
      selectCurrent: e.index
    })
  },
  onLoad: function(e) {
    wx.showShareMenu({
      withShareTicket: true
    })
    const that = this
    // if (e && e.query && e.query.inviter_id) {
    //   wx.setStorageSync('referrer', e.query.inviter_id)
    // }
    if (e && e.scene) {
      const scene = decodeURIComponent(e.scene)
      if (scene) {
        wx.setStorageSync('referrer', scene.substring(11))
      }
    }
    wx.setNavigationBarTitle({
      title: wx.getStorageSync('mallName')
    })
    /**
     * 示例：
     * 调用接口封装方法
     */
    WXAPI.banners({
      type: 'index'
    }).then(function(res) {
      if (res.code == 700) {
        wx.showModal({
          title: '提示',
          content: '请在后台添加 banner 轮播图片，自定义类型填写 index',
          showCancel: false
        })
      } else {
        that.setData({
          banners: res.data
        });
      }
    }).catch(function(e) {
      wx.showToast({
        title: res.msg,
        icon: 'none'
      })
    })
    this.categories()
    WXAPI.goods({
      recommendStatus: 1
    }).then(res => {
      if (res.code === 0){
        that.setData({
          goodsRecommend: res.data
        })
      }
    })
    that.getCoupons()
    that.getNotice()
    that.kanjiaGoods()
    that.pingtuanGoods()
  },
  onShow: function(e){
    // 获取购物车数据，显示TabBarBadge
    TOOLS.showTabBarBadge();
  },
  async categories(){
    const res = await WXAPI.goodsCategory()
    let categories = [];
    if (res.code == 0) {
      const _categories = res.data.filter(ele => {
        return ele.level == 1
      })
      categories = categories.concat(_categories)
    }
    this.setData({
      categories: categories,
      activeCategoryId: 0,
      curPage: 1
    });
    this.getGoodsList(0);
  },
  onPageScroll(e) {
    let scrollTop = this.data.scrollTop
    this.setData({
      scrollTop: e.scrollTop
    })
  },
  getGoodsList: function(categoryId, append) {
    if (categoryId == 0) {
      categoryId = "";
    }
    var that = this;
    wx.showLoading({
      "mask": true
    })
    WXAPI.goods({
      categoryId: categoryId,
      nameLike: that.data.inputVal,
      page: this.data.curPage,
      pageSize: this.data.pageSize
    }).then(function(res) {
      wx.hideLoading()
      if (res.code == 404 || res.code == 700) {
        let newData = {
          loadingMoreHidden: false
        }
        if (!append) {
          newData.goods = []
        }
        that.setData(newData);
        return
      }
      let goods = [];
      if (append) {
        goods = that.data.goods
      }
      for (var i = 0; i < res.data.length; i++) {
        goods.push(res.data[i]);
      }
      that.setData({
        loadingMoreHidden: true,
        goods: goods,
      });
    })
  },
  getCoupons: function() {
    var that = this;
    WXAPI.coupons().then(function (res) {
      if (res.code == 0) {
        that.setData({
          coupons: res.data
        });
      }
    })
  },
  onShareAppMessage: function() {
    return {
      title: '"' + wx.getStorageSync('mallName') + '" ' + CONFIG.shareProfile,
      path: '/pages/index/index?inviter_id=' + wx.getStorageSync('uid')
    }
  },
  getNotice: function() {
    var that = this;
    WXAPI.noticeList({pageSize: 5}).then(function (res) {
      if (res.code == 0) {
        that.setData({
          noticeList: res.data
        });
      }
    })
  },
  onReachBottom: function() {
    this.setData({
      curPage: this.data.curPage + 1
    });
    this.getGoodsList(this.data.activeCategoryId, true)
  },
  onPullDownRefresh: function() {
    this.setData({
      curPage: 1
    });
    this.getGoodsList(this.data.activeCategoryId)
    wx.stopPullDownRefresh()
  },
  // 获取砍价商品
  async kanjiaGoods(){
    const res = await WXAPI.goods({
      kanjia: true
    });
    if (res.code == 0) {
      this.setData({
        kanjiaList: res.data
      })
    }
  },
  goCoupons: function (e) {
    wx.navigateTo({
      url: "/pages/coupons/index"
    })
  },
  pingtuanGoods(){ // 获取团购商品列表
    const _this = this
    WXAPI.goods({
      pingtuan: true
    }).then(res => {
      if (res.code === 0) {
        _this.setData({
          pingtuanList: res.data
        })
      }
    })
  },
  bindinput(e) {
    this.setData({
      inputVal: e.detail.value
    })
  },
  bindconfirm(e) {
    this.setData({
      inputVal: e.detail.value
    })
    wx.navigateTo({
      url: '/pages/goods/list?name=' + this.data.inputVal,
    })
  },
})<commit_msg>首页加载提示效果优化<commit_after>const WXAPI = require('apifm-wxapi')
const CONFIG = require('../../config.js')
const TOOLS = require('../../utils/tools.js')

//获取应用实例
var app = getApp()
Page({
  data: {
    inputVal: "", // 搜索框内容
    goodsRecommend: [], // 推荐商品
    kanjiaList: [], //砍价商品列表
    pingtuanList: [], //拼团商品列表

    loadingHidden: false, // loading
    selectCurrent: 0,
    categories: [],
    activeCategoryId: 0,
    goods: [],

    scrollTop: 0,
    loadingMoreHidden: true,

    coupons: [],

    curPage: 1,
    pageSize: 20,
    cateScrollTop: 0
  },

  tabClick: function(e) {
    wx.navigateTo({
      url: '/pages/goods/list?categoryId=' + e.currentTarget.id,
    })
  },
  toDetailsTap: function(e) {
    wx.navigateTo({
      url: "/pages/goods-details/index?id=" + e.currentTarget.dataset.id
    })
  },
  tapBanner: function(e) {
    if (e.currentTarget.dataset.id != 0) {
      wx.navigateTo({
        url: "/pages/goods-details/index?id=" + e.currentTarget.dataset.id
      })
    }
  },
  bindTypeTap: function(e) {
    this.setData({
      selectCurrent: e.index
    })
  },
  onLoad: function(e) {
    wx.showShareMenu({
      withShareTicket: true
    })
    const that = this
    // if (e && e.query && e.query.inviter_id) {
    //   wx.setStorageSync('referrer', e.query.inviter_id)
    // }
    if (e && e.scene) {
      const scene = decodeURIComponent(e.scene)
      if (scene) {
        wx.setStorageSync('referrer', scene.substring(11))
      }
    }
    wx.setNavigationBarTitle({
      title: wx.getStorageSync('mallName')
    })
    /**
     * 示例：
     * 调用接口封装方法
     */
    WXAPI.banners({
      type: 'index'
    }).then(function(res) {
      if (res.code == 700) {
        wx.showModal({
          title: '提示',
          content: '请在后台添加 banner 轮播图片，自定义类型填写 index',
          showCancel: false
        })
      } else {
        that.setData({
          banners: res.data
        });
      }
    }).catch(function(e) {
      wx.showToast({
        title: res.msg,
        icon: 'none'
      })
    })
    this.categories()
    WXAPI.goods({
      recommendStatus: 1
    }).then(res => {
      if (res.code === 0){
        that.setData({
          goodsRecommend: res.data
        })
      }
    })
    that.getCoupons()
    that.getNotice()
    that.kanjiaGoods()
    that.pingtuanGoods()
  },
  onShow: function(e){
    // 获取购物车数据，显示TabBarBadge
    TOOLS.showTabBarBadge();
  },
  async categories(){
    const res = await WXAPI.goodsCategory()
    let categories = [];
    if (res.code == 0) {
      const _categories = res.data.filter(ele => {
        return ele.level == 1
      })
      categories = categories.concat(_categories)
    }
    this.setData({
      categories: categories,
      activeCategoryId: 0,
      curPage: 1
    });
    this.getGoodsList(0);
  },
  onPageScroll(e) {
    let scrollTop = this.data.scrollTop
    this.setData({
      scrollTop: e.scrollTop
    })
  },
  async getGoodsList(categoryId, append) {
    if (categoryId == 0) {
      categoryId = "";
    }
    wx.showLoading({
      "mask": true
    })
    const res = await WXAPI.goods({
      categoryId: categoryId,
      nameLike: this.data.inputVal,
      page: this.data.curPage,
      pageSize: this.data.pageSize
    })
    wx.hideLoading()
    if (res.code == 404 || res.code == 700) {
      let newData = {
        loadingMoreHidden: false
      }
      if (!append) {
        newData.goods = []
      }
      this.setData(newData);
      return
    }
    let goods = [];
    if (append) {
      goods = this.data.goods
    }
    for (var i = 0; i < res.data.length; i++) {
      goods.push(res.data[i]);
    }
    this.setData({
      loadingMoreHidden: true,
      goods: goods,
    });
  },
  getCoupons: function() {
    var that = this;
    WXAPI.coupons().then(function (res) {
      if (res.code == 0) {
        that.setData({
          coupons: res.data
        });
      }
    })
  },
  onShareAppMessage: function() {
    return {
      title: '"' + wx.getStorageSync('mallName') + '" ' + CONFIG.shareProfile,
      path: '/pages/index/index?inviter_id=' + wx.getStorageSync('uid')
    }
  },
  getNotice: function() {
    var that = this;
    WXAPI.noticeList({pageSize: 5}).then(function (res) {
      if (res.code == 0) {
        that.setData({
          noticeList: res.data
        });
      }
    })
  },
  onReachBottom: function() {
    this.setData({
      curPage: this.data.curPage + 1
    });
    this.getGoodsList(this.data.activeCategoryId, true)
  },
  onPullDownRefresh: function() {
    this.setData({
      curPage: 1
    });
    this.getGoodsList(this.data.activeCategoryId)
    wx.stopPullDownRefresh()
  },
  // 获取砍价商品
  async kanjiaGoods(){
    const res = await WXAPI.goods({
      kanjia: true
    });
    if (res.code == 0) {
      this.setData({
        kanjiaList: res.data
      })
    }
  },
  goCoupons: function (e) {
    wx.navigateTo({
      url: "/pages/coupons/index"
    })
  },
  pingtuanGoods(){ // 获取团购商品列表
    const _this = this
    WXAPI.goods({
      pingtuan: true
    }).then(res => {
      if (res.code === 0) {
        _this.setData({
          pingtuanList: res.data
        })
      }
    })
  },
  bindinput(e) {
    this.setData({
      inputVal: e.detail.value
    })
  },
  bindconfirm(e) {
    this.setData({
      inputVal: e.detail.value
    })
    wx.navigateTo({
      url: '/pages/goods/list?name=' + this.data.inputVal,
    })
  },
})<|endoftext|>


<commit_before>///import core
///import commands/inserthtml.js
///commands 插入公式
///commandsName  formula
///commandsTitle  插入公式
///commandsDialog  dialogs\formula\formula.html

UE.plugins['formula'] = function () {
    var me = this;
    me._formulaid = 0;

    var filter = function (node) {
        return domUtils.findParent(node, function (node) {
            return node.nodeType == 1 && node.tagName.toLowerCase() == 'span' && domUtils.hasClass(node, 'mathquill-rendered-math')
        }, true);
    };

    var fnBlock = function (node) {
        return domUtils.findParent(node, function (node) {
            return node.nodeType == 1 && node.tagName.toLowerCase() == 'p' && domUtils.hasClass(node, 'formulaBlock')
        }, true);
    };

    var setCursorPos = function (range, start, end, callback) {
        if (start && end && start === end) {
            if (start.nextSibling) {
                range.setStart(start.nextSibling, 0)
            } else {
                if (start.previousSibling) {
                    range.setStartAtLast(start.previousSibling)
                } else {
                    var p = me.document.createElement('p');
                    domUtils.fillNode(me.document, p);
                    range.setStart(p, 0)
                }
            }
            range.setCursor(false, true);
            callback();
        }
    };

    function toInline(node, ignorePre, ignoreNext) {
        function merge(rtl, start, node) {
            var next;
            if ((next = node[rtl]) && !domUtils.isBookmarkNode(next) && next.nodeType == 1) {
                while (next.firstChild) {
                    if (start == 'firstChild') {
                        node.insertBefore(next.lastChild, node.firstChild);
                    }
                    else {
                        node.appendChild(next.firstChild);
                    }
                }
                domUtils.remove(next);
            }
        }

        !ignorePre && merge('previousSibling', 'firstChild', node);
        !ignoreNext && merge('nextSibling', 'lastChild', node);
    }

    me.addListener("ready", function () {
        utils.loadFile(me.document, {
            id:"mathquill_css",
            tag:"link",
            rel:"stylesheet",
            type:"text/css",
            href:me.options.formulaCssUrl || me.options.UEDITOR_HOME_URL + "third-party/mathquill/mathquill.css"
        });
        utils.loadFile(me.document, {
            id:"jquery.min_js",
            src:me.options.jqueryUrl || me.options.UEDITOR_HOME_URL + "third-party/mathquill/jquery.min.js",
            tag:"script",
            type:"text/javascript",
            defer:"defer"
        }, function () {
            utils.loadFile(me.document, {
                id:"mathquill_js",
                src:me.options.formulaJsUrl || me.options.UEDITOR_HOME_URL + "third-party/mathquill/mathquill.min.js",
                tag:"script",
                type:"text/javascript",
                defer:"defer"
            });
        });
    });

    me.addListener("afterbackspace", function (types, evt) {
        if (!browser.ie) {
            var rng = me.selection.getRange();
            var formula = rng.startContainer.childNodes[rng.startOffset - 1];
            if (formula) {
                if (domUtils.hasClass(formula, "mathquill-rendered-math")) {
                    var bk = rng.createBookmark();
                    domUtils.remove(formula);
                    rng.moveToBookmark(bk).select();
                    evt.preventDefault();
                }
            }
        }
    });

    me.addListener("keydown", function (types, evt) {
        if (!browser.ie) {
            var keyCode = evt.keyCode || evt.which;
            if (keyCode == 46) {
                var rng = me.selection.getRange();
                var formula = domUtils.getNextDomNode(rng.startContainer);
                if (formula) {
                    if (domUtils.hasClass(formula, "mathquill-rendered-math")) {
                        var bk = rng.createBookmark();
                        domUtils.remove(formula);
                        rng.moveToBookmark(bk).select();
                        evt.preventDefault();
                    }
                }
            }
        }
    });

    function addFillChar(node) {
        var previous = node.previousSibling,
            next = node.nextSibling;

        if (!previous || !domUtils.isFillChar(previous)) {
            node.parentNode.insertBefore(document.createTextNode(domUtils.fillChar), node);
        }
        if (!next || !domUtils.isFillChar(next)) {
            domUtils.insertAfter(node, document.createTextNode(domUtils.fillChar));
        }
    }

    function queryState() {
        try {
            var rng = this.selection.getRange();
            var start = filter(rng.startContainer);
            end = filter(rng.endContainer);
            if (start && end && start == end) {
                addFillChar(start);
                return 1;
            } else {
                return 0;
            }
        }
        catch (e) {
            return 0;
        }
    }

    //不需要判断highlight的command列表
    me.notNeedmathQuery = {
        help:1,
        undo:1,
        redo:1,
        source:1,
        print:1,
        searchreplace:1,
        fullscreen:1,
        autotypeset:1,
        pasteplain:1,
        preview:1,
        insertparagraph:1,
        elementpath:1,
        formula:1,
        formulainline:1,
        formulablock:1,
        formuladelete:1,
        formualmergeup:1
    };

    //将queyCommamndState重置
    var orgQuery = me.queryCommandState;
    me.queryCommandState = function (cmd) {
        if (!me.notNeedmathQuery[cmd.toLowerCase()] && queryState.call(this) == 1) {
            return -1;
        }
        return orgQuery.apply(this, arguments)
    };

    me.addListener("beforegetcontent beforegetscene", function () {
        if (!me.window || !me.window.$)return;
        utils.each(domUtils.getElementsByTagName(me.body, 'span', 'mathquill-rendered-math'), function (di) {
            var id = di.getAttribute("formulaid");
            var txt = me.window.$("[formulaid=" + id + "]").mathquill("latex");
            var span = domUtils.createElement(me.document, 'span', {
                'class':'mathquill-embedded-latex',
                'formulaid':id
            });
            span.appendChild(me.document.createTextNode(txt));
            di.parentNode.replaceChild(span, di);
        });
    });

    me.addListener("aftergetcontent aftersetcontent aftergetscene", function () {
        if (!me.window || !me.window.$)return;
        var list = me.window.$(".mathquill-embedded-latex"), obj = {};
        if (list.length) {
            for (var i = 0, len = list.length; i < len; i++) {
                obj[list[i].getAttribute("formulaid")] = list[i].innerText || list[i].textContent || list[i].nodeValue;
            }
            for (var attr in obj) {
                me.window.$("[formulaid=" + attr + "]")
                    .html("")
                    .mathquill("editable")
                    .mathquill("write", obj[attr].replace("{/}", "\\"));
            }
        }
    });

    me.commands['formula'] = {
        execCommand:function (cmdName, txt) {
            var rng = me.selection.getRange();
            var start = filter(rng.startContainer);
            var end = filter(rng.endContainer);
            var id = 0;

            if (start && end && start == end) {
                id = start.getAttribute("formulaid");
            } else {
                var doc = me.document;
                var span = domUtils.createElement(doc, "span", {
                    formulaid:me._formulaid
                });
                span.className = "mathquill-editable";
                span.appendChild(doc.createTextNode(txt));
                me.execCommand('inserthtml', span.outerHTML);

                id = me._formulaid;
                me.window.$("[formulaid=" + id + "]").html("").mathquill('editable');
                me._formulaid += 1;
            }

            var selector = "[formulaid=" + id + "]";
            me.window.$(selector).focus().mathquill("write", txt.replace("{/}", "\\"));
            rng.setStartAfter(me.window.$(selector)[0]).collapse(true);
            rng.setCursor();
        },
        queryCommandState:function () {
            return queryState.call(me);
        }
    };

    me.commands['formulainline'] = {
        execCommand:function () {
            var range = me.selection.getRange();
            range.adjustmentBoundary();
            var start = fnBlock(range.startContainer),
                end = fnBlock(range.endContainer);

            setCursorPos(range, start, end, function () {
                if (start.previousSibling || start.nextSibling || /li/i.test(start.parentNode.tagName)) {
                    toInline(start);
                }
                else {
                    var p = document.createElement("p");
                    p.appendChild(start);
                    start.parentNode.replaceChild(p, start);
                }
                domUtils.removeAttributes(start, ["style", "class"]);
            });
        },
        queryCommandState:function () {
            try {
                var range = this.selection.getRange();
                var start = fnBlock(range.startContainer),
                    end = fnBlock(range.startContainer);

                return start && end && start == end ? 0 : -1;
            }
            catch (e) {
                return -1;
            }
        }
    };

    me.commands['formulablock'] = {
        execCommand:function () {
            var range = me.selection.getRange();
            range.adjustmentBoundary();
            var start = filter(range.startContainer),
                end = filter(range.endContainer);

            setCursorPos(range, start, end, function () {
                domUtils.breakParent(start, domUtils.findParent(start, function (node) {
                    return node.nodeType == 1 && node.tagName.toLowerCase() == 'p'
                }, false));

                var p = domUtils.createElement(document, "p", {
                    "style":"text-align:center",
                    "class":"formulaBlock"
                });
                start.parentNode.replaceChild(p, start);
                p.appendChild(start);
            });
        },
        queryCommandState:function () {
            try {
                var range = me.selection.getRange();
                var start = filter(range.startContainer),
                    end = filter(range.endContainer);

                if (start && end && start == end) {
                    var p = fnBlock(range.startContainer);
                    return p ? -1 : 0;
                } else {
                    return -1;
                }

            }
            catch (e) {
                return -1;
            }
        }
    };

    me.commands["formuladelete"] = {
        execCommand:function () {
            var range = me.selection.getRange();
            var start = filter(range.startContainer),
                end = filter(range.endContainer);

            setCursorPos(range, start, end, function () {
                domUtils.remove(start);
            });
        },
        queryCommandState:function () {
            try {
                var rng = me.selection.getRange();
                var start = filter(rng.startContainer);
                var end = filter(rng.endContainer);
                return start && end && start == end ? 0 : -1;
            } catch (e) {
                return -1;
            }

        }
    }

    me.commands["formualmergeup"] = {
        execCommand:function () {
            var range = me.selection.getRange();
            var start = filter(range.startContainer),
                end = filter(range.endContainer);

            setCursorPos(range, start, end, function () {
                var p = domUtils.findParent(start, function (node) {
                    return node.nodeType == 1 && node.tagName.toLowerCase() == 'p';
                });
                var cur = start.previousSibling;
                while (cur) {
                    if (!domUtils.isFillChar(cur) && domUtils.isBr(cur)) {
                        domUtils.remove(cur);
                        break;
                    }else{
                        cur=cur.previousSibling;
                    }
                }
                domUtils.mergeSibling(p, false, true);
            });
        },
        queryCommandState:function () {
            try {
                var rng = me.selection.getRange();
                var start = filter(rng.startContainer);
                var end = filter(rng.endContainer);
                if (start && end && start == end) {
                    if (fnBlock(start)) {
                        return -1;
                    } else {
                        return 0;
                    }
                } else {
                    return -1;
                }
            } catch (e) {
                return -1;
            }

        }
    }
}<commit_msg>New changelist<commit_after>///import core
///import commands/inserthtml.js
///commands 插入公式
///commandsName  formula
///commandsTitle  插入公式
///commandsDialog  dialogs\formula\formula.html

UE.plugins['formula'] = function () {
    var me = this;
    me._formulaid = 0;

    var filter = function (node) {
        return domUtils.findParent(node, function (node) {
            return node.nodeType == 1 && node.tagName.toLowerCase() == 'span' && domUtils.hasClass(node, 'mathquill-rendered-math')
        }, true);
    };

    var fnBlock = function (node) {
        return domUtils.findParent(node, function (node) {
            return node.nodeType == 1 && node.tagName.toLowerCase() == 'p' && domUtils.hasClass(node, 'formulaBlock')
        }, true);
    };

    var setCursorPos = function (range, start, end, callback) {
        if (start && end && start === end) {
            if (start.nextSibling) {
                range.setStart(start.nextSibling, 0)
            } else {
                if (start.previousSibling) {
                    range.setStartAtLast(start.previousSibling)
                } else {
                    var p = me.document.createElement('p');
                    domUtils.fillNode(me.document, p);
                    range.setStart(p, 0)
                }
            }
            range.setCursor(false, true);
            callback();
        }
    };

    function toInline(node, ignorePre, ignoreNext) {
        function merge(rtl, start, node) {
            var next;
            if ((next = node[rtl]) && !domUtils.isBookmarkNode(next) && next.nodeType == 1) {
                while (next.firstChild) {
                    if (start == 'firstChild') {
                        node.insertBefore(next.lastChild, node.firstChild);
                    }
                    else {
                        node.appendChild(next.firstChild);
                    }
                }
                domUtils.remove(next);
            }
        }

        !ignorePre && merge('previousSibling', 'firstChild', node);
        !ignoreNext && merge('nextSibling', 'lastChild', node);
    }

    me.addListener("ready", function () {
        utils.loadFile(me.document, {
            id:"mathquill_css",
            tag:"link",
            rel:"stylesheet",
            type:"text/css",
            href:me.options.formulaCssUrl || me.options.UEDITOR_HOME_URL + "third-party/mathquill/mathquill.css"
        });
        utils.loadFile(me.document, {
            id:"jquery.min_js",
            src:me.options.jqueryUrl || me.options.UEDITOR_HOME_URL + "third-party/mathquill/jquery.min.js",
            tag:"script",
            type:"text/javascript",
            defer:"defer"
        }, function () {
            utils.loadFile(me.document, {
                id:"mathquill_js",
                src:me.options.formulaJsUrl || me.options.UEDITOR_HOME_URL + "third-party/mathquill/mathquill.min.js",
                tag:"script",
                type:"text/javascript",
                defer:"defer"
            });
        });
    });

    me.addListener("afterbackspace", function (types, evt) {
        if (!browser.ie) {
            var rng = me.selection.getRange();
            var formula = rng.startContainer.childNodes[rng.startOffset - 1];
            if (formula) {
                if (domUtils.hasClass(formula, "mathquill-rendered-math")) {
                    var bk = rng.createBookmark();
                    domUtils.remove(formula);
                    rng.moveToBookmark(bk).select();
                    evt.preventDefault();
                }
            }
        }
    });

    me.addListener("keydown", function (types, evt) {
        if (!browser.ie) {
            var keyCode = evt.keyCode || evt.which;
            if (keyCode == 46) {
                var rng = me.selection.getRange();
                var formula = domUtils.getNextDomNode(rng.startContainer);
                if (formula) {
                    if (domUtils.hasClass(formula, "mathquill-rendered-math")) {
                        var bk = rng.createBookmark();
                        domUtils.remove(formula);
                        rng.moveToBookmark(bk).select();
                        evt.preventDefault();
                    }
                }
            }
        }
    });

    function addFillChar(node) {
        var previous = node.previousSibling,
            next = node.nextSibling;

        if (!previous || !domUtils.isFillChar(previous)) {
            node.parentNode.insertBefore(document.createTextNode(domUtils.fillChar), node);
        }
        if (!next || !domUtils.isFillChar(next)) {
            domUtils.insertAfter(node, document.createTextNode(domUtils.fillChar));
        }
    }

    function queryState() {
        try {
            var rng = this.selection.getRange();
            var start = filter(rng.startContainer);
            end = filter(rng.endContainer);
            if (start && end && start == end) {
                addFillChar(start);
                return 1;
            } else {
                return 0;
            }
        }
        catch (e) {
            return 0;
        }
    }

    //不需要判断highlight的command列表
    me.notNeedmathQuery = {
        help:1,
        undo:1,
        redo:1,
        source:1,
        print:1,
        searchreplace:1,
        fullscreen:1,
        autotypeset:1,
        pasteplain:1,
        preview:1,
        insertparagraph:1,
        elementpath:1,
        formula:1,
        formulainline:1,
        formulablock:1,
        formuladelete:1,
        formualmergeup:1
    };

    //将queyCommamndState重置
    var orgQuery = me.queryCommandState;
    me.queryCommandState = function (cmd) {
        if (!me.notNeedmathQuery[cmd.toLowerCase()] && queryState.call(this) == 1) {
            return -1;
        }
        return orgQuery.apply(this, arguments)
    };

    me.addListener("beforegetcontent beforegetscene", function () {
        if (!me.window || !me.window.$)return;
        utils.each(domUtils.getElementsByTagName(me.body, 'span', 'mathquill-rendered-math'), function (di) {
            var id = di.getAttribute("formulaid");
            var txt = me.window.$("[formulaid=" + id + "]").mathquill("latex");
            var span = domUtils.createElement(me.document, 'span', {
                'class':'mathquill-embedded-latex',
                'formulaid':id
            });
            span.appendChild(me.document.createTextNode(txt));
            di.parentNode.replaceChild(span, di);
        });
    });

    me.addListener("aftergetcontent aftersetcontent aftergetscene", function () {
        if (!me.window || !me.window.$)return;
        var list = me.window.$(".mathquill-embedded-latex"), obj = {};
        if (list.length) {
            for (var i = 0, len = list.length; i < len; i++) {
                obj[list[i].getAttribute("formulaid")] = list[i].innerText || list[i].textContent || list[i].nodeValue;
            }
            for (var attr in obj) {
                me.window.$("[formulaid=" + attr + "]")
                    .html("")
                    .mathquill("editable")
                    .mathquill("write", obj[attr].replace("{/}", "\\"));
            }
        }
    });

    me.commands['formula'] = {
        execCommand:function (cmdName, txt) {
            var rng = me.selection.getRange();
            var start = filter(rng.startContainer);
            var end = filter(rng.endContainer);
            var id = 0;

            if (start && end && start == end) {
                id = start.getAttribute("formulaid");
            } else {
                var doc = me.document;
                var span = domUtils.createElement(doc, "span", {
                    formulaid:me._formulaid
                });
                span.className = "mathquill-editable";
                span.appendChild(doc.createTextNode(txt));
                me.execCommand('inserthtml', span.outerHTML);

                id = me._formulaid;
                me.window.$("[formulaid=" + id + "]").html("").mathquill('editable');
                me._formulaid += 1;
            }

            var selector = "[formulaid=" + id + "]";
            me.window.$(selector).focus().mathquill("write", txt.replace("{/}", "\\"));
            rng.setStartAfter(me.window.$(selector)[0]).collapse(true);
            rng.setCursor();
        },
        queryCommandState:function () {
            return queryState.call(me);
        }
    };

    me.commands['formulainline'] = {
        execCommand:function () {
            var range = me.selection.getRange();
            range.adjustmentBoundary();
            var start = fnBlock(range.startContainer),
                end = fnBlock(range.endContainer);

            setCursorPos(range, start, end, function () {
                if (start.previousSibling || start.nextSibling || /li/i.test(start.parentNode.tagName)) {
                    toInline(start);
                }
                else {
                    var p = document.createElement("p");
                    p.appendChild(start);
                    start.parentNode.replaceChild(p, start);
                }
                domUtils.removeAttributes(start, ["style", "class"]);
            });
        },
        queryCommandState:function () {
            try {
                var range = this.selection.getRange();
                var start = fnBlock(range.startContainer),
                    end = fnBlock(range.startContainer);

                return start && end && start == end ? 0 : -1;
            }
            catch (e) {
                return -1;
            }
        }
    };

    me.commands['formulablock'] = {
        execCommand:function () {
            var range = me.selection.getRange();
            range.adjustmentBoundary();
            var start = filter(range.startContainer),
                end = filter(range.endContainer);

            setCursorPos(range, start, end, function () {
                domUtils.breakParent(start, domUtils.findParent(start, function (node) {
                    return node.nodeType == 1 && node.tagName.toLowerCase() == 'p'
                }, false));

                var p = domUtils.createElement(document, "p", {
                    "style":"text-align:center",
                    "class":"formulaBlock"
                });
                start.parentNode.replaceChild(p, start);
                p.appendChild(start);
            });
        },
        queryCommandState:function () {
            try {
                var range = me.selection.getRange();
                var start = filter(range.startContainer),
                    end = filter(range.endContainer);

                if (start && end && start == end) {
                    var p = fnBlock(range.startContainer);
                    return p ? -1 : 0;
                } else {
                    return -1;
                }

            }
            catch (e) {
                return -1;
            }
        }
    };

    me.commands["formuladelete"] = {
        execCommand:function () {
            var range = me.selection.getRange();
            var start = filter(range.startContainer),
                end = filter(range.endContainer);

            setCursorPos(range, start, end, function () {
                domUtils.remove(start);
            });
        },
        queryCommandState:function () {
            try {
                var rng = me.selection.getRange();
                var start = filter(rng.startContainer);
                var end = filter(rng.endContainer);
                return start && end && start == end ? 0 : -1;
            } catch (e) {
                return -1;
            }

        }
    }

    me.commands["formualmergeup"] = {
        execCommand:function () {
            var range = me.selection.getRange();
            var start = filter(range.startContainer),
                end = filter(range.endContainer);

            setCursorPos(range, start, end, function () {
                var p = domUtils.findParent(start, function (node) {
                    return node.nodeType == 1 && node.tagName.toLowerCase() == 'p';
                });
                var cur = start.previousSibling;
                while (cur) {
                    if (!domUtils.isFillChar(cur) && domUtils.isBr(cur)) {
                        domUtils.remove(cur);
                        break;
                    } else {
                        cur = cur.previousSibling;
                    }
                }

                domUtils.mergeSibling(p, false, true);
            });
        },
        queryCommandState:function () {
            try {
                var rng = me.selection.getRange();
                var li = domUtils.findParent(rng.startContainer, function (node) {
                    return node.nodeType == 1 && node.tagName.toLowerCase() == 'li';
                }, true);

                if (!li) {
                    var start = filter(rng.startContainer);
                    var end = filter(rng.endContainer);
                    if (start && end && start == end) {
                        if (fnBlock(start)) {
                            return -1;
                        } else {
                            return 0;
                        }
                    } else {
                        return -1;
                    }
                }

            } catch (e) {
                return -1;
            }

        }
    }
}<|endoftext|>


<commit_before>module.exports = {

//---------------------------------------------------------------------
// Action Name
//
// This is the name of the action displayed in the editor.
//---------------------------------------------------------------------

name: "Send Message",

//---------------------------------------------------------------------
// Action Section
//
// This is the section the action will fall into.
//---------------------------------------------------------------------

section: "Messaging",

// Who made the mod (If not set, defaults to "DBM Mods")
author: "DBM, Lasse & NetLuis",

// The version of the mod (Defaults to 1.0.0)
version: "1.9.4", //Added in 1.9.4

// A short description to show on the mod line for this mod (Must be on a single line)
short_description: "Added If Message Delivery Fails option.",

//---------------------------------------------------------------------
// Action Subtitle
//
// This function generates the subtitle displayed next to the name.
//---------------------------------------------------------------------

subtitle: function(data) {
	const channels = ['Same Channel', 'Command Author', 'Mentioned User', 'Mentioned Channel', 'Default Channel', 'Temp Variable', 'Server Variable', 'Global Variable'];
	return `${channels[parseInt(data.channel)]}: "${data.message.replace(/[\n\r]+/, '')}"`;
},

//---------------------------------------------------------------------
// Action Storage Function
//
// Stores the relevant variable info for the editor.
//---------------------------------------------------------------------

variableStorage: function(data, varType) {
	const type = parseInt(data.storage);
	if(type !== varType) return;
	return ([data.varName2, 'Message']);
},

//---------------------------------------------------------------------
// Action Fields
//
// These are the fields for the action. These fields are customized
// by creating elements with corresponding IDs in the HTML. These
// are also the names of the fields stored in the action's JSON data.
//---------------------------------------------------------------------

fields: ["channel", "varName", "message", "storage", "varName2", "iffalse", "iffalseVal"],

//---------------------------------------------------------------------
// Command HTML
//
// This function returns a string containing the HTML used for
// editting actions.
//
// The "isEvent" parameter will be true if this action is being used
// for an event. Due to their nature, events lack certain information,
// so edit the HTML to reflect this.
//
// The "data" parameter stores constants for select elements to use.
// Each is an array: index 0 for commands, index 1 for events.
// The names are: sendTargets, members, roles, channels,
//                messages, servers, variables
//---------------------------------------------------------------------

html: function(isEvent, data) {
	return `

This action has been modified by DBM Mods.

		Send To:

		<select id="channel" class="round" onchange="glob.sendTargetChange(this, 'varNameContainer')">
			${data.sendTargets[isEvent ? 1 : 0]}
		</select>

		Variable Name:

		<input id="varName" class="round" type="text" list="variableList">

	Message:

	<textarea id="message" rows="9" placeholder="Insert message here..." style="width: 99%; font-family: monospace; white-space: nowrap; resize: none;"></textarea>

		Store In:

		<select id="storage" class="round" onchange="glob.variableChange(this, 'varNameContainer2')">
			${data.variables[0]}
		</select>

		Variable Name:

		<input id="varName2" class="round" type="text">

            If Message Delivery Fails:

            <select id="iffalse" class="round" onchange="glob.onChangeFalse(this)">
				<option value="0" selected>Continue Actions</option>
				<option value="1">Stop Action Sequence</option>
				<option value="2">Jump To Action</option>
				<option value="3">Skip Next Actions</option>
		 </select>

Action Number:
<input id="iffalseVal" class="round" type="text">
`;
},

//---------------------------------------------------------------------
// Action Editor Init Code
//
// When the HTML is first applied to the action editor, this code
// is also run. This helps add modifications or setup reactionary
// functions for the DOM elements.
//---------------------------------------------------------------------

init: function() {
	const {glob, document} = this;

	glob.sendTargetChange(document.getElementById('channel'), 'varNameContainer');
	glob.variableChange(document.getElementById('storage'), 'varNameContainer2');
	glob.onChangeFalse(document.getElementById('iffalse'));
},

//---------------------------------------------------------------------
// Action Bot Function
//
// This is the function for the action within the Bot's Action class.
// Keep in mind event calls won't have access to the "msg" parameter,
// so be sure to provide checks for variable existance.
//---------------------------------------------------------------------

action: function(cache) {
	const data = cache.actions[cache.index];
	const server = cache.server;
	const msg = cache.msg;
	const channel = parseInt(data.channel);
	const message = data.message;
	if(channel === undefined || message === undefined) return;
	const varName = this.evalMessage(data.varName, cache);
	const target = this.getSendTarget(channel, varName, cache);
	if(Array.isArray(target)) {
		this.callListFunc(target, 'send', [this.evalMessage(message, cache)]).then(function(resultMsg) {
			const varName2 = this.evalMessage(data.varName2, cache);
			const storage = parseInt(data.storage);
			this.storeValue(resultMsg, storage, varName2, cache);
			this.callNextAction(cache);
		}.bind(this));
	} else if(target && target.send) {
		target.send(this.evalMessage(message, cache)).then(function(resultMsg) {
			const varName2 = this.evalMessage(data.varName2, cache);
			const storage = parseInt(data.storage);
			this.storeValue(resultMsg, storage, varName2, cache);
			this.callNextAction(cache);
		}.bind(this)).catch(err => {
			if(err.message == ('Cannot send messages to this user')) {
				this.executeResults(false, data, cache);
			} else {
			this.displayError.bind(this, data, cache)}
		});
	} else {
		this.callNextAction(cache);
	}
},

//---------------------------------------------------------------------
// Action Bot Mod
//
// Upon initialization of the bot, this code is run. Using the bot's
// DBM namespace, one can add/modify existing functions if necessary.
// In order to reduce conflictions between mods, be sure to alias
// functions you wish to overwrite.
//---------------------------------------------------------------------

mod: function(DBM) {
}

}; // End of module
<commit_msg>Update send_message.js<commit_after>module.exports = {

//---------------------------------------------------------------------
// Action Name
//
// This is the name of the action displayed in the editor.
//---------------------------------------------------------------------

name: "Send Message",

//---------------------------------------------------------------------
// Action Section
//
// This is the section the action will fall into.
//---------------------------------------------------------------------

section: "Messaging",

// Who made the mod (If not set, defaults to "DBM Mods")
author: "DBM, Lasse & NetLuis",

// The version of the mod (Defaults to 1.0.0)
version: "1.9.4", //Added in 1.9.4

// A short description to show on the mod line for this mod (Must be on a single line)
short_description: "Added If Message Delivery Fails option.",

//---------------------------------------------------------------------
// Action Subtitle
//
// This function generates the subtitle displayed next to the name.
//---------------------------------------------------------------------

subtitle: function(data) {
	const channels = ['Same Channel', 'Command Author', 'Mentioned User', 'Mentioned Channel', 'Default Channel (Top Channel)', 'Temp Variable', 'Server Variable', 'Global Variable'];
	return `${channels[parseInt(data.channel)]}: "${data.message.replace(/[\n\r]+/, '')}"`;
},

//---------------------------------------------------------------------
// Action Storage Function
//
// Stores the relevant variable info for the editor.
//---------------------------------------------------------------------

variableStorage: function(data, varType) {
	const type = parseInt(data.storage);
	if(type !== varType) return;
	return ([data.varName2, 'Message']);
},

//---------------------------------------------------------------------
// Action Fields
//
// These are the fields for the action. These fields are customized
// by creating elements with corresponding IDs in the HTML. These
// are also the names of the fields stored in the action's JSON data.
//---------------------------------------------------------------------

fields: ["channel", "varName", "message", "storage", "varName2", "iffalse", "iffalseVal"],

//---------------------------------------------------------------------
// Command HTML
//
// This function returns a string containing the HTML used for
// editting actions.
//
// The "isEvent" parameter will be true if this action is being used
// for an event. Due to their nature, events lack certain information,
// so edit the HTML to reflect this.
//
// The "data" parameter stores constants for select elements to use.
// Each is an array: index 0 for commands, index 1 for events.
// The names are: sendTargets, members, roles, channels,
//                messages, servers, variables
//---------------------------------------------------------------------

html: function(isEvent, data) {
	return `

This action has been modified by DBM Mods.

		Send To:

		<select id="channel" class="round" onchange="glob.sendTargetChange(this, 'varNameContainer')">
			${data.sendTargets[isEvent ? 1 : 0]}
		</select>

		Variable Name:

		<input id="varName" class="round" type="text" list="variableList">

	Message:

	<textarea id="message" rows="9" placeholder="Insert message here..." style="width: 99%; font-family: monospace; white-space: nowrap; resize: none;"></textarea>

		Store In:

		<select id="storage" class="round" onchange="glob.variableChange(this, 'varNameContainer2')">
			${data.variables[0]}
		</select>

		Variable Name:

		<input id="varName2" class="round" type="text">

            If Message Delivery Fails:

            <select id="iffalse" class="round" onchange="glob.onChangeFalse(this)">
				<option value="0" selected>Continue Actions</option>
				<option value="1">Stop Action Sequence</option>
				<option value="2">Jump To Action</option>
				<option value="3">Skip Next Actions</option>
		 </select>

Action Number:
<input id="iffalseVal" class="round" type="text">
`;
},

//---------------------------------------------------------------------
// Action Editor Init Code
//
// When the HTML is first applied to the action editor, this code
// is also run. This helps add modifications or setup reactionary
// functions for the DOM elements.
//---------------------------------------------------------------------

init: function() {
	const {glob, document} = this;

	glob.sendTargetChange(document.getElementById('channel'), 'varNameContainer');
	glob.variableChange(document.getElementById('storage'), 'varNameContainer2');
	glob.onChangeFalse(document.getElementById('iffalse'));
},

//---------------------------------------------------------------------
// Action Bot Function
//
// This is the function for the action within the Bot's Action class.
// Keep in mind event calls won't have access to the "msg" parameter,
// so be sure to provide checks for variable existance.
//---------------------------------------------------------------------

action: function(cache) {
	const data = cache.actions[cache.index];
	const server = cache.server;
	const msg = cache.msg;
	const channel = parseInt(data.channel);
	const message = data.message;
	if(channel === undefined || message === undefined) return;
	const varName = this.evalMessage(data.varName, cache);
	const target = this.getSendTarget(channel, varName, cache);
	if(Array.isArray(target)) {
		this.callListFunc(target, 'send', [this.evalMessage(message, cache)]).then(function(resultMsg) {
			const varName2 = this.evalMessage(data.varName2, cache);
			const storage = parseInt(data.storage);
			this.storeValue(resultMsg, storage, varName2, cache);
			this.callNextAction(cache);
		}.bind(this));
	} else if(target && target.send) {
		target.send(this.evalMessage(message, cache)).then(function(resultMsg) {
			const varName2 = this.evalMessage(data.varName2, cache);
			const storage = parseInt(data.storage);
			this.storeValue(resultMsg, storage, varName2, cache);
			this.callNextAction(cache);
		}.bind(this)).catch(err => {
			if(err.message == ('Cannot send messages to this user')) {
				this.executeResults(false, data, cache);
			} else {
			this.displayError.bind(this, data, cache)}
		});
	} else {
		this.callNextAction(cache);
	}
},

//---------------------------------------------------------------------
// Action Bot Mod
//
// Upon initialization of the bot, this code is run. Using the bot's
// DBM namespace, one can add/modify existing functions if necessary.
// In order to reduce conflictions between mods, be sure to alias
// functions you wish to overwrite.
//---------------------------------------------------------------------

mod: function(DBM) {
}

}; // End of module
<|endoftext|>