<commit_before>import React from "react";
import PropTypes from "prop-types";
import glamorous from "glamorous";
import stripIndent from "strip-indent";
import { highlight } from "highlight.js";
import * as s from "../common/styles.js";

//
// Article wrapper
//

export class ArticleWrapper extends React.Component {
  static propTypes = {
    children: PropTypes.node.isRequired
  };

  render() {
    return <WrapperStyled>{this.props.children}</WrapperStyled>;
  }
}

const WrapperStyled = glamorous.div({
  "> *:first-child": {
    marginTop: 0
  }
});

//
// Texts
//

// .Article-content em {
//   font-style: italic;
// }

// .Article-content mark {
//   background-color: var(--color-yellow);
// }

// .Article-content s {
//   text-decoration: line-through;
// }

export class P extends React.Component {
  static propTypes = {
    children: PropTypes.node.isRequired
  };

  render() {
    return <ParagraphStyled>{this.props.children}</ParagraphStyled>;
  }
}

const classNameParagraph = "article-paragraph";

const ParagraphStyled = glamorous.p(classNameParagraph, {
  ...s.fonts.paragraph,
  marginTop: s.dimensions.paragraphSpacing
});

export class Bold extends React.Component {
  static propTypes = {
    children: PropTypes.string.isRequired
  };

  render() {
    return <BoldStyled>{this.props.children}</BoldStyled>;
  }
}

const BoldStyled = glamorous.strong({
  fontWeight: "bold"
});

// TODO: probably not used?
// export class Small extends React.Component {
//   static propTypes = {
//     children: PropTypes.string.isRequired
//   };

//   render() {
//     return <SmallComponent>{this.props.children}</SmallComponent>;
//   }
// }

// const SmallComponent = glamorous.small({
//   ...s.fonts.paragraphSmall,
//   marginTop: s.dimensions.paragraphSpacing,
//   color: s.colors.grayDark
// });

//
// Link
//

export class Link extends React.Component {
  static propTypes = {
    children: PropTypes.string.isRequired,
    href: PropTypes.string.isRequired
  };

  render() {
    return (
      <LinkStyled href={this.props.href}>{this.props.children}</LinkStyled>
    );
  }
}

const LinkStyled = glamorous.a({
  color: s.colors.blueDark,
  transition: `0.2s border ease-in-out`,
  ":visited": {
    color: s.colors.blueDark
  }
});

//
// Lists
//

export class List extends React.Component {
  static propTypes = {
    // TODO: children only prop type of li
    children: PropTypes.node.isRequired,
    numbered: PropTypes.bool
  };

  render() {
    const ListStyled = this.props.numbered
      ? ListOrderedStyled
      : ListUnorderedStyled;

    // TODO: consider using contect api when the new one comes out
    const children = React.Children.map(this.props.children, child =>
      React.cloneElement(child, { numbered: this.props.numbered })
    );

    return <ListStyled>{children}</ListStyled>;
  }
}

export class Li extends React.Component {
  static propTypes = {
    children: PropTypes.node.isRequired,
    numbered: PropTypes.bool
  };

  render() {
    return (
      <ListItemStyled numbered={this.props.numbered}>
        {this.props.children}
      </ListItemStyled>
    );
  }
}

const listSharedStyles = {
  // TODO: why is there size and not grid?
  margin: `${s.dimensions.paragraphSpacing} 0 0 1em`,
  padding: 0
};

const listIndentSize = s.gridRaw(2);

const ListUnorderedStyled = glamorous.ul({
  ...listSharedStyles,
  position: "relative",
  marginLeft: s.size(listIndentSize),
  [`.${classNameParagraph} + &`]: {
    marginTop: 0
  }
});

const ListOrderedStyled = glamorous.ol({
  ...listSharedStyles
});

const ListItemStyled = glamorous.li(
  {
    ...s.fonts.paragraph,
    "> *": {
      marginTop: 0
    }
  },
  props => {
    if (props.numbered) {
      return {
        listStyleType: "decimal"
      };
    } else {
      return {
        listStyleType: "none",
        "::before": {
          content: `"–"`,
          display: "block",
          position: "absolute",
          left: s.size(-listIndentSize)
        }
      };
    }
  }
);

//
// Headings
//

const removeSpacingAfterHeading = {
  "& + *": {
    // TODO: some easy and clean way to do this?
    marginTop: "0 !important"
  }
};

export class H1 extends React.Component {
  static propTypes = {
    children: PropTypes.string.isRequired
  };

  render() {
    return <Heading1Styled>{this.props.children}</Heading1Styled>;
  }
}

const Heading1Styled = glamorous.h2(
  s.fonts.headingMedium,
  {
    margin: `${s.size(56)} 0 ${s.size(12)} 0`,
    color: s.colors.grayDark,
    [s.breakpoints.medium]: {
      margin: `${s.size(44)} 0 ${s.size(10)} 0`
    },
    [s.breakpoints.small]: {
      margin: `${s.size(34)} 0 ${s.size(8)} 0`
    }
  },
  removeSpacingAfterHeading
);

export class H2 extends React.Component {
  static propTypes = {
    children: PropTypes.string.isRequired
  };

  render() {
    return <Heading2Styled>{this.props.children}</Heading2Styled>;
  }
}

const Heading2Styled = glamorous.h3(
  s.fonts.headingSmall,
  {
    margin: `${s.size(32)} 0 ${s.size(10)} 0`,
    color: s.colors.grayDark,
    [s.breakpoints.medium]: {
      margin: `${s.size(26)} 0 ${s.size(8)} 0`
    },
    [s.breakpoints.small]: {
      margin: `${s.size(18)} 0 ${s.size(6)} 0`
    }
  },
  removeSpacingAfterHeading
);

//
// Code
//

export class Code extends React.Component {
  // TODO: make this component dynamic so we do not import whole highlight.js

  static propTypes = {
    children: PropTypes.string.isRequired,
    multiline: PropTypes.bool,
    language: PropTypes.string
  };

  shouldComponentUpdate(nextProps) {
    if (nextProps.children !== this.props.children) return true;
    if (nextProps.language !== this.props.language) return true;

    return false;
  }

  render() {
    const code = (() => {
      let res = this.props.children;
      res = stripIndent(res);
      res = res.trim();
      return res;
    })();

    const codeComponent = this.props.language ? (
      <CodeStyled
        dangerouslySetInnerHTML={{
          __html: highlight(this.props.language, code).value
        }}
        multiline={this.props.multiline}
      />
    ) : (
      <CodeStyled multiline={this.props.multiline}>{code}</CodeStyled>
    );

    if (this.props.multiline) {
      return <PreStyled>{codeComponent}</PreStyled>;
    } else {
      return codeComponent;
    }
  }
}

const PreStyled = glamorous.pre({
  display: "block",
  margin: `${s.dimensions.paragraphSpacing} 0 0 0`
});

const CodeStyled = glamorous.code(
  {
    backgroundColor: s.colors.grayLighter,
    border: `${s.size(1)} solid ${s.colors.grayLight}`,
    borderRadius: s.dimensions.borderRadius,
    boxDecorationBreak: "clone", // inline code snippets can be spread across 2 rows
    WebkitOverflowScrolling: "touch",
    "&.language-diagram": {
      lineHeight: 1
    }
  },
  props => {
    if (props.multiline) {
      return {
        ...s.fonts.codeMultiline,
        display: "block",
        padding: s.grid(1),
        overflow: "auto"
      };
    } else {
      return {
        ...s.fonts.codeInline,
        display: "inline",
        padding: `${s.size(1)} ${s.size(2)}`
      };
    }
  }
);

//
// Table
//

export class Table extends React.Component {
  static propTypes = {
    // TODO: children only table rows
    heading: PropTypes.node,
    children: PropTypes.node.isRequired
  };

  constructor() {
    super();
  }

  render() {
    const heading = (() => {
      const headingProp = this.props.heading;
      if (!headingProp) return null;

      const headingRow = React.Children.map(this.props.heading, child =>
        React.cloneElement(child, { heading: true })
      );

      return headingRow;
    })();

    return (
      <TableStyled>
        {heading &&
{heading}
}

{this.props.children}

      </TableStyled>
    );
  }
}

const TableStyled = glamorous.table({
  margin: `${s.dimensions.paragraphSpacing} 0 0 0`,
  borderCollapse: "collapse"
});

export class Tr extends React.Component {
  static propTypes = {
    // TODO: child oly TableCell

    // Children are not required because we might have empty filler cells.
    children: PropTypes.node.isRequired,
    heading: PropTypes.bool
  };

  render() {
    const cells = React.Children.map(this.props.children, child =>
      React.cloneElement(child, { heading: this.props.heading })
    );

    return
{cells}
;
  }
}

export class Tc extends React.Component {
  static propTypes = {
    children: PropTypes.node,
    heading: PropTypes.bool
  };

  render() {
    const Component = this.props.heading
      ? TableCellHeadingStyled
      : TableCellStyled;

    return <Component>{this.props.children}</Component>;
  }
}

const tableCellSharedStyles = {
  ...s.fonts.paragraphSmall,
  border: `${s.size(1)} solid ${s.colors.grayLight}`,
  padding: s.grid(1)
};

const TableCellStyled = glamorous.td({
  ...tableCellSharedStyles
});

const TableCellHeadingStyled = glamorous.th({
  ...tableCellSharedStyles,
  ...s.fonts.headingTable,
  fontWeight: "bold",
  textAlign: "center"
});

/*

// comments

.Article-comments {
}

.Article-comments-heading {
  margin: 0;
  padding: var(--font-padding-headline);
  font-size: var(--font-size-headline);
  line-height: var(--font-line-height-headline);
  font-family: var(--font-family-heading);
  font-weight: normal;
  color: var(--color-gray-dark);
}

// images

.Article-content img {
  display: block;
  margin: var(--paragraph-spacing) 0 0 0;
}

.Article-content figure {
  margin: var(--paragraph-spacing) 0 0 0;
  font-family: var(--font-family-paragraph);
  font-size: var(--font-size-paragraph);
  line-height: var(--font-line-height-paragraph);
}

.Article-content figure figcaption {
  font-size: var(--font-size-paragraph-small);
  font-family: var(--font-family-paragraph);
  line-height: var(--font-line-height-paragraph-small);
}

// videos

.Article-content video {
  max-width: 100%;
  height: auto;
}

// quotes

.Article-content blockquote {
  margin: var(--paragraph-spacing) 0 0 0;
  padding-left: 1em;
  padding-right: 1em;
  border-left: 0.6rem solid var(--color-gray-lighter);
  font-family: var(--font-family-paragraph);
  font-size: var(--font-size-paragraph);
  line-height: var(--font-line-height-paragraph);
}

.Article-content blockquote p {
  margin: 0;
}

.Article-content blockquote footer {
  margin-top: 0.4em;
}

// videos

.Article-content video {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

 */
<commit_msg>rewrite: only include subset of languages of highlightjs in bundle<commit_after>import React from "react";
import PropTypes from "prop-types";
import glamorous from "glamorous";
import stripIndent from "strip-indent";

// Only include used languages in the bundle
// https://github.com/isagalaev/highlight.js/issues/1257
// TODO: make the register language with dynamic imports so we do not have
//       to register languages manually and so only needed languages are
//       downloaded?
import highlight from "highlight.js/lib/highlight.js";
import highlightJavaScript from "highlight.js/lib/languages/javascript";
import highlightJson from "highlight.js/lib/languages/json";
import highlightCss from "highlight.js/lib/languages/css";
import highlightXml from "highlight.js/lib/languages/xml"; // HTML
import highlightBash from "highlight.js/lib/languages/bash";
// import highlightShell from "highlight.js/lib/languages/shell";
// import highlightHttp from "highlight.js/lib/languages/http";
// import highlightPython from "highlight.js/lib/languages/python";
// import highlightSql from "highlight.js/lib/languages/sql";
// import highlightDiff from "highlight.js/lib/languages/diff";
// import highlightMarkdown from "highlight.js/lib/languages/markdown";

import * as s from "../common/styles.js";

highlight.registerLanguage("javascript", highlightJavaScript);
highlight.registerLanguage("json", highlightJson);
highlight.registerLanguage("css", highlightCss);
highlight.registerLanguage("xml", highlightXml);
highlight.registerLanguage("bash", highlightBash);

//
// Article wrapper
//

export class ArticleWrapper extends React.Component {
  static propTypes = {
    children: PropTypes.node.isRequired
  };

  render() {
    return <WrapperStyled>{this.props.children}</WrapperStyled>;
  }
}

const WrapperStyled = glamorous.div({
  "> *:first-child": {
    marginTop: 0
  }
});

//
// Texts
//

// .Article-content em {
//   font-style: italic;
// }

// .Article-content mark {
//   background-color: var(--color-yellow);
// }

// .Article-content s {
//   text-decoration: line-through;
// }

export class P extends React.Component {
  static propTypes = {
    children: PropTypes.node.isRequired
  };

  render() {
    return <ParagraphStyled>{this.props.children}</ParagraphStyled>;
  }
}

const classNameParagraph = "article-paragraph";

const ParagraphStyled = glamorous.p(classNameParagraph, {
  ...s.fonts.paragraph,
  marginTop: s.dimensions.paragraphSpacing
});

export class Bold extends React.Component {
  static propTypes = {
    children: PropTypes.string.isRequired
  };

  render() {
    return <BoldStyled>{this.props.children}</BoldStyled>;
  }
}

const BoldStyled = glamorous.strong({
  fontWeight: "bold"
});

// TODO: probably not used?
// export class Small extends React.Component {
//   static propTypes = {
//     children: PropTypes.string.isRequired
//   };

//   render() {
//     return <SmallComponent>{this.props.children}</SmallComponent>;
//   }
// }

// const SmallComponent = glamorous.small({
//   ...s.fonts.paragraphSmall,
//   marginTop: s.dimensions.paragraphSpacing,
//   color: s.colors.grayDark
// });

//
// Link
//

export class Link extends React.Component {
  static propTypes = {
    children: PropTypes.string.isRequired,
    href: PropTypes.string.isRequired
  };

  render() {
    return (
      <LinkStyled href={this.props.href}>{this.props.children}</LinkStyled>
    );
  }
}

const LinkStyled = glamorous.a({
  color: s.colors.blueDark,
  transition: `0.2s border ease-in-out`,
  ":visited": {
    color: s.colors.blueDark
  }
});

//
// Lists
//

export class List extends React.Component {
  static propTypes = {
    // TODO: children only prop type of li
    children: PropTypes.node.isRequired,
    numbered: PropTypes.bool
  };

  render() {
    const ListStyled = this.props.numbered
      ? ListOrderedStyled
      : ListUnorderedStyled;

    // TODO: consider using contect api when the new one comes out
    const children = React.Children.map(this.props.children, child =>
      React.cloneElement(child, { numbered: this.props.numbered })
    );

    return <ListStyled>{children}</ListStyled>;
  }
}

export class Li extends React.Component {
  static propTypes = {
    children: PropTypes.node.isRequired,
    numbered: PropTypes.bool
  };

  render() {
    return (
      <ListItemStyled numbered={this.props.numbered}>
        {this.props.children}
      </ListItemStyled>
    );
  }
}

const listSharedStyles = {
  // TODO: why is there size and not grid?
  margin: `${s.dimensions.paragraphSpacing} 0 0 1em`,
  padding: 0
};

const listIndentSize = s.gridRaw(2);

const ListUnorderedStyled = glamorous.ul({
  ...listSharedStyles,
  position: "relative",
  marginLeft: s.size(listIndentSize),
  [`.${classNameParagraph} + &`]: {
    marginTop: 0
  }
});

const ListOrderedStyled = glamorous.ol({
  ...listSharedStyles
});

const ListItemStyled = glamorous.li(
  {
    ...s.fonts.paragraph,
    "> *": {
      marginTop: 0
    }
  },
  props => {
    if (props.numbered) {
      return {
        listStyleType: "decimal"
      };
    } else {
      return {
        listStyleType: "none",
        "::before": {
          content: `"–"`,
          display: "block",
          position: "absolute",
          left: s.size(-listIndentSize)
        }
      };
    }
  }
);

//
// Headings
//

const removeSpacingAfterHeading = {
  "& + *": {
    // TODO: some easy and clean way to do this?
    marginTop: "0 !important"
  }
};

export class H1 extends React.Component {
  static propTypes = {
    children: PropTypes.string.isRequired
  };

  render() {
    return <Heading1Styled>{this.props.children}</Heading1Styled>;
  }
}

const Heading1Styled = glamorous.h2(
  s.fonts.headingMedium,
  {
    margin: `${s.size(56)} 0 ${s.size(12)} 0`,
    color: s.colors.grayDark,
    [s.breakpoints.medium]: {
      margin: `${s.size(44)} 0 ${s.size(10)} 0`
    },
    [s.breakpoints.small]: {
      margin: `${s.size(34)} 0 ${s.size(8)} 0`
    }
  },
  removeSpacingAfterHeading
);

export class H2 extends React.Component {
  static propTypes = {
    children: PropTypes.string.isRequired
  };

  render() {
    return <Heading2Styled>{this.props.children}</Heading2Styled>;
  }
}

const Heading2Styled = glamorous.h3(
  s.fonts.headingSmall,
  {
    margin: `${s.size(32)} 0 ${s.size(10)} 0`,
    color: s.colors.grayDark,
    [s.breakpoints.medium]: {
      margin: `${s.size(26)} 0 ${s.size(8)} 0`
    },
    [s.breakpoints.small]: {
      margin: `${s.size(18)} 0 ${s.size(6)} 0`
    }
  },
  removeSpacingAfterHeading
);

//
// Code
//

export class Code extends React.Component {
  // TODO: make this component dynamic so we do not import whole highlight.js

  static propTypes = {
    children: PropTypes.string.isRequired,
    multiline: PropTypes.bool,
    language: PropTypes.string
  };

  shouldComponentUpdate(nextProps) {
    if (nextProps.children !== this.props.children) return true;
    if (nextProps.language !== this.props.language) return true;

    return false;
  }

  render() {
    const code = (() => {
      let res = this.props.children;
      res = stripIndent(res);
      res = res.trim();
      return res;
    })();

    const codeComponent = this.props.language ? (
      <CodeStyled
        dangerouslySetInnerHTML={{
          __html: highlight.highlight(this.props.language, code).value
        }}
        multiline={this.props.multiline}
      />
    ) : (
      <CodeStyled multiline={this.props.multiline}>{code}</CodeStyled>
    );

    if (this.props.multiline) {
      return <PreStyled>{codeComponent}</PreStyled>;
    } else {
      return codeComponent;
    }
  }
}

const PreStyled = glamorous.pre({
  display: "block",
  margin: `${s.dimensions.paragraphSpacing} 0 0 0`
});

const CodeStyled = glamorous.code(
  {
    backgroundColor: s.colors.grayLighter,
    border: `${s.size(1)} solid ${s.colors.grayLight}`,
    borderRadius: s.dimensions.borderRadius,
    boxDecorationBreak: "clone", // inline code snippets can be spread across 2 rows
    WebkitOverflowScrolling: "touch",
    "&.language-diagram": {
      lineHeight: 1
    }
  },
  props => {
    if (props.multiline) {
      return {
        ...s.fonts.codeMultiline,
        display: "block",
        padding: s.grid(1),
        overflow: "auto"
      };
    } else {
      return {
        ...s.fonts.codeInline,
        display: "inline",
        padding: `${s.size(1)} ${s.size(2)}`
      };
    }
  }
);

//
// Table
//

export class Table extends React.Component {
  static propTypes = {
    // TODO: children only table rows
    heading: PropTypes.node,
    children: PropTypes.node.isRequired
  };

  constructor() {
    super();
  }

  render() {
    const heading = (() => {
      const headingProp = this.props.heading;
      if (!headingProp) return null;

      const headingRow = React.Children.map(this.props.heading, child =>
        React.cloneElement(child, { heading: true })
      );

      return headingRow;
    })();

    return (
      <TableStyled>
        {heading &&
{heading}
}

{this.props.children}

      </TableStyled>
    );
  }
}

const TableStyled = glamorous.table({
  margin: `${s.dimensions.paragraphSpacing} 0 0 0`,
  borderCollapse: "collapse"
});

export class Tr extends React.Component {
  static propTypes = {
    // TODO: child oly TableCell

    // Children are not required because we might have empty filler cells.
    children: PropTypes.node.isRequired,
    heading: PropTypes.bool
  };

  render() {
    const cells = React.Children.map(this.props.children, child =>
      React.cloneElement(child, { heading: this.props.heading })
    );

    return
{cells}
;
  }
}

export class Tc extends React.Component {
  static propTypes = {
    children: PropTypes.node,
    heading: PropTypes.bool
  };

  render() {
    const Component = this.props.heading
      ? TableCellHeadingStyled
      : TableCellStyled;

    return <Component>{this.props.children}</Component>;
  }
}

const tableCellSharedStyles = {
  ...s.fonts.paragraphSmall,
  border: `${s.size(1)} solid ${s.colors.grayLight}`,
  padding: s.grid(1)
};

const TableCellStyled = glamorous.td({
  ...tableCellSharedStyles
});

const TableCellHeadingStyled = glamorous.th({
  ...tableCellSharedStyles,
  ...s.fonts.headingTable,
  fontWeight: "bold",
  textAlign: "center"
});

/*

// comments

.Article-comments {
}

.Article-comments-heading {
  margin: 0;
  padding: var(--font-padding-headline);
  font-size: var(--font-size-headline);
  line-height: var(--font-line-height-headline);
  font-family: var(--font-family-heading);
  font-weight: normal;
  color: var(--color-gray-dark);
}

// images

.Article-content img {
  display: block;
  margin: var(--paragraph-spacing) 0 0 0;
}

.Article-content figure {
  margin: var(--paragraph-spacing) 0 0 0;
  font-family: var(--font-family-paragraph);
  font-size: var(--font-size-paragraph);
  line-height: var(--font-line-height-paragraph);
}

.Article-content figure figcaption {
  font-size: var(--font-size-paragraph-small);
  font-family: var(--font-family-paragraph);
  line-height: var(--font-line-height-paragraph-small);
}

// videos

.Article-content video {
  max-width: 100%;
  height: auto;
}

// quotes

.Article-content blockquote {
  margin: var(--paragraph-spacing) 0 0 0;
  padding-left: 1em;
  padding-right: 1em;
  border-left: 0.6rem solid var(--color-gray-lighter);
  font-family: var(--font-family-paragraph);
  font-size: var(--font-size-paragraph);
  line-height: var(--font-line-height-paragraph);
}

.Article-content blockquote p {
  margin: 0;
}

.Article-content blockquote footer {
  margin-top: 0.4em;
}

// videos

.Article-content video {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

 */
<|endoftext|>


<commit_before>'use strict';

/* POLYFILL (es6StringPolyfill)  IS NEEDED FOR IE11, maybe Symbol support or something missing:
 * http://babeljs.io/docs/usage/polyfill/
 * */

(function () {
  /***********************
  ******** IMPORT ********
  ***********************/
  var polyfills = window.flatworld.generalUtils.polyfills;
  var factories = window.flatworld.factories;
  var Preload = window.flatworld.Preload;
  var baseEventlisteners = window.flatworld.extensions.baseEventlisteners;
  var mapZoom = window.flatworld.extensions.mapZoom;
  var mapDrag = window.flatworld.extensions.mapDrag;
  var hexagons = window.flatworld.extensions.hexagons;
  var mapMovement = window.flatworld.extensions.mapMovement;
  var Sound = window.flatworld.Sound;
  var mapEvents = window.flatworld.mapEvents;
  var mapAPI = window.flatworld.mapAPI;
  var UI = window.flatworld.UI;
  /* DATA FILES used for testing */
  var gameData = window.gameData;
  var typeData = window.typeData;

  /** ===== CONFIGS ===== */
  /* Note the y is 3/4 of the actual height */
  const HEXAGON_RADIUS = gameData.hexagonRadius;
  const BASE_URL = "/requests/";

  /* REQUIRED FOR IE11 */
  polyfills.arrayFind();
  polyfills.es6String();
  hexagons.utils.init(HEXAGON_RADIUS);
  /* This will suppress the fetch errors and make later possible to emulate http-requests */
  window.fetch = function () {
    return {
      then: function () {
        return window.fetch();
      },
      catch: function () {
        return {
          then: 1
        };
      }
    };
  };

  /* Start the whole functionality */
  (function () {
    window.FPSElement = document.createElement("div");
    window.FPSElement.style.position = 'absolute';
    window.FPSElement.style.left = '0px';
    window.FPSElement.style.top = '0px';
    window.FPSElement.style.backgroundColor = 'white';

    document.body.appendChild( window.FPSElement );

    var mapsizeElement = document.getElementById("hexaTiles");
    var cacheElement = document.getElementById("cache");
    var UIThemeIndex = document.getElementById("UItheme").value;
    var cacheMap = true;
    var currentMapSize, mapData;

    document.getElementById("testNotification").textContent = "START THE TESTS BY SELECTING VALUES BELOW AND CLICKING START!";
    document.getElementById("changeValues").disabled = false;

    document.getElementById("changeValues").addEventListener("click", function() {
      document.getElementById("testNotification").style.display = "none";
      currentMapSize = mapsizeElement.value;
      cacheMap = cacheElement.checked;

      mapData = getMapData(currentMapSize);

      initFlatworld(mapData, {
        mapsize: currentMapSize,
        cache: cacheMap,
        UITheme: window.flatworld.UIs[UIThemeIndex],
        canvasContainer: document.getElementById("mapCanvasContainer"),
        automatic: window.automaticTest,
        trackFPSCB: function (data) {
          var totalFPS = data.FPS;
          var totalTime = data.FPStime;
          var totalRenderTime = data.renderTime;
          var drawCount = data.drawCount;

          window.FPSElement.innerHTML = totalFPS + " - " + Math.round( ( totalRenderTime / totalTime * 100 ) ) + "%" + " : " + drawCount;
        }
      });
    });
  })();

  /**************************************
  ****** GENERATE RANDOM MAP DATA *******
  **************************************/
  function getMapData(mapsize) {
    const TERRAIN_TYPE_COUNT = 5;
    const UNIT_TYPE_COUNT = 56;
    var coordMapsize = {
      x: mapsize,
      y: mapsize
    };
    var gridSize = {
      rows: coordMapsize.x / hexagons.utils.calcShortDiagonal(),
      columns: coordMapsize.y / hexagons.utils.calcLongDiagonal()
    };
    var hexagonGridCoordinates = hexagons.utils.createHexagonGridCoordinates(gridSize);
    var terrainLayer;

    terrainLayer = populateTerrainLayer(hexagonGridCoordinates, TERRAIN_TYPE_COUNT);

    return {
      gameID: "53837d47976fed3b24000005",
      turn: 1,
      startPoint: { x: 0, y: 0 },
      element: "#mapCanvas",
      layers: [
      terrainLayer,
      populateUnitLayer(hexagonGridCoordinates, UNIT_TYPE_COUNT)
      ]
    };
  }

  function initFlatworld(mapData, options) {
    var { mapsize, canvasContainer, trackFPSCB, UITheme, cache, automatic} = options;
    var map = {};
    var globalMap = {
      data: {}
    };
    var pluginsToActivate = [
      baseEventlisteners,
      mapZoom,
      mapDrag,
      hexagons.selectHexagonObject,
      mapMovement
    ];
    var sound = new Sound();
    var preload;

    /* This NEEDS to be set for the hexagon plugin to work correctly */
    hexagons.utils.init(gameData.hexagonRadius);
    activateAPIs();

    /* Determines how much stuff we show on screen for stress testing */
    // If either is even 1 pixel bigger than this, gets all black
    /* works with:
    x: 8118,
    y: 8107*/
    gameData.mapSize = {
      x: mapsize || 1000,
      y: mapsize || 1000
    };

    preload = new Preload( "", { crossOrigin: false } );
    preload.addResource( typeData.graphicData.terrainBase.json );
    preload.addResource( typeData.graphicData.unit.json );
    loadSounds();
    mapEvents.subscribe("objectsSelected", unitSelectedSound);

    preload.setErrorHandler(function(e) {
      console.log("preloader error:", e);
    });
    preload.setProgressHandler(function(progress) {
      console.log("progressing" + progress);
    });

    return preload.resolveOnComplete()
      .then(onComplete)
      .then(function (map) {
        return map.whenReady;
      }).then(function () {
        document.getElementById("testFullscreen").addEventListener("click", map.toggleFullScreen);

        var perfTestLoop = setupPerfTestLoop();

        if (automatic) {
          map.whenReady().then(function() {
            window.setTimeout(perfTestLoop);
          }).then(null, function(e) {
            console.log(e);
          });
        }

        function setupPerfTestLoop () {
          var direction = 1;
          var round = 0;
          var quantifier = 2;

          return function() {
            map.moveMap({
              x: direction === 1 ? -quantifier : quantifier,
              y: direction === 1 ? -quantifier : quantifier
            });

            if (map.getMovableLayer().x > 500) {
              round ++;
              direction = 1;
            } else if (map.getMovableLayer().x < - 7000) {
              direction = 2;
            }

            if (round < 5) {
              window.setTimeout(perfTestLoop);
            }
          };
        }
      })
      .catch(function (e) {
        console.log("Map stressTest error: ", e);
      });

    function onComplete(loader, resources) {
      window.worldMap = map = globalMap.data = factories.hexaFactory(
        canvasContainer, {
          game: gameData,
          map: mapData,
          type: typeData
        },
        {
          trackFPSCB: trackFPSCB,
          isHiddenByDefault: true,
          cache: options.cache
        });

      let dialog_selection = document.getElementById("selectionDialog");
      let initializedUITheme = new UITheme.init(dialog_selection, map);
      UI(initializedUITheme, map);

      map.init( pluginsToActivate, mapData.startPoint );

      /* Activate the fullscreen button: */
      document.getElementById("testFullscreen").addEventListener("click", function () {
        map.setFullScreen();
      });

      return map;
    }

    /* ====== private functions ====== */
    function preloadErrorHandler(err) {
      console.log("PRELOADER ERROR", err );
    }
    function unitSelectedSound() {
      sound.play("cheer");
    }
    function loadSounds() {
      sound.add( "cheer", "/tests/testAssets/sounds/personCheering.mp3" );
    }
  }

  /*---------------------
  ------- PRIVATE -------
  ---------------------*/
  /* THESE GENERATE THE ACTUAL RANDOM MAP DATA */
  function addBase_spriteLayerData(name, group, options) {
    options = options || {};
    var interactive = options.interactive || true;
    var cache = options.cache || true;

    return {
      type: "MapLayerParent",
      coord: { x: 0, y: 0 },
      name: name,
      group: group, // For quadTrees
      specials: [{
        interactive: interactive
      }],
      options: {
        cache: cache
      },
      objectGroups: []
    };
  }

  function populateTerrainLayer(hexagonGrid, typeCount) {
    var layerData = addBase_spriteLayerData("terrainLayer", "terrain");

    hexagonGrid.forEach((coordinates) => {
      var { x, y } = coordinates;

      layerData.objectGroups.push({
        type: "ObjectTerrain",
        name: "Terrain", // For quadTrees and debugging
        typeImageData: "terrainBase",
        objects: [{
          objType: Math.floor(Math.random() * typeCount),
          name:"random_" + Math.random(),
          _id: Math.random(),
          coord:{
            x: x,
            y: y
          },
          data: {},
          lastSeenTurn:Math.floor(Math.random() * 10)
        }]
      });
    });

    return layerData;
  }

  function populateUnitLayer(hexagonGrid, typeCount) {
    var layerData = addBase_spriteLayerData("unitLayer", "unit");

    hexagonGrid.forEach((coordinates) => {
      var { x, y } = coordinates;

      layerData.objectGroups.push({
        type: "ObjectUnit",
        name: "Unit", // For quadTrees and debugging
        typeImageData: "unit",
        objects: [{
          objType: Math.floor(Math.random() * typeCount),
          name: "random_" + Math.random(),
          _id: Math.random(),
          coord:{
            x: x,
            y: y
          },
          data: {
            playerID: Math.floor(Math.random() * 10),
            hp: Math.floor(Math.random() * 100),
            someStuff: "jalajajajajaja" + Math.random(),
            someStuff2: "jalajajajajaja" + Math.random(),
            someStuff3: "jalajajajajaja" + Math.random(),
            someStuff4: "jalajajajajaja" + Math.random(),
            someStuff5: "jalajajajajaja" + Math.random(),
            someStuff6: ("jalajajajajaja" + Math.random()).repeat(30)
          },
          lastSeenTurn:Math.floor(Math.random() * 10)
        }]
      });
    });

    return layerData;
  }

  function activateAPIs() {
    mapAPI.add(
      "objectMove",
      function (type, data, movementData) {
        if (type === "get") {
          return {
            url: data.baseUrl + movementData.id
          };
        } else {
          return {
            url: data.baseUrl + movementData.id,
            body: JSON.stringify(movementData)
          };
        }
      },
      BASE_URL
    );
  }
})();<commit_msg>added double the terrain and unit layers for possibly better stresstesting<commit_after>'use strict';

/* POLYFILL (es6StringPolyfill)  IS NEEDED FOR IE11, maybe Symbol support or something missing:
 * http://babeljs.io/docs/usage/polyfill/
 * */

(function () {
  /***********************
  ******** IMPORT ********
  ***********************/
  var polyfills = window.flatworld.generalUtils.polyfills;
  var factories = window.flatworld.factories;
  var Preload = window.flatworld.Preload;
  var baseEventlisteners = window.flatworld.extensions.baseEventlisteners;
  var mapZoom = window.flatworld.extensions.mapZoom;
  var mapDrag = window.flatworld.extensions.mapDrag;
  var hexagons = window.flatworld.extensions.hexagons;
  var mapMovement = window.flatworld.extensions.mapMovement;
  var Sound = window.flatworld.Sound;
  var mapEvents = window.flatworld.mapEvents;
  var mapAPI = window.flatworld.mapAPI;
  var UI = window.flatworld.UI;
  /* DATA FILES used for testing */
  var gameData = window.gameData;
  var typeData = window.typeData;

  /** ===== CONFIGS ===== */
  /* Note the y is 3/4 of the actual height */
  const HEXAGON_RADIUS = gameData.hexagonRadius;
  const BASE_URL = "/requests/";

  /* REQUIRED FOR IE11 */
  polyfills.arrayFind();
  polyfills.es6String();
  hexagons.utils.init(HEXAGON_RADIUS);
  /* This will suppress the fetch errors and make later possible to emulate http-requests */
  window.fetch = function () {
    return {
      then: function () {
        return window.fetch();
      },
      catch: function () {
        return {
          then: 1
        };
      }
    };
  };

  /* Start the whole functionality */
  (function () {
    window.FPSElement = document.createElement("div");
    window.FPSElement.style.position = 'absolute';
    window.FPSElement.style.left = '0px';
    window.FPSElement.style.top = '0px';
    window.FPSElement.style.backgroundColor = 'white';

    document.body.appendChild( window.FPSElement );

    var mapsizeElement = document.getElementById("hexaTiles");
    var cacheElement = document.getElementById("cache");
    var UIThemeIndex = document.getElementById("UItheme").value;
    var cacheMap = true;
    var currentMapSize, mapData;

    document.getElementById("testNotification").textContent = "START THE TESTS BY SELECTING VALUES BELOW AND CLICKING START!";
    document.getElementById("changeValues").disabled = false;

    document.getElementById("changeValues").addEventListener("click", function() {
      document.getElementById("testNotification").style.display = "none";
      currentMapSize = mapsizeElement.value;
      cacheMap = cacheElement.checked;

      mapData = getMapData(currentMapSize);

      initFlatworld(mapData, {
        mapsize: currentMapSize,
        cache: cacheMap,
        UITheme: window.flatworld.UIs[UIThemeIndex],
        canvasContainer: document.getElementById("mapCanvasContainer"),
        automatic: window.automaticTest,
        trackFPSCB: function (data) {
          var totalFPS = data.FPS;
          var totalTime = data.FPStime;
          var totalRenderTime = data.renderTime;
          var drawCount = data.drawCount;

          window.FPSElement.innerHTML = totalFPS + " - " + Math.round( ( totalRenderTime / totalTime * 100 ) ) + "%" + " : " + drawCount;
        }
      });
    });
  })();

  /**************************************
  ****** GENERATE RANDOM MAP DATA *******
  **************************************/
  function getMapData(mapsize) {
    const TERRAIN_TYPE_COUNT = 5;
    const UNIT_TYPE_COUNT = 56;
    var coordMapsize = {
      x: mapsize,
      y: mapsize
    };
    var gridSize = {
      rows: Math.floor(coordMapsize.x / hexagons.utils.calcShortDiagonal()),
      columns: Math.floor(coordMapsize.y / hexagons.utils.calcLongDiagonal())
    };
    var gridSizeHalf = {
      rows: Math.floor(gridSize.rows / 2),
      columns: Math.floor(gridSize.columns / 2)
    };
    var hexagonGridCoordinates = {
      terrains: hexagons.utils.createHexagonGridCoordinates(gridSize),
      units: hexagons.utils.createHexagonGridCoordinates(gridSize),
      units2: hexagons.utils.createHexagonGridCoordinates(gridSizeHalf)
    };
    var terrainLayer, terrainLayer2;

    terrainLayer = populateTerrainLayer(hexagonGridCoordinates.terrains, TERRAIN_TYPE_COUNT);
    terrainLayer2 = populateTerrainLayer(hexagonGridCoordinates.terrains, TERRAIN_TYPE_COUNT);

    return {
      gameID: "53837d47976fed3b24000005",
      turn: 1,
      startPoint: { x: 0, y: 0 },
      element: "#mapCanvas",
      layers: [
      terrainLayer,
      terrainLayer2,
      populateUnitLayer(hexagonGridCoordinates.units, UNIT_TYPE_COUNT),
      populateUnitLayer(hexagonGridCoordinates.units2, UNIT_TYPE_COUNT)
      ]
    };
  }

  function initFlatworld(mapData, options) {
    var { mapsize, canvasContainer, trackFPSCB, UITheme, cache, automatic} = options;
    var map = {};
    var globalMap = {
      data: {}
    };
    var pluginsToActivate = [
      baseEventlisteners,
      mapZoom,
      mapDrag,
      hexagons.selectHexagonObject,
      mapMovement
    ];
    var sound = new Sound();
    var preload;

    /* This NEEDS to be set for the hexagon plugin to work correctly */
    hexagons.utils.init(gameData.hexagonRadius);
    activateAPIs();

    /* Determines how much stuff we show on screen for stress testing */
    // If either is even 1 pixel bigger than this, gets all black
    /* works with:
    x: 8118,
    y: 8107*/
    gameData.mapSize = {
      x: mapsize || 1000,
      y: mapsize || 1000
    };

    preload = new Preload( "", { crossOrigin: false } );
    preload.addResource( typeData.graphicData.terrainBase.json );
    preload.addResource( typeData.graphicData.unit.json );
    loadSounds();
    mapEvents.subscribe("objectsSelected", unitSelectedSound);

    preload.setErrorHandler(function(e) {
      console.log("preloader error:", e);
    });
    preload.setProgressHandler(function(progress) {
      console.log("progressing" + progress);
    });

    return preload.resolveOnComplete()
      .then(onComplete)
      .then(function (map) {
        return map.whenReady;
      }).then(function () {
        document.getElementById("testFullscreen").addEventListener("click", map.toggleFullScreen);

        var perfTestLoop = setupPerfTestLoop();

        if (automatic) {
          map.whenReady().then(function() {
            window.setTimeout(perfTestLoop);
          }).then(null, function(e) {
            console.log(e);
          });
        }

        function setupPerfTestLoop () {
          var direction = 1;
          var round = 0;
          var quantifier = 2;

          return function() {
            map.moveMap({
              x: direction === 1 ? -quantifier : quantifier,
              y: direction === 1 ? -quantifier : quantifier
            });

            if (map.getMovableLayer().x > 500) {
              round ++;
              direction = 1;
            } else if (map.getMovableLayer().x < - 7000) {
              direction = 2;
            }

            if (round < 5) {
              window.setTimeout(perfTestLoop);
            }
          };
        }
      })
      .catch(function (e) {
        console.log("Map stressTest error: ", e);
      });

    function onComplete(loader, resources) {
      window.worldMap = map = globalMap.data = factories.hexaFactory(
        canvasContainer, {
          game: gameData,
          map: mapData,
          type: typeData
        },
        {
          trackFPSCB: trackFPSCB,
          isHiddenByDefault: true,
          cache: options.cache
        });

      let dialog_selection = document.getElementById("selectionDialog");
      let initializedUITheme = new UITheme.init(dialog_selection, map);
      UI(initializedUITheme, map);

      map.init( pluginsToActivate, mapData.startPoint );

      /* Activate the fullscreen button: */
      document.getElementById("testFullscreen").addEventListener("click", function () {
        map.setFullScreen();
      });

      return map;
    }

    /* ====== private functions ====== */
    function preloadErrorHandler(err) {
      console.log("PRELOADER ERROR", err );
    }
    function unitSelectedSound() {
      sound.play("cheer");
    }
    function loadSounds() {
      sound.add( "cheer", "/tests/testAssets/sounds/personCheering.mp3" );
    }
  }

  /*---------------------
  ------- PRIVATE -------
  ---------------------*/
  /* THESE GENERATE THE ACTUAL RANDOM MAP DATA */
  function addBase_spriteLayerData(name, group, options) {
    options = options || {};
    var interactive = options.interactive || true;
    var cache = options.cache || true;

    return {
      type: "MapLayerParent",
      coord: { x: 0, y: 0 },
      name: name,
      group: group, // For quadTrees
      specials: [{
        interactive: interactive
      }],
      options: {
        cache: cache
      },
      objectGroups: []
    };
  }

  function populateTerrainLayer(hexagonGrid, typeCount) {
    var layerData = addBase_spriteLayerData("terrainLayer", "terrain");

    hexagonGrid.forEach((coordinates) => {
      var { x, y } = coordinates;

      layerData.objectGroups.push({
        type: "ObjectTerrain",
        name: "Terrain", // For quadTrees and debugging
        typeImageData: "terrainBase",
        objects: [{
          objType: Math.floor(Math.random() * typeCount),
          name:"random_" + Math.random(),
          _id: Math.random(),
          coord:{
            x: x,
            y: y
          },
          data: {},
          lastSeenTurn:Math.floor(Math.random() * 10)
        }]
      });
    });

    return layerData;
  }

  function populateUnitLayer(hexagonGrid, typeCount) {
    var layerData = addBase_spriteLayerData("unitLayer", "unit");

    hexagonGrid.forEach((coordinates) => {
      var { x, y } = coordinates;

      layerData.objectGroups.push({
        type: "ObjectUnit",
        name: "Unit", // For quadTrees and debugging
        typeImageData: "unit",
        objects: [{
          objType: Math.floor(Math.random() * typeCount),
          name: "random_" + Math.random(),
          _id: Math.random(),
          coord:{
            x: x,
            y: y
          },
          data: {
            playerID: Math.floor(Math.random() * 10),
            hp: Math.floor(Math.random() * 100),
            someStuff: "jalajajajajaja" + Math.random(),
            someStuff2: "jalajajajajaja" + Math.random(),
            someStuff3: "jalajajajajaja" + Math.random(),
            someStuff4: "jalajajajajaja" + Math.random(),
            someStuff5: "jalajajajajaja" + Math.random(),
            someStuff6: ("jalajajajajaja" + Math.random()).repeat(30)
          },
          lastSeenTurn:Math.floor(Math.random() * 10)
        }]
      });
    });

    return layerData;
  }

  function activateAPIs() {
    mapAPI.add(
      "objectMove",
      function (type, data, movementData) {
        if (type === "get") {
          return {
            url: data.baseUrl + movementData.id
          };
        } else {
          return {
            url: data.baseUrl + movementData.id,
            body: JSON.stringify(movementData)
          };
        }
      },
      BASE_URL
    );
  }
})();<|endoftext|>


<commit_before>(function($)
{
	function TextExtAutocomplete()
	{
	};

	$.fn.textext.TextExtAutocomplete = TextExtAutocomplete;
	$.fn.textext.addPlugin('autocomplete', TextExtAutocomplete);

	var p = TextExtAutocomplete.prototype,

		CSS_DOT            = '.',
		CSS_SELECTED       = 'text-selected',
		CSS_DOT_SELECTED   = CSS_DOT + CSS_SELECTED,
		CSS_SUGGESTION     = 'text-suggestion',
		CSS_DOT_SUGGESTION = CSS_DOT + CSS_SUGGESTION,

		HIDE_DROPDOWN = 'hideDropdown',
		SHOW_DROPDOWN = 'showDropdown',

		DEFAULT_OPTS = {
			dropdownEnabled : true,

			html : {
				dropdown   : '

',
				suggestion : '

'
			}
		}
		;

	p.init = function(parent)
	{
		var self = this;

		self.baseInit(parent, DEFAULT_OPTS);

		var input = self.input(),
			opts  = self.opts()
			;

		if(opts.dropdownEnabled)
		{
			input.after(opts.html.dropdown);

			self.on({
				click          : self.onClick,
				blur           : self.onBlur,
				otherKeyUp     : self.onOtherKeyUp,
				deleteKeyUp    : self.onOtherKeyUp,
				backspaceKeyUp : self.onBackspaceKeyUp,
				downKeyDown    : self.onDownKeyDown,
				upKeyDown      : self.onUpKeyDown,
				enterKeyDown   : self.onEnterKeyDown,
				escapeKeyUp    : self.onEscapeKeyUp,
				setSuggestions : self.onSetSuggestions,
				showDropdown   : self.onShowDropdown,
				hideDropdown   : self.onHideDropdown
			});

			self.getDropdownContainer().mouseover(function(e) { self.onMouseOver(e) });
		}
	};

	p.getDropdownContainer = function()
	{
		return this.input().siblings('.text-dropdown');
	};

	//--------------------------------------------------------------------------------
	// User mouse/keyboard input

	p.onMouseOver = function(e)
	{
		var self   = this,
			target = $(e.target)
			;

		if(target.is(CSS_DOT_SUGGESTION))
		{
			self.clearSelected();
			target.addClass(CSS_SELECTED);
		}
	};

	p.onClick = function(e)
	{
		var self   = this,
			target = $(e.target)
			;

		if(target.is(CSS_DOT_SUGGESTION))
			self.selectFromDropdown();
	};

	p.onBlur = function(e)
	{
		var self = this;

		// use timeout here so that onClick has a chance to fire because if
		// dropdown is hidden when clicked, onClick doesn't fire
		if(self.isDropdownVisible())
			setTimeout(function() { self.trigger(HIDE_DROPDOWN) }, 100);
	};

	p.onBackspaceKeyUp = function(e)
	{
		var self = this;

		if(self.input().val().length > 0)
			self.getSuggestions();
	};

	p.onOtherKeyUp = function(e)
	{
		this.getSuggestions();
	};

	p.onDownKeyDown = function(e)
	{
		var self = this;

		self.isDropdownVisible()
			? self.toggleNextSuggestion()
			: self.getSuggestions()
			;
	};

	p.onUpKeyDown = function(e)
	{
		this.togglePreviousSuggestion();
	};

	p.onEnterKeyDown = function(e)
	{
		var self = this;

		if(self.isDropdownVisible())
			self.selectFromDropdown();
	};

	p.onEscapeKeyUp = function(e)
	{
		var self = this;

		if(self.isDropdownVisible())
			self.trigger(HIDE_DROPDOWN);
	};

	//--------------------------------------------------------------------------------
	// Core functionality

	p.getSuggestionElements = function()
	{
		return this.getDropdownContainer().find(CSS_DOT_SUGGESTION);
	};

	p.setSelectedSuggestion = function(suggestion)
	{
		if(!suggestion)
			return;

		var self   = this,
			all    = self.getSuggestionElements(),
			target = all.first(),
			item, i
			;

		self.clearSelected();

		for(i = 0; i < all.length; i++)
		{
			item = $(all[i]);

			if(self.compareItems(item.data(CSS_SUGGESTION), suggestion))
			{
				target = item.addClass(CSS_SELECTED);
				break;
			}
		}

		target.addClass(CSS_SELECTED);
		self.scrollSuggestionIntoView(target);
	};

	p.getSelectedSuggestion = function()
	{
		return this.getSuggestionElements().filter(CSS_DOT_SELECTED).first();
	};

	p.isDropdownVisible = function()
	{
		return this.getDropdownContainer().is(':visible');
	};

	p.onHideDropdown = function(e)
	{
		this.hideDropdown();
	};

	p.onShowDropdown = function(e)
	{
		var self    = this,
			current = self.getSelectedSuggestion().data(CSS_SUGGESTION)
			;
		self.renderDropdown(self.suggestions);
		self.showDropdown(self.getDropdownContainer());
		self.setSelectedSuggestion(current);
	};

	p.onSetSuggestions = function(e, data)
	{
		var self        = this,
			suggestions = self.suggestions = data.result
			;

		if(data.showHideDropdown != false)
			self.trigger(suggestions == null || suggestions.length == 0 ? HIDE_DROPDOWN : SHOW_DROPDOWN);
	};

	p.getSuggestions = function()
	{
		var self = this,
			val  = self.input().val()
			;

		if(self.previousInputValue == val)
			return;

		// if user clears input, then we want to select first suggestion
		// instead of the last one
		if(val == '')
			current = null;

		self.previousInputValue = val;
		self.trigger('getSuggestions', { query : val });
	};

	p.renderDropdown = function(suggestions)
	{
		var self = this;

		self.getDropdownContainer().find('.text-list').children().remove();

		$.each(suggestions, function(index, item)
		{
			self.addSuggestion(item);
		});

		self.toggleNextSuggestion();
	};

	p.showDropdown = function()
	{
		this.getDropdownContainer().show();
	};

	p.hideDropdown = function()
	{
		var self     = this,
			dropdown = self.getDropdownContainer()
			;

		self.previousInputValue = null;
		dropdown.hide();
	};

	p.addSuggestion = function(suggestion)
	{
		var self      = this,
			container = self.getDropdownContainer().find('.text-list')
			;

		container.append(self.renderSuggestion(suggestion));
	};

	p.renderSuggestion = function(suggestion)
	{
		var self = this,
			node = $(self.opts().html.suggestion)
			;

		node.find('.text-label').text(self.itemToString(suggestion));
		node.data(CSS_SUGGESTION, suggestion);
		return node;
	};

	/**
	 * Removed `text-selected` class from all suggestion elements.
	 * @author agorbatchev
	 * @date 2011/08/02
	 */
	p.clearSelected = function()
	{
		this.getSuggestionElements().removeClass(CSS_SELECTED);
	};

	/**
	 * Selects next suggestion relative to the current one. If there's no
	 * currently selected suggestion, it will select the first one.
	 * @author agorbatchev
	 * @date 2011/08/02
	 */
	p.toggleNextSuggestion = function()
	{
		var self     = this,
			selected = self.getSelectedSuggestion(),
			next
			;

		if(selected.length > 0)
		{
			next = selected.next();

			if(next.length > 0)
				selected.removeClass(CSS_SELECTED);
		}
		else
		{
			next = self.getSuggestionElements().first();
		}

		next.addClass(CSS_SELECTED);
		self.scrollSuggestionIntoView(next);
	};

	p.togglePreviousSuggestion = function()
	{
		var self     = this,
			selected = self.getSelectedSuggestion(),
			prev     = selected.prev()
			;

		if(prev.length == 0)
			return;

		self.clearSelected();
		prev.addClass(CSS_SELECTED);
		self.scrollSuggestionIntoView(prev);
	};

	p.scrollSuggestionIntoView = function(item)
	{
		var itemHeight     = item.outerHeight(),
			dropdown       = this.getDropdownContainer(),
			dropdownHeight = dropdown.innerHeight(),
			scrollPos      = dropdown.scrollTop(),
			itemTop        = (item.position() || {}).top,
			scrollTo       = null,
			paddingTop     = parseInt(dropdown.css('paddingTop'))
			;

		if(itemTop == null)
			return;

		// if scrolling down and item is below the bottom fold
		if(itemTop + itemHeight > dropdownHeight)
			scrollTo = itemTop + scrollPos + itemHeight - dropdownHeight + paddingTop;

		// if scrolling up and item is above the top fold
		if(itemTop < 0)
			scrollTo = itemTop + scrollPos - paddingTop;

		if(scrollTo != null)
			dropdown.scrollTop(scrollTo);
	};

	p.selectFromDropdown = function()
	{
		var self       = this,
			suggestion = self.getSelectedSuggestion().first().data(CSS_SUGGESTION)
			;

		if(suggestion)
		{
			self.input().val(self.itemToString(suggestion));
			self.trigger('selectItem', suggestion);
		}

		self.trigger(HIDE_DROPDOWN);
	};
})(jQuery);
<commit_msg>Suggestions list is now refreshed when backspacing and text area is empty or dropdown is still visible.<commit_after>(function($)
{
	function TextExtAutocomplete()
	{
	};

	$.fn.textext.TextExtAutocomplete = TextExtAutocomplete;
	$.fn.textext.addPlugin('autocomplete', TextExtAutocomplete);

	var p = TextExtAutocomplete.prototype,

		CSS_DOT            = '.',
		CSS_SELECTED       = 'text-selected',
		CSS_DOT_SELECTED   = CSS_DOT + CSS_SELECTED,
		CSS_SUGGESTION     = 'text-suggestion',
		CSS_DOT_SUGGESTION = CSS_DOT + CSS_SUGGESTION,

		HIDE_DROPDOWN = 'hideDropdown',
		SHOW_DROPDOWN = 'showDropdown',

		DEFAULT_OPTS = {
			dropdownEnabled : true,

			html : {
				dropdown   : '

',
				suggestion : '

'
			}
		}
		;

	p.init = function(parent)
	{
		var self = this;

		self.baseInit(parent, DEFAULT_OPTS);

		var input = self.input(),
			opts  = self.opts()
			;

		if(opts.dropdownEnabled)
		{
			input.after(opts.html.dropdown);

			self.on({
				click          : self.onClick,
				blur           : self.onBlur,
				otherKeyUp     : self.onOtherKeyUp,
				deleteKeyUp    : self.onOtherKeyUp,
				backspaceKeyUp : self.onBackspaceKeyUp,
				downKeyDown    : self.onDownKeyDown,
				upKeyDown      : self.onUpKeyDown,
				enterKeyDown   : self.onEnterKeyDown,
				escapeKeyUp    : self.onEscapeKeyUp,
				setSuggestions : self.onSetSuggestions,
				showDropdown   : self.onShowDropdown,
				hideDropdown   : self.onHideDropdown
			});

			self.getDropdownContainer().mouseover(function(e) { self.onMouseOver(e) });
		}
	};

	p.getDropdownContainer = function()
	{
		return this.input().siblings('.text-dropdown');
	};

	//--------------------------------------------------------------------------------
	// User mouse/keyboard input

	p.onMouseOver = function(e)
	{
		var self   = this,
			target = $(e.target)
			;

		if(target.is(CSS_DOT_SUGGESTION))
		{
			self.clearSelected();
			target.addClass(CSS_SELECTED);
		}
	};

	p.onClick = function(e)
	{
		var self   = this,
			target = $(e.target)
			;

		if(target.is(CSS_DOT_SUGGESTION))
			self.selectFromDropdown();
	};

	p.onBlur = function(e)
	{
		var self = this;

		// use timeout here so that onClick has a chance to fire because if
		// dropdown is hidden when clicked, onClick doesn't fire
		if(self.isDropdownVisible())
			setTimeout(function() { self.trigger(HIDE_DROPDOWN) }, 100);
	};

	p.onBackspaceKeyUp = function(e)
	{
		var self = this,
			isEmpty = self.input().val().length > 0
			;

		if(isEmpty || self.isDropdownVisible())
			self.getSuggestions();
	};

	p.onOtherKeyUp = function(e)
	{
		this.getSuggestions();
	};

	p.onDownKeyDown = function(e)
	{
		var self = this;

		self.isDropdownVisible()
			? self.toggleNextSuggestion()
			: self.getSuggestions()
			;
	};

	p.onUpKeyDown = function(e)
	{
		this.togglePreviousSuggestion();
	};

	p.onEnterKeyDown = function(e)
	{
		var self = this;

		if(self.isDropdownVisible())
			self.selectFromDropdown();
	};

	p.onEscapeKeyUp = function(e)
	{
		var self = this;

		if(self.isDropdownVisible())
			self.trigger(HIDE_DROPDOWN);
	};

	//--------------------------------------------------------------------------------
	// Core functionality

	p.getSuggestionElements = function()
	{
		return this.getDropdownContainer().find(CSS_DOT_SUGGESTION);
	};

	p.setSelectedSuggestion = function(suggestion)
	{
		if(!suggestion)
			return;

		var self   = this,
			all    = self.getSuggestionElements(),
			target = all.first(),
			item, i
			;

		self.clearSelected();

		for(i = 0; i < all.length; i++)
		{
			item = $(all[i]);

			if(self.compareItems(item.data(CSS_SUGGESTION), suggestion))
			{
				target = item.addClass(CSS_SELECTED);
				break;
			}
		}

		target.addClass(CSS_SELECTED);
		self.scrollSuggestionIntoView(target);
	};

	p.getSelectedSuggestion = function()
	{
		return this.getSuggestionElements().filter(CSS_DOT_SELECTED).first();
	};

	p.isDropdownVisible = function()
	{
		return this.getDropdownContainer().is(':visible');
	};

	p.onHideDropdown = function(e)
	{
		this.hideDropdown();
	};

	p.onShowDropdown = function(e)
	{
		var self    = this,
			current = self.getSelectedSuggestion().data(CSS_SUGGESTION)
			;
		self.renderDropdown(self.suggestions);
		self.showDropdown(self.getDropdownContainer());
		self.setSelectedSuggestion(current);
	};

	p.onSetSuggestions = function(e, data)
	{
		var self        = this,
			suggestions = self.suggestions = data.result
			;

		if(data.showHideDropdown != false)
			self.trigger(suggestions == null || suggestions.length == 0 ? HIDE_DROPDOWN : SHOW_DROPDOWN);
	};

	p.getSuggestions = function()
	{
		var self = this,
			val  = self.input().val()
			;

		if(self._previousInputValue == val)
			return;

		// if user clears input, then we want to select first suggestion
		// instead of the last one
		if(val == '')
			current = null;

		self._previousInputValue = val;
		self.trigger('getSuggestions', { query : val });
	};

	p.renderDropdown = function(suggestions)
	{
		var self = this;

		self.getDropdownContainer().find('.text-list').children().remove();

		$.each(suggestions, function(index, item)
		{
			self.addSuggestion(item);
		});

		self.toggleNextSuggestion();
	};

	p.showDropdown = function()
	{
		this.getDropdownContainer().show();
	};

	p.hideDropdown = function()
	{
		var self     = this,
			dropdown = self.getDropdownContainer()
			;

		self._previousInputValue = null;
		dropdown.hide();
	};

	p.addSuggestion = function(suggestion)
	{
		var self      = this,
			container = self.getDropdownContainer().find('.text-list')
			;

		container.append(self.renderSuggestion(suggestion));
	};

	p.renderSuggestion = function(suggestion)
	{
		var self = this,
			node = $(self.opts().html.suggestion)
			;

		node.find('.text-label').text(self.itemToString(suggestion));
		node.data(CSS_SUGGESTION, suggestion);
		return node;
	};

	/**
	 * Removed `text-selected` class from all suggestion elements.
	 * @author agorbatchev
	 * @date 2011/08/02
	 */
	p.clearSelected = function()
	{
		this.getSuggestionElements().removeClass(CSS_SELECTED);
	};

	/**
	 * Selects next suggestion relative to the current one. If there's no
	 * currently selected suggestion, it will select the first one.
	 * @author agorbatchev
	 * @date 2011/08/02
	 */
	p.toggleNextSuggestion = function()
	{
		var self     = this,
			selected = self.getSelectedSuggestion(),
			next
			;

		if(selected.length > 0)
		{
			next = selected.next();

			if(next.length > 0)
				selected.removeClass(CSS_SELECTED);
		}
		else
		{
			next = self.getSuggestionElements().first();
		}

		next.addClass(CSS_SELECTED);
		self.scrollSuggestionIntoView(next);
	};

	p.togglePreviousSuggestion = function()
	{
		var self     = this,
			selected = self.getSelectedSuggestion(),
			prev     = selected.prev()
			;

		if(prev.length == 0)
			return;

		self.clearSelected();
		prev.addClass(CSS_SELECTED);
		self.scrollSuggestionIntoView(prev);
	};

	p.scrollSuggestionIntoView = function(item)
	{
		var itemHeight     = item.outerHeight(),
			dropdown       = this.getDropdownContainer(),
			dropdownHeight = dropdown.innerHeight(),
			scrollPos      = dropdown.scrollTop(),
			itemTop        = (item.position() || {}).top,
			scrollTo       = null,
			paddingTop     = parseInt(dropdown.css('paddingTop'))
			;

		if(itemTop == null)
			return;

		// if scrolling down and item is below the bottom fold
		if(itemTop + itemHeight > dropdownHeight)
			scrollTo = itemTop + scrollPos + itemHeight - dropdownHeight + paddingTop;

		// if scrolling up and item is above the top fold
		if(itemTop < 0)
			scrollTo = itemTop + scrollPos - paddingTop;

		if(scrollTo != null)
			dropdown.scrollTop(scrollTo);
	};

	p.selectFromDropdown = function()
	{
		var self       = this,
			suggestion = self.getSelectedSuggestion().first().data(CSS_SUGGESTION)
			;

		if(suggestion)
		{
			self.input().val(self.itemToString(suggestion));
			self.trigger('selectItem', suggestion);
		}

		self.trigger(HIDE_DROPDOWN);
	};
})(jQuery);
<|endoftext|>


<commit_before>/*
 * jQuery EasIng v1.1.2 - http://gsgd.co.uk/sandbox/jquery.easIng.php
 *
 * Uses the built In easIng capabilities added In jQuery 1.1
 * to offer multiple easIng options
 *
 * Copyright (c) 2007 George Smith
 * Licensed under the MIT License:
 *   http://www.opensource.org/licenses/mit-license.php
 */

// t: current time, b: begInnIng value, c: change In value, d: duration

jQuery.extend( jQuery.easing,
{
	easeInQuad: function (x, t, b, c, d) {
		return c*(t/=d)*t + b;
	},
	easeOutQuad: function (x, t, b, c, d) {
		return -c *(t/=d)*(t-2) + b;
	},
	easeInOutQuad: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	},
	easeInCubic: function (x, t, b, c, d) {
		return c*(t/=d)*t*t + b;
	},
	easeOutCubic: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t + 1) + b;
	},
	easeInOutCubic: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t + b;
		return c/2*((t-=2)*t*t + 2) + b;
	},
	easeInQuart: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t + b;
	},
	easeOutQuart: function (x, t, b, c, d) {
		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	},
	easeInOutQuart: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
		return -c/2 * ((t-=2)*t*t*t - 2) + b;
	},
	easeInQuint: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t*t + b;
	},
	easeOutQuint: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	},
	easeInOutQuint: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
		return c/2*((t-=2)*t*t*t*t + 2) + b;
	},
	easeInSine: function (x, t, b, c, d) {
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	},
	easeOutSine: function (x, t, b, c, d) {
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	},
	easeInOutSine: function (x, t, b, c, d) {
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	},
	easeInExpo: function (x, t, b, c, d) {
		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
	},
	easeOutExpo: function (x, t, b, c, d) {
		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
	},
	easeInOutExpo: function (x, t, b, c, d) {
		if (t==0) return b;
		if (t==d) return b+c;
		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
	},
	easeInCirc: function (x, t, b, c, d) {
		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
	},
	easeOutCirc: function (x, t, b, c, d) {
		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
	},
	easeInOutCirc: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
	},
	easeInElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	},
	easeOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
	},
	easeInOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
	},
	easeInBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*(t/=d)*t*((s+1)*t - s) + b;
	},
	easeOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	},
	easeInOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
	},
	easeInBounce: function (x, t, b, c, d) {
		return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
	},
	easeOutBounce: function (x, t, b, c, d) {
		if ((t/=d) < (1/2.75)) {
			return c*(7.5625*t*t) + b;
		} else if (t < (2/2.75)) {
			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
		} else if (t < (2.5/2.75)) {
			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
		} else {
			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
		}
	},
	easeInOutBounce: function (x, t, b, c, d) {
		if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
		return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
	}
});<commit_msg>commiting again<commit_after>/*
 * jQuery EasIng v1.1.2 - http://gsgd.co.uk/sandbox/jquery.easIng.php
 *
 * Uses the built In easIng capabilities added In jQuery 1.1
 * to offer multiple easIng options
 *
 * Copyright (c) 2007 George Smith
 * Licensed under the MIT License:
 *   http://www.opensource.org/licenses/mit-license.php
 */

// t: current time, b: begInnIng value, c: change In value, d: duration

jQuery.extend( jQuery.easing,
{
	easeInQuad: function (x, t, b, c, d) {
		return c*(t/=d)*t + b;
	},
	easeOutQuad: function (x, t, b, c, d) {
		return -c *(t/=d)*(t-2) + b;
	},
	easeInOutQuad: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	},
	easeInCubic: function (x, t, b, c, d) {
		return c*(t/=d)*t*t + b;
	},
	easeOutCubic: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t + 1) + b;
	},
	easeInOutCubic: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t + b;
		return c/2*((t-=2)*t*t + 2) + b;
	},
	easeInQuart: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t + b;
	},
	easeOutQuart: function (x, t, b, c, d) {
		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	},
	easeInOutQuart: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
		return -c/2 * ((t-=2)*t*t*t - 2) + b;
	},
	easeInQuint: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t*t + b;
	},
	easeOutQuint: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	},
	easeInOutQuint: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
		return c/2*((t-=2)*t*t*t*t + 2) + b;
	},
	easeInSine: function (x, t, b, c, d) {
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	},
	easeOutSine: function (x, t, b, c, d) {
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	},
	easeInOutSine: function (x, t, b, c, d) {
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	},
	easeInExpo: function (x, t, b, c, d) {
		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
	},
	easeOutExpo: function (x, t, b, c, d) {
		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
	},
	easeInOutExpo: function (x, t, b, c, d) {
		if (t==0) return b;
		if (t==d) return b+c;
		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
	},
	easeInCirc: function (x, t, b, c, d) {
		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
	},
	easeOutCirc: function (x, t, b, c, d) {
		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
	},
	easeInOutCirc: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
	},
	easeInElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	},
	easeOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
	},
	easeInOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
	},
	easeInBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*(t/=d)*t*((s+1)*t - s) + b;
	},
	easeOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	},
	easeInOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
	},
	easeInBounce: function (x, t, b, c, d) {
		return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
	},
	easeOutBounce: function (x, t, b, c, d) {
		if ((t/=d) < (1/2.75)) {
			return c*(7.5625*t*t) + b;
		} else if (t < (2/2.75)) {
			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
		} else if (t < (2.5/2.75)) {
			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
		} else {
			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
		}
	},
	easeInOutBounce: function (x, t, b, c, d) {
		if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
		return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
	}
});
<|endoftext|>


<commit_before>import Storage from 'store2';

/**
 * @param {String} ns Local storage namespace
 * @param {String[]} persistMutations
 * @return {function(...[*]=)} Vuex plugin
 */
export default function persistFactory(ns, persistMutations) {
  const storage = Storage.namespace(ns);

  return function(store) {
    const load = () => {
      persistMutations.forEach(mutation => {
        if (storage.has(mutation)) {
          store.commit(mutation, storage(mutation));
        }
      });
    };

    window.addEventListener('focus', load);
    load();

    store.subscribe(mutation => {
      if (
        persistMutations.indexOf(mutation.type) >= 0 &&
        storage(mutation.type) !== mutation.payload
      ) {
        storage(mutation.type, mutation.payload);
      }
    });
  };
}
<commit_msg>Enable list support in state persist helper<commit_after>import Storage from 'store2';

/**
 * @param {String} ns Local storage namespace
 * @param {String[]} persistMutations
 * @return {function(...[*]=)} Vuex plugin
 */
export default function persistFactory(ns, persistMutations) {
  const storage = Storage.namespace(ns);

  return function(store) {
    const load = () => {
      persistMutations.forEach(mutation => {
        if (storage.has(mutation)) {
          const payloads = /^ADD/.test(mutation) ? storage(mutation) : [storage(mutation)];

          payloads.forEach(payload => store.commit(mutation, payload));
        }
      });
    };

    window.addEventListener('focus', load);
    load();

    store.subscribe(mutation => {
      if (persistMutations.indexOf(mutation.type) >= 0) {
        let oldValue = storage(mutation.type);

        // If ADD vs SET, then we'll keep a list of payloads
        if (/^ADD/.test(mutation.type)) {
          oldValue = oldValue || [];
          oldValue.push(mutation.payload);
          storage(mutation.type, oldValue);
        } else if (oldValue !== mutation.payload) {
          storage(mutation.type, mutation.payload);
        }
      }
    });
  };
}
<|endoftext|>


<commit_before>var messageList,
    userList;

var msgcolor = 0;

$(document).ready(function(){
	IO = new IO();

	messageList = new MessageList();
	userList = new UserList();
	uli = new UserListUI(userList, $('#user_list .users'));

	UI = new UI();

	IO.addMessageHandler(messageList);
	IO.addMessageHandler(userList);

	IO.connect();

	if(!readonly){
		$('#message').keydown(function(e){
			if(e.keyCode == 13){
				var el = $(this),
						message = $.trim(el.val());

				if(message.length > 0){
					IO.socket.send({chan: channel, action:'post', msg:message});
					el.val('');
				}

				e.preventDefault();
			}
		});
	}else {
		$('#message').val('Sign in to send messages');
		$('#message').attr('disabled', 'disabled');
	}
	$('#stats').click(function(e){
		IO.socket.send({chan: channel, action:'stats'});
	});
});

function IO(){
	var socket = this.socket = new io.Socket(window.location.hostname);
	var messageHandlers = [];

	socket.on('connect', function(){
		UI.update_connection_status('Connected');
	});

	socket.on('disconnect', function(){
		UI.update_connection_status('Not Connected');
	});

	socket.on('message', function(data){
		for(var i=0, len=messageHandlers.length; i<len; i++){
			var handler = messageHandlers[i];
			if(handler.newMessage(data)) break;
		}
	});

	this.connect = function(){
		UI.update_connection_status('Connecting');
		socket.connect();
		socket.send({channel: channel, action: 'join', connector_id: connector_id});
	}

	this.addMessageHandler = function(handler){
		messageHandlers.push(handler);
	}
}

function UI(){
	if(!readonly){
		IO.socket.on('connect', function(){
			$('#message').attr('disabled', false).focus();
		});
	}

	this.appendMessages = function(data){
		var messages = data.messages;
		for(var i=0; i<messages.length; i++){
			this.appendMessage(messages[i]);
		}
	}

	this.update_connection_status = function(text){
		$('#connection_status').text(text);
	};

	this.appendMessage = function(data){
		var line = $('
'),
				timestamp = $('
'),
				nick = $('
'),
				msg  = $('
');

		nick.text(data.from.name);
		nick.addClass('name');

		var time = new Date();
		/*timestamp.text("(" + time.getHours() + ":" + time.getMinutes() + ":" + time.getSeconds() + ")");*/
		timestamp.append("(",
			time.getHours() < 10 ? "0" + time.getHours() : time.getHours(), ":",
			time.getMinutes() < 10 ? "0" + time.getMinutes() : time.getMinutes(), ":",
			time.getSeconds() < 10 ? "0" + time.getSeconds() : time.getSeconds(), ")");
		timestamp.addClass('timestamp');

		if(this.linkifyTest(data.msg))
			msg.html(this.linkify(data.msg));
		else
			msg.text(data.msg);
		msg.addClass('msg');

		line.append(timestamp, nick, msg);
		line.addClass('line');
		if(msgcolor == 0){
			line.addClass('line0');
			msgcolor = 1;
		} else {
			line.addClass('line1');
			msgcolor = 0;
		}

		$('#messages').append(line);
	}

	this.systemMessage = function(msg){
		this.appendMessage({from:{name: "System"}, msg:msg});
	}

	this.linkify = function(inputText){
		var replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
		var replacedText = inputText.replace(replacePattern1, '$1');
		var replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
		var replacedText = replacedText.replace(replacePattern2, '$1$2');
		var replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;
		var replacedText = replacedText.replace(replacePattern3, '$1');
    return replacedText
	}

	this.linkifyTest = function(inputText){
		var replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
		if(inputText.match(replacePattern1))
			return true;
		var replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
		if(inputText.match(replacePattern2))
			return true;
		var replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;
		if(inputText.match(replacePattern3))
			return true;
    return false;
	}

}

function MessageList(){
	this.list = [];
}

MessageList.prototype.newMessage = function(msg){
	if(msg.action == 'message'){
		UI.appendMessage(msg);
		var msgDiv = document.getElementById("messages");
		msgDiv.scrollTop = msgDiv.scrollHeight;
		return true;
	}else if(msg.action == 'previous'){
		UI.appendMessages(msg);
		var msgDiv = document.getElementById("messages");
		msgDiv.scrollTop = msgDiv.scrollHeight;
		return true;
	}
}

function UserList(){
	this.list = [];
}

UserList.prototype = new EventEmitter();

UserList.prototype.newMessage = function(msg){
	switch(msg.action){
		case "join":
			this.list = this.list.concat(msg.users);
			this.emit('join', msg.users);
			break;
		case "part":
			this.list = this.list.concat(msg.users);
			this.emit('part', msg.users);
			break;
		case "who":
			this.list = msg.users;
			this.emit('who', this.list);
		default:
			return false;
	}
	return true;
}

function UserListUI(ul, container){
	var user_divs = {};

	ul.on('join', function(users){
		var names=[];
		$.each(users, function(i, user){
			addUser(user);
			names.push(user.name);
		});
		UI.systemMessage("Joined: " + names.join(', '));
	});

	ul.on('part', function(users){
		var names=[];
		$.each(users, function(i, user){
			removeUser(user);
			names.push(user.name);
		});
		UI.systemMessage("Left: " + names.join(', '));
	});

	ul.on('who', function(users){
		clearUserList();
		$.each(users, function(i, user){
			addUser(user);
		});
	});

	function addUser(user){
		var name_div = $('
');
		name_div.attr('id', 'user_' + user.id);
		name_div.attr('title', user.name);
		name_div.append(user.name);
		name_div.addClass('user');
		container.append(name_div);
		user_divs[user.id] = name_div;
	}

	function removeUser(user){
		if(user_divs[user.id]){
			user_divs[user.id].remove();
			delete user_divs[user.id];
		}
	}

	function clearUserList(){
		for(var i in user_divs){
			user_divs[i].remove();
		}
		user_divs = {};
	}
}
<commit_msg>Escape < and > when replacing links in messages<commit_after>var messageList,
    userList;

var msgcolor = 0;

$(document).ready(function(){
	IO = new IO();

	messageList = new MessageList();
	userList = new UserList();
	uli = new UserListUI(userList, $('#user_list .users'));

	UI = new UI();

	IO.addMessageHandler(messageList);
	IO.addMessageHandler(userList);

	IO.connect();

	if(!readonly){
		$('#message').keydown(function(e){
			if(e.keyCode == 13){
				var el = $(this),
						message = $.trim(el.val());

				if(message.length > 0){
					IO.socket.send({chan: channel, action:'post', msg:message});
					el.val('');
				}

				e.preventDefault();
			}
		});
	}else {
		$('#message').val('Sign in to send messages');
		$('#message').attr('disabled', 'disabled');
	}
	$('#stats').click(function(e){
		IO.socket.send({chan: channel, action:'stats'});
	});
});

function IO(){
	var socket = this.socket = new io.Socket(window.location.hostname);
	var messageHandlers = [];

	socket.on('connect', function(){
		UI.update_connection_status('Connected');
	});

	socket.on('disconnect', function(){
		UI.update_connection_status('Not Connected');
	});

	socket.on('message', function(data){
		for(var i=0, len=messageHandlers.length; i<len; i++){
			var handler = messageHandlers[i];
			if(handler.newMessage(data)) break;
		}
	});

	this.connect = function(){
		UI.update_connection_status('Connecting');
		socket.connect();
		socket.send({channel: channel, action: 'join', connector_id: connector_id});
	}

	this.addMessageHandler = function(handler){
		messageHandlers.push(handler);
	}
}

function UI(){
	if(!readonly){
		IO.socket.on('connect', function(){
			$('#message').attr('disabled', false).focus();
		});
	}

	this.appendMessages = function(data){
		var messages = data.messages;
		for(var i=0; i<messages.length; i++){
			this.appendMessage(messages[i]);
		}
	}

	this.update_connection_status = function(text){
		$('#connection_status').text(text);
	};

	this.appendMessage = function(data){
		var line = $('
'),
				timestamp = $('
'),
				nick = $('
'),
				msg  = $('
');

		nick.text(data.from.name);
		nick.addClass('name');

		var time = new Date();
		/*timestamp.text("(" + time.getHours() + ":" + time.getMinutes() + ":" + time.getSeconds() + ")");*/
		timestamp.append("(",
			time.getHours() < 10 ? "0" + time.getHours() : time.getHours(), ":",
			time.getMinutes() < 10 ? "0" + time.getMinutes() : time.getMinutes(), ":",
			time.getSeconds() < 10 ? "0" + time.getSeconds() : time.getSeconds(), ")");
		timestamp.addClass('timestamp');

		if(this.linkifyTest(data.msg)){
			//escape <,> so we don't include any nasty html tags
			data.msg = data.msg.replace(/</g, '<').replace(/>/g,'>');
			msg.html(this.linkify(data.msg));
		}
		else
			msg.text(data.msg);
		msg.addClass('msg');

		line.append(timestamp, nick, msg);
		line.addClass('line');
		if(msgcolor == 0){
			line.addClass('line0');
			msgcolor = 1;
		} else {
			line.addClass('line1');
			msgcolor = 0;
		}

		$('#messages').append(line);
	}

	this.systemMessage = function(msg){
		this.appendMessage({from:{name: "System"}, msg:msg});
	}

	this.linkify = function(inputText){
		var replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
		var replacedText = inputText.replace(replacePattern1, '$1');
		var replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
		var replacedText = replacedText.replace(replacePattern2, '$1$2');
		var replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;
		var replacedText = replacedText.replace(replacePattern3, '$1');
    return replacedText
	}

	this.linkifyTest = function(inputText){
		var replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
		if(inputText.match(replacePattern1))
			return true;
		var replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
		if(inputText.match(replacePattern2))
			return true;
		var replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;
		if(inputText.match(replacePattern3))
			return true;
    return false;
	}

}

function MessageList(){
	this.list = [];
}

MessageList.prototype.newMessage = function(msg){
	if(msg.action == 'message'){
		UI.appendMessage(msg);
		var msgDiv = document.getElementById("messages");
		msgDiv.scrollTop = msgDiv.scrollHeight;
		return true;
	}else if(msg.action == 'previous'){
		UI.appendMessages(msg);
		var msgDiv = document.getElementById("messages");
		msgDiv.scrollTop = msgDiv.scrollHeight;
		return true;
	}
}

function UserList(){
	this.list = [];
}

UserList.prototype = new EventEmitter();

UserList.prototype.newMessage = function(msg){
	switch(msg.action){
		case "join":
			this.list = this.list.concat(msg.users);
			this.emit('join', msg.users);
			break;
		case "part":
			this.list = this.list.concat(msg.users);
			this.emit('part', msg.users);
			break;
		case "who":
			this.list = msg.users;
			this.emit('who', this.list);
		default:
			return false;
	}
	return true;
}

function UserListUI(ul, container){
	var user_divs = {};

	ul.on('join', function(users){
		var names=[];
		$.each(users, function(i, user){
			addUser(user);
			names.push(user.name);
		});
		UI.systemMessage("Joined: " + names.join(', '));
	});

	ul.on('part', function(users){
		var names=[];
		$.each(users, function(i, user){
			removeUser(user);
			names.push(user.name);
		});
		UI.systemMessage("Left: " + names.join(', '));
	});

	ul.on('who', function(users){
		clearUserList();
		$.each(users, function(i, user){
			addUser(user);
		});
	});

	function addUser(user){
		var name_div = $('
');
		name_div.attr('id', 'user_' + user.id);
		name_div.attr('title', user.name);
		name_div.append(user.name);
		name_div.addClass('user');
		container.append(name_div);
		user_divs[user.id] = name_div;
	}

	function removeUser(user){
		if(user_divs[user.id]){
			user_divs[user.id].remove();
			delete user_divs[user.id];
		}
	}

	function clearUserList(){
		for(var i in user_divs){
			user_divs[i].remove();
		}
		user_divs = {};
	}
}
<|endoftext|>


<commit_before>const styles = require('./styles.js')
const Firebase = require('firebase');
const StatusBar = require('./components/StatusBar');
const ActionButton = require('./components/ActionButton');
const ListItem = require('./components/ListItem');
const { ListView, TextInput, Switch, SliderIOS, AlertIOS, DatePickerIOS, Picker, PickerIOS } = React;

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */
'use strict';
import React, {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  View
} from 'react-native';

import Form from 'react-native';

const FirebaseUrl = 'https://amber-inferno-9686.firebaseio.com/data';
var ref = new Firebase(FirebaseUrl);

class Survu extends Component {
  render() {
    return (
      <View style={styles.container}>

        <StatusBar title="Grocery List" />

        <ListView
          dataSource={this.state.dataSource}
          renderRow={this._renderItem.bind(this)}
          style={styles.listview}/>

          <ActionButton title="Add" onPress={this._newSurvey.bind(this)} />

      </View>
    );
  }

  constructor(props) {
    super(props);
    this.state = {
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      })
    };
  }

  _newSurvey() {
  var itemsRef = ref.child("anything");
  AlertIOS.prompt(
    'Start New Survey',
    null,
    [
      {
        text: 'Start',
        onPress: (text) => {
          itemsRef.push({ title: text })
        }
      },
    ],
    'plain-text'
  );
}

  _renderItem(item) {
    const onPress = () => {
      AlertIOS.alert(
        'Complete',
        null,
        [
          {text: 'Complete', onPress: (text) => this.itemsRef.child(item._key).remove()},
          {text: 'Cancel', onPress: (text) => console.log('Cancelled')}
        ],
        'default'
      );
    };
    return (
      <ListItem item={item} onPress={onPress} />
    );
  }

  componentDidMount() {
    this.setState({
      dataSource: this.state.dataSource.cloneWithRows([{ title: 'Pizza' }])
    })
  }

}

AppRegistry.registerComponent('Survu', () => Survu);
<commit_msg>form.js<commit_after>const styles = require('./styles.js')
const Firebase = require('firebase');
const StatusBar = require('./components/StatusBar');
const ActionButton = require('./components/ActionButton');
const ListItem = require('./components/ListItem');
const Form = require('./components/form')
const { ListView, TextInput, Switch, SliderIOS, AlertIOS, DatePickerIOS, Picker, PickerIOS } = React;

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */
'use strict';
import React, {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  View
} from 'react-native';

const FirebaseUrl = 'https://amber-inferno-9686.firebaseio.com/data';
var ref = new Firebase(FirebaseUrl);

class Survu extends Component {
  render() {
    return (
      <View style={styles.container}>

        <StatusBar title="Grocery List" />

        <ListView
          dataSource={this.state.dataSource}
          renderRow={this._renderItem.bind(this)}
          style={styles.listview}/>

          <ActionButton title="Add" onPress={this._newSurvey.bind(this)} />

      </View>
    );
  }

  constructor(props) {
    super(props);
    this.state = {
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      })
    };
  }

  _newSurvey() {
  var itemsRef = ref.child("anything");
  AlertIOS.prompt(
    'Start New Survey',
    null,
    [
      {
        text: 'Start',
        onPress: (text) => {
          itemsRef.push({ title: text })
        }
      },
    ],
    'plain-text'
  );
}

  _renderItem(item) {
    const onPress = () => {
      AlertIOS.alert(
        'Complete',
        null,
        [
          {text: 'Complete', onPress: (text) => this.itemsRef.child(item._key).remove()},
          {text: 'Cancel', onPress: (text) => console.log('Cancelled')}
        ],
        'default'
      );
    };
    return (
      <ListItem item={item} onPress={onPress} />
    );
  }

  componentDidMount() {
    this.setState({
      dataSource: this.state.dataSource.cloneWithRows([{ title: 'Pizza' }])
    })
  }

  // if the database code is valid

}

AppRegistry.registerComponent('Survu', () => Survu);
<|endoftext|>


<commit_before>/**
 * @author v.lugovsky
 * created on 16.12.2015
 */
(function() {
    'use strict';
    angular.module('BlurAdmin.pages', [
            'ui.router',
            'BlurAdmin.pages.sides',
            'BlurAdmin.pages.home',
            'BlurAdmin.pages.register',
            'BlurAdmin.pages.profile',
            'BlurAdmin.pages.viewReview',
            'BlurAdmin.pages.settings'
        ])
        .config(routeConfig);

    /** @ngInject */
    function routeConfig($urlRouterProvider, baSidebarServiceProvider) {
        $urlRouterProvider.otherwise('/signin');

    }

})();
<commit_msg>new module added<commit_after>/**
 * @author v.lugovsky
 * created on 16.12.2015
 */
(function() {
    'use strict';
    angular.module('BlurAdmin.pages', [
            'ui.router',
            'BlurAdmin.pages.sides',
            'BlurAdmin.pages.home',
            'BlurAdmin.pages.register',
            'BlurAdmin.pages.profile',
            'BlurAdmin.pages.viewReview',
            'BlurAdmin.pages.settings',
            'BlurAdmin.pages.viewtasks'
        ])
        .config(routeConfig);

    /** @ngInject */
    function routeConfig($urlRouterProvider, baSidebarServiceProvider) {
        $urlRouterProvider.otherwise('/signin');

    }

})();
<|endoftext|>


<commit_before>import { combineReducers } from 'redux'
import { routerReducer as routing } from 'react-router-redux'
import { reducer as formReducer } from 'redux-form'
import Immutable from 'immutable'
import moment from 'moment'

import * as Actions from '../actions'

function api(state = {}, action) {
  if (action.payload && action.payload.response) {
    return Object.assign({}, state, {[action.type]: action.payload.response})
  } else if (action.type.endsWith('_FAILURE') && Immutable.fromJS(action).getIn(['payload', 'error'])) {
    return Object.assign({}, state, {error: action.payload.error})
  } else if (action.type === Actions.DELETE_ERROR_ACTION) {
    return Immutable.fromJS(state).delete('error').toJS()
  }
  return state
}

const rootReducer = combineReducers({
  routing,
  api,
  form: formReducer.plugin({
    mockSettingForm: (state={}, action) => {
      if (action.type === Actions.CHANGE_SETTING_VALUE) {
        return {
          ...state,
          values: {
            ...state.values,
            [action.payload.name]: action.payload.value
          },
          fields: {
            ...state.fields,
            [action.payload.name]: undefined
          }
        }
      } else if (action.type === Actions.MOCK_SETTING_DEFINITION) {
        return {
          ...state,
          values: {
            ...Immutable.fromJS(action.payload.def.properties).map((v) => v.get('default')).toJS(),
          },
          fields: {
            ...state.fields
          }
        }
      }
      return state
    },
    timecardEntry: (state={values: {vacationType: 'NOTHING'}}, action) => {
      if (action.type === Actions.INITIALIZE_TIMECARD_ENTRY) {
        return {
          ...state,
          values: {
            ...state.values,
            ...action.payload
          },
          fields: {
            ...state.fields
          }
        }
      } else if (action.meta && action.meta.form === 'timecardEntry' && action.type === '@@redux-form/BLUR') {
        const entryDate = moment(state.values.entryDate).startOf('day')
        const value = (() => {
          if (isNaN(parseInt(action.payload, 10))) {
            return action.payload
          }
          if (action.payload.length === 1 || action.payload.length === 2) {
            return entryDate.clone().hour(action.payload).format('HH:mm')
          } else if (action.payload.length === 3) {
            return entryDate.clone().hour(action.payload[0]).minute(action.payload.substring(1)).format('HH:mm')
          } else if (action.payload.length === 4) {
            return entryDate.clone().hour(action.payload.substring(0, 2)).minute(action.payload.substring(2)).format('HH:mm')
          }
          return action.payload
        })()
        return {
          ...state,
          values: {
            ...state.values,
            [action.meta.field]: value
          },
          fields: {
            ...state.fields
          }
        }
      }
      return state
    }
  })
})

export default rootReducer
<commit_msg>モック設定用reducer削除<commit_after>import { combineReducers } from 'redux'
import { routerReducer as routing } from 'react-router-redux'
import { reducer as formReducer } from 'redux-form'
import Immutable from 'immutable'
import moment from 'moment'

import * as Actions from '../actions'

function api(state = {}, action) {
  if (action.payload && action.payload.response) {
    return Object.assign({}, state, {[action.type]: action.payload.response})
  } else if (action.type.endsWith('_FAILURE') && Immutable.fromJS(action).getIn(['payload', 'error'])) {
    return Object.assign({}, state, {error: action.payload.error})
  } else if (action.type === Actions.DELETE_ERROR_ACTION) {
    return Immutable.fromJS(state).delete('error').toJS()
  }
  return state
}

const rootReducer = combineReducers({
  routing,
  api,
  form: formReducer.plugin({
    timecardEntry: (state={values: {vacationType: 'NOTHING'}}, action) => {
      if (action.type === Actions.INITIALIZE_TIMECARD_ENTRY) {
        return {
          ...state,
          values: {
            ...state.values,
            ...action.payload
          },
          fields: {
            ...state.fields
          }
        }
      } else if (action.meta && action.meta.form === 'timecardEntry' && action.type === '@@redux-form/BLUR') {
        const entryDate = moment(state.values.entryDate).startOf('day')
        const value = (() => {
          if (isNaN(parseInt(action.payload, 10))) {
            return action.payload
          }
          if (action.payload.length === 1 || action.payload.length === 2) {
            return entryDate.clone().hour(action.payload).format('HH:mm')
          } else if (action.payload.length === 3) {
            return entryDate.clone().hour(action.payload[0]).minute(action.payload.substring(1)).format('HH:mm')
          } else if (action.payload.length === 4) {
            return entryDate.clone().hour(action.payload.substring(0, 2)).minute(action.payload.substring(2)).format('HH:mm')
          }
          return action.payload
        })()
        return {
          ...state,
          values: {
            ...state.values,
            [action.meta.field]: value
          },
          fields: {
            ...state.fields
          }
        }
      }
      return state
    }
  })
})

export default rootReducer
<|endoftext|>