<commit_before>import './Site.css';

import React from 'react';
import AngleRightIcon from 'react-icons/lib/fa/angle-right';
import AngleLeftIcon from 'react-icons/lib/fa/angle-left';

import * as ReactUI from '../src/index';
import * as Nav from '../src/topNav';
import {Block} from '../src/index';

function Item({children}) {
  return (
    <Block inline marginRight="x-small">
      {children}
    </Block>
  );
}

function Items({children}) {
  return <Block marginBottom="small">{children}</Block>;
}

class InputDemo extends React.Component {

  constructor(props) {
    super(props);
    this.state = {value: ''};
  }

  render() {
    let {value} = this.state;
    let {children} = this.props;
    return (
      <Block marginBottom="small">
        <Block marginBottom="x-small">
          {React.cloneElement(children, {onChange: this.onChange, value})}
        </Block>
        <Block>

{JSON.stringify(value)}

        </Block>
      </Block>
    );
  }

  onChange = value => {
    if (value && value.target) {
      value = value.target.value;
    }
    this.setState({value});
  };
}

function DemoSection({title, children}) {
  return (
    <Block marginBottom="large">

{title}

      <Block>{children}</Block>
    </Block>
  );
}

function DemoVariant({title, children}) {
  return (
    <Block marginBottom="medium">

{title}

      <Block>{children}</Block>
    </Block>
  );
}

function DemoButtonVariants({Button}) {
  return (
    <Items>
      <Item>
        <Button size="small">Button</Button>
      </Item>
      <Item>
        <Button size="small" variant={{hover: true}}>
          Button
        </Button>
      </Item>
      <Item>
        <Button size="small" variant={{focus: true}}>
          Button
        </Button>
      </Item>
      <Item>
        <Button size="small" variant={{active: true}}>
          Button
        </Button>
      </Item>
      <Item>
        <Button size="small" disabled>
          Button
        </Button>
      </Item>

    </Items>
  );
}

function DemoButtonSizes({Button}) {
  return (
    <Items>
      <Item>
        <Button size="small">Button</Button>
      </Item>
      <Item>
        <Button size="normal">Button</Button>
      </Item>
      <Item>
        <Button size="large">Button</Button>
      </Item>
    </Items>
  );
}

function DemoButtonGroup({children, disabled = []}) {
  if (!Array.isArray(disabled)) {
    disabled = [disabled];
  }
  return (
    <Items>
      <Item>
        {React.cloneElement(children, {
          children: 'Left',
          disabled: disabled.indexOf('left') > -1,
          groupHorizontally: true})}
        {React.cloneElement(children, {
          children: 'Center',
          disabled: disabled.indexOf('center') > -1,
          groupHorizontally: true})}
        {React.cloneElement(children, {
          children: 'Right',
          disabled: disabled.indexOf('right') > -1,
          groupHorizontally: true})}
      </Item>
    </Items>
  );
}

export default function Site() {
  return (
    <Block>
      <Nav.Navigation
        title="React UI"
        menu={[
          Home,
          Layout,
          <Nav.PrimaryMenu key="ui"
            items={[
              Button
            ]}
            >
            UI

        ]}
        />
      <Block padding="medium">
        <DemoSection title="Button">

          <DemoVariant title="Size">
            <DemoButtonSizes Button={ReactUI.Button} />
          </DemoVariant>

          <DemoVariant title="States">
            <DemoButtonVariants Button={ReactUI.Button} />
          </DemoVariant>

          <DemoVariant title="<FlatButton />">
            <DemoButtonSizes Button={ReactUI.FlatButton} />
            <DemoButtonVariants Button={ReactUI.FlatButton} />
          </DemoVariant>

          <DemoVariant title="<QuietButton />">
            <DemoButtonSizes Button={ReactUI.QuietButton} />
            <DemoButtonVariants Button={ReactUI.QuietButton} />
          </DemoVariant>

          <DemoVariant title="<SuccessButton />">
            <DemoButtonSizes Button={ReactUI.SuccessButton} />
            <DemoButtonVariants Button={ReactUI.SuccessButton} />
          </DemoVariant>

          <DemoVariant title="<DangerButton />">
            <DemoButtonSizes Button={ReactUI.DangerButton} />
            <DemoButtonVariants Button={ReactUI.DangerButton} />
          </DemoVariant>

          <DemoVariant title="<FlatSuccessButton />">
            <DemoButtonSizes Button={ReactUI.FlatSuccessButton} />
            <DemoButtonVariants Button={ReactUI.FlatSuccessButton} />
          </DemoVariant>

          <DemoVariant title="<FlatDangerButton />">
            <DemoButtonSizes Button={ReactUI.FlatDangerButton} />
            <DemoButtonVariants Button={ReactUI.FlatDangerButton} />
          </DemoVariant>

          <DemoVariant title="Button as a link">
            <Items>
              <Item>
                <ReactUI.Button size="small" href="/">Go home</ReactUI.Button>
              </Item>
              <Item>
                <ReactUI.FlatButton size="small" href="/">Go home</ReactUI.FlatButton>
              </Item>
              <Item>
                <ReactUI.QuietButton size="small" href="/">Go home</ReactUI.QuietButton>
              </Item>
          </Items>
          </DemoVariant>

        </DemoSection>

        <DemoSection title="Button group">

          <DemoButtonGroup>
            <ReactUI.Button size="small" />
          </DemoButtonGroup>

          <DemoButtonGroup>
            <ReactUI.Button size="normal" />
          </DemoButtonGroup>

          <DemoVariant title="Disabled buttons">
            <DemoButtonGroup disabled="left">
              <ReactUI.Button size="normal" />
            </DemoButtonGroup>

            <DemoButtonGroup disabled="center">
              <ReactUI.Button size="normal" />
            </DemoButtonGroup>

            <DemoButtonGroup disabled="right">
              <ReactUI.Button size="normal" />
            </DemoButtonGroup>
          </DemoVariant>

          <DemoVariant title="With <FlatButton />">
            <DemoButtonGroup>
              <ReactUI.FlatButton size="small" />
            </DemoButtonGroup>

            <DemoButtonGroup>
              <ReactUI.FlatButton size="normal" />
            </DemoButtonGroup>
          </DemoVariant>

          <DemoVariant title="With <FlatButton /> with Disabled buttons">
            <DemoButtonGroup disabled="left">
              <ReactUI.FlatButton size="normal" />
            </DemoButtonGroup>

            <DemoButtonGroup disabled="center">
              <ReactUI.FlatButton size="normal" />
            </DemoButtonGroup>

            <DemoButtonGroup disabled="right">
              <ReactUI.FlatButton size="normal" />
            </DemoButtonGroup>
          </DemoVariant>

          <DemoButtonGroup>
            <ReactUI.QuietButton size="normal" />
          </DemoButtonGroup>

          <DemoButtonGroup>
            <ReactUI.SuccessButton size="normal" />
          </DemoButtonGroup>

          <DemoButtonGroup>
            <ReactUI.DangerButton size="normal" />
          </DemoButtonGroup>

          <Items>
            <Item>
              <ReactUI.Button groupHorizontally icon={<AngleLeftIcon />}>
                Left
              </ReactUI.Button>
              <ReactUI.Button groupHorizontally>
                Center
              </ReactUI.Button>
              <ReactUI.Button groupHorizontally icon={<AngleRightIcon />}>
                Right
              </ReactUI.Button>
            </Item>
          </Items>

          <Items>
            <Item>
              <ReactUI.Button size="small" groupHorizontally icon={<AngleLeftIcon />}>
                Left
              </ReactUI.Button>
              <ReactUI.Button size="small" groupHorizontally>
                Center
              </ReactUI.Button>
              <ReactUI.Button size="small" groupHorizontally icon={<AngleRightIcon />}>
                Right
              </ReactUI.Button>
            </Item>
          </Items>

          <Items>
            <Item>
              <ReactUI.FlatButton groupHorizontally icon={<AngleLeftIcon />}>
                Left
              </ReactUI.FlatButton>
              <ReactUI.FlatButton groupHorizontally>
                Center
              </ReactUI.FlatButton>
              <ReactUI.FlatButton groupHorizontally icon={<AngleRightIcon />}>
                Right
              </ReactUI.FlatButton>
            </Item>
          </Items>

          <Items>
            <Item>
              <ReactUI.FlatButton size="small" groupHorizontally icon={<AngleLeftIcon />}>
                Left
              </ReactUI.FlatButton>
              <ReactUI.FlatButton size="small" groupHorizontally>
                Center
              </ReactUI.FlatButton>
              <ReactUI.FlatButton size="small" groupHorizontally icon={<AngleRightIcon />}>
                Right
              </ReactUI.FlatButton>
            </Item>
          </Items>

        </DemoSection>

        <DemoSection title="Button with icons">
          <Items>
            <ReactUI.Button groupHorizontally icon={<AngleLeftIcon />}>
              Prev
            </ReactUI.Button>
            <ReactUI.Button groupHorizontally iconRight={<AngleRightIcon />}>
              Next
            </ReactUI.Button>
          </Items>
          <Items>
            <ReactUI.Button size="small" groupHorizontally icon={<AngleLeftIcon />}>
              Prev
            </ReactUI.Button>
            <ReactUI.Button size="small" groupHorizontally iconRight={<AngleRightIcon />}>
              Next
            </ReactUI.Button>
          </Items>
          <Items>
            <ReactUI.Button groupHorizontally icon={<AngleLeftIcon />} />
            <ReactUI.Button groupHorizontally icon={<AngleRightIcon />} />
          </Items>
        </DemoSection>

        <DemoSection title="Checkbox">
          <Items>
            <Item>
              <ReactUI.Checkbox label="Not checked" value={false} />
            </Item>
            <Item>
              <ReactUI.Checkbox label="Checked" value={true} />
            </Item>
            <Item>
              <ReactUI.Checkbox label="Checked" value={true} disabled />
            </Item>
            <Item>
              <ReactUI.Checkbox label="Checked" value={false} disabled />
            </Item>
          </Items>
        </DemoSection>

        <DemoSection title="Checkbox group">
          <DemoVariant title="Vertical layout">
            <ReactUI.CheckboxGroup
              options={[
                {label: 'Dog', value: 'dog'},
                {label: 'Cat', value: 'cat'}]}
              value={['cat']}
              />
          </DemoVariant>
          <DemoVariant title="Horizontal layout">
            <ReactUI.CheckboxGroup
              layout="horizontal"
              options={[
                {label: 'Dog', value: 'dog'},
                {label: 'Cat', value: 'cat'}]}
              value={['cat']}
              />
          </DemoVariant>

          <DemoVariant title="Disabled">
            <ReactUI.CheckboxGroup
              disabled
              options={[
                {label: 'Dog', value: 'dog'},
                {label: 'Cat', value: 'cat'}]}
              value={['cat']}
              />
          </DemoVariant>

        </DemoSection>

        <DemoSection title="Radiogroup">

          <DemoVariant title="Vertical layout">
            <ReactUI.RadioGroup
              options={[
                {label: 'Dog', value: 'dog'},
                {label: 'Cat', value: 'cat'}]}
              value="cat"
              />
          </DemoVariant>

          <DemoVariant title="Horizontal layout">
            <ReactUI.RadioGroup
              layout="horizontal"
              options={[
                {label: 'Dog', value: 'dog'},
                {label: 'Cat', value: 'cat'}]}
              value="cat"
              />
          </DemoVariant>

          <DemoVariant title="Disabled state">
            <ReactUI.RadioGroup
              layout="horizontal"
              disabled
              options={[
                {label: 'Dog', value: 'dog'},
                {label: 'Cat', value: 'cat'}]}
              value="cat"
              />
          </DemoVariant>
        </DemoSection>

        <DemoSection title="<Input />">
          <Items>
            <InputDemo>
              <ReactUI.Input />
            </InputDemo>
          </Items>
          <Items>
            <ReactUI.Input variant={{focus: true}} />
          </Items>
          <Items>
            <ReactUI.Input variant={{error: true}} />
          </Items>
          <Items>
            <ReactUI.Input variant={{error: true, focus: true}} />
          </Items>
          <Items>
            <ReactUI.Input disabled />
          </Items>
        </DemoSection>

        <DemoSection title="<NumberInput />">
          <InputDemo>
            <ReactUI.NumberInput />
          </InputDemo>
        </DemoSection>

        <DemoSection title="<Textarea />">
          <Items>
            <ReactUI.Textarea />
          </Items>
          <Items>
            <ReactUI.Textarea variant={{error: true}} />
          </Items>
          <Items>
            <ReactUI.Textarea disabled />
          </Items>
        </DemoSection>

        <DemoSection title="<Card />">

          <DemoVariant title="<Card />">
            <ReactUI.Card padding="x-small">
              Children
            </ReactUI.Card>
          </DemoVariant>

          <DemoVariant title="<Card header={...} />">
            <ReactUI.Card header="Title" padding="x-small">
              Children
            </ReactUI.Card>
          </DemoVariant>

          <DemoVariant title="<Card header={...} footer={...} />">
            <ReactUI.Card
              header="Title"
              footer={<ReactUI.FlatButton size="small">Submit</ReactUI.FlatButton>}
              padding="x-small">
              Children
            </ReactUI.Card>
          </DemoVariant>

          <DemoVariant title="<Card variant={{success: true}} />">
            <ReactUI.Card padding="x-small" variant={{success: true}}>
              Children
            </ReactUI.Card>
          </DemoVariant>

          <DemoVariant title="<Card variant={{success: true}} header={...} />">
            <ReactUI.Card variant={{success: true}} header="Title" padding="x-small">
              Children
            </ReactUI.Card>
          </DemoVariant>

        </DemoSection>

        <DemoSection title="<Menu />">
          <ReactUI.Card width={300}>
            <ReactUI.Block paddingH="small" marginTop="small">
              <ReactUI.LabelText>Menu</ReactUI.LabelText>
            </ReactUI.Block>
            <ReactUI.Block marginV="x-small">
              <ReactUI.QuietButton
                attach={{left: true, right: true}}
                width="100%"
                textAlign="left">
                First item
              </ReactUI.QuietButton>
              <ReactUI.QuietButton
                attach={{left: true, right: true}}
                width="100%"
                textAlign="left">
                Second item
              </ReactUI.QuietButton>
              <ReactUI.QuietButton
                attach={{left: true, right: true}}
                width="100%"
                textAlign="left">
                Third item
              </ReactUI.QuietButton>
            </ReactUI.Block>
          </ReactUI.Card>
        </DemoSection>

        <DemoSection title="<ProgressBar />">
          <ReactUI.Block maxWidth={300}>
            <Items>
              <ReactUI.ProgressBar progress={0} />
            </Items>
            <Items>
              <ReactUI.ProgressBar progress={0.2334234} />
            </Items>
            <Items>
              <ReactUI.ProgressBar progress={0.49} />
            </Items>
            <Items>
              <ReactUI.ProgressBar progress={0.76} />
            </Items>
            <Items>
              <ReactUI.ProgressBar progress={1} />
            </Items>
          </ReactUI.Block>
        </DemoSection>

      </Block>
    </Block>
  );
}
<commit_msg>doc: rtl example for button groups<commit_after>import './Site.css';

import React from 'react';
import AngleRightIcon from 'react-icons/lib/fa/angle-right';
import AngleLeftIcon from 'react-icons/lib/fa/angle-left';

import * as ReactUI from '../src/index';
import * as Nav from '../src/topNav';
import {Block} from '../src/index';

function Item({children}) {
  return (
    <Block inline marginRight="x-small">
      {children}
    </Block>
  );
}

function Items({children}) {
  return <Block marginBottom="small">{children}</Block>;
}

class InputDemo extends React.Component {

  constructor(props) {
    super(props);
    this.state = {value: ''};
  }

  render() {
    let {value} = this.state;
    let {children} = this.props;
    return (
      <Block marginBottom="small">
        <Block marginBottom="x-small">
          {React.cloneElement(children, {onChange: this.onChange, value})}
        </Block>
        <Block>

{JSON.stringify(value)}

        </Block>
      </Block>
    );
  }

  onChange = value => {
    if (value && value.target) {
      value = value.target.value;
    }
    this.setState({value});
  };
}

function DemoSection({title, children}) {
  return (
    <Block marginBottom="large">

{title}

      <Block>{children}</Block>
    </Block>
  );
}

function DemoVariant({title, children}) {
  return (
    <Block marginBottom="medium">

{title}

      <Block>{children}</Block>
    </Block>
  );
}

function DemoButtonVariants({Button}) {
  return (
    <Items>
      <Item>
        <Button size="small">Button</Button>
      </Item>
      <Item>
        <Button size="small" variant={{hover: true}}>
          Button
        </Button>
      </Item>
      <Item>
        <Button size="small" variant={{focus: true}}>
          Button
        </Button>
      </Item>
      <Item>
        <Button size="small" variant={{active: true}}>
          Button
        </Button>
      </Item>
      <Item>
        <Button size="small" disabled>
          Button
        </Button>
      </Item>

    </Items>
  );
}

function DemoButtonSizes({Button}) {
  return (
    <Items>
      <Item>
        <Button size="small">Button</Button>
      </Item>
      <Item>
        <Button size="normal">Button</Button>
      </Item>
      <Item>
        <Button size="large">Button</Button>
      </Item>
    </Items>
  );
}

function DemoButtonGroup({children, disabled = []}) {
  if (!Array.isArray(disabled)) {
    disabled = [disabled];
  }
  return (
    <Items>
      <Item>
        {React.cloneElement(children, {
          children: 'Left',
          disabled: disabled.indexOf('left') > -1,
          groupHorizontally: true})}
        {React.cloneElement(children, {
          children: 'Center',
          disabled: disabled.indexOf('center') > -1,
          groupHorizontally: true})}
        {React.cloneElement(children, {
          children: 'Right',
          disabled: disabled.indexOf('right') > -1,
          groupHorizontally: true})}
      </Item>
    </Items>
  );
}

export default function Site() {
  return (
    <Block>
      <Nav.Navigation
        title="React UI"
        menu={[
          Home,
          Layout,
          <Nav.PrimaryMenu key="ui"
            items={[
              Button
            ]}
            >
            UI

        ]}
        />
      <Block padding="medium">
        <DemoSection title="Button">

          <DemoVariant title="Size">
            <DemoButtonSizes Button={ReactUI.Button} />
          </DemoVariant>

          <DemoVariant title="States">
            <DemoButtonVariants Button={ReactUI.Button} />
          </DemoVariant>

          <DemoVariant title="<FlatButton />">
            <DemoButtonSizes Button={ReactUI.FlatButton} />
            <DemoButtonVariants Button={ReactUI.FlatButton} />
          </DemoVariant>

          <DemoVariant title="<QuietButton />">
            <DemoButtonSizes Button={ReactUI.QuietButton} />
            <DemoButtonVariants Button={ReactUI.QuietButton} />
          </DemoVariant>

          <DemoVariant title="<SuccessButton />">
            <DemoButtonSizes Button={ReactUI.SuccessButton} />
            <DemoButtonVariants Button={ReactUI.SuccessButton} />
          </DemoVariant>

          <DemoVariant title="<DangerButton />">
            <DemoButtonSizes Button={ReactUI.DangerButton} />
            <DemoButtonVariants Button={ReactUI.DangerButton} />
          </DemoVariant>

          <DemoVariant title="<FlatSuccessButton />">
            <DemoButtonSizes Button={ReactUI.FlatSuccessButton} />
            <DemoButtonVariants Button={ReactUI.FlatSuccessButton} />
          </DemoVariant>

          <DemoVariant title="<FlatDangerButton />">
            <DemoButtonSizes Button={ReactUI.FlatDangerButton} />
            <DemoButtonVariants Button={ReactUI.FlatDangerButton} />
          </DemoVariant>

          <DemoVariant title="Button as a link">
            <Items>
              <Item>
                <ReactUI.Button size="small" href="/">Go home</ReactUI.Button>
              </Item>
              <Item>
                <ReactUI.FlatButton size="small" href="/">Go home</ReactUI.FlatButton>
              </Item>
              <Item>
                <ReactUI.QuietButton size="small" href="/">Go home</ReactUI.QuietButton>
              </Item>
          </Items>
          </DemoVariant>

        </DemoSection>

        <DemoSection title="Button group">

          <DemoButtonGroup>
            <ReactUI.Button size="small" />
          </DemoButtonGroup>

          <DemoButtonGroup>
            <ReactUI.Button size="normal" />
          </DemoButtonGroup>

          <DemoVariant title="Disabled buttons">
            <DemoButtonGroup disabled="left">
              <ReactUI.Button size="normal" />
            </DemoButtonGroup>

            <DemoButtonGroup disabled="center">
              <ReactUI.Button size="normal" />
            </DemoButtonGroup>

            <DemoButtonGroup disabled="right">
              <ReactUI.Button size="normal" />
            </DemoButtonGroup>
          </DemoVariant>

          <DemoVariant title="With <FlatButton />">
            <DemoButtonGroup>
              <ReactUI.FlatButton size="small" />
            </DemoButtonGroup>

            <DemoButtonGroup>
              <ReactUI.FlatButton size="normal" />
            </DemoButtonGroup>
          </DemoVariant>

          <DemoVariant title="With <FlatButton /> with Disabled buttons">
            <DemoButtonGroup disabled="left">
              <ReactUI.FlatButton size="normal" />
            </DemoButtonGroup>

            <DemoButtonGroup disabled="center">
              <ReactUI.FlatButton size="normal" />
            </DemoButtonGroup>

            <DemoButtonGroup disabled="right">
              <ReactUI.FlatButton size="normal" />
            </DemoButtonGroup>
          </DemoVariant>

          <DemoButtonGroup>
            <ReactUI.QuietButton size="normal" />
          </DemoButtonGroup>

          <DemoButtonGroup>
            <ReactUI.SuccessButton size="normal" />
          </DemoButtonGroup>

          <DemoButtonGroup>
            <ReactUI.DangerButton size="normal" />
          </DemoButtonGroup>

          <Items>
            <Item>
              <ReactUI.Button groupHorizontally icon={<AngleLeftIcon />}>
                Left
              </ReactUI.Button>
              <ReactUI.Button groupHorizontally>
                Center
              </ReactUI.Button>
              <ReactUI.Button groupHorizontally icon={<AngleRightIcon />}>
                Right
              </ReactUI.Button>
            </Item>
          </Items>

          <Items>
            <Item>
              <ReactUI.Button size="small" groupHorizontally icon={<AngleLeftIcon />}>
                Left
              </ReactUI.Button>
              <ReactUI.Button size="small" groupHorizontally>
                Center
              </ReactUI.Button>
              <ReactUI.Button size="small" groupHorizontally icon={<AngleRightIcon />}>
                Right
              </ReactUI.Button>
            </Item>
          </Items>

          <Items>
            <Item>
              <ReactUI.FlatButton groupHorizontally icon={<AngleLeftIcon />}>
                Left
              </ReactUI.FlatButton>
              <ReactUI.FlatButton groupHorizontally>
                Center
              </ReactUI.FlatButton>
              <ReactUI.FlatButton groupHorizontally icon={<AngleRightIcon />}>
                Right
              </ReactUI.FlatButton>
            </Item>
          </Items>

          <Items>
            <Item>
              <ReactUI.FlatButton size="small" groupHorizontally icon={<AngleLeftIcon />}>
                Left
              </ReactUI.FlatButton>
              <ReactUI.FlatButton size="small" groupHorizontally>
                Center
              </ReactUI.FlatButton>
              <ReactUI.FlatButton size="small" groupHorizontally icon={<AngleRightIcon />}>
                Right
              </ReactUI.FlatButton>
            </Item>
          </Items>

        </DemoSection>

        <DemoSection title="Button with icons">
          <Items>
            <ReactUI.Button groupHorizontally icon={<AngleLeftIcon />}>
              Prev
            </ReactUI.Button>
            <ReactUI.Button groupHorizontally iconAlt={<AngleRightIcon />}>
              Next
            </ReactUI.Button>
          </Items>
          <Items>
            <ReactUI.Button size="small" groupHorizontally icon={<AngleLeftIcon />}>
              Prev
            </ReactUI.Button>
            <ReactUI.Button size="small" groupHorizontally iconAlt={<AngleRightIcon />}>
              Next
            </ReactUI.Button>
          </Items>
          <Items>
            <ReactUI.Button groupHorizontally icon={<AngleLeftIcon />} />
            <ReactUI.Button groupHorizontally icon={<AngleRightIcon />} />
          </Items>
        </DemoSection>

        <DemoSection title="Button with icons (RTL)">
          <ReactUI.I18N.I18N dir="rtl">
            <Items>
              <ReactUI.Button groupHorizontally icon={<AngleLeftIcon />}>
                Prev
              </ReactUI.Button>
              <ReactUI.Button groupHorizontally iconAlt={<AngleRightIcon />}>
                Next
              </ReactUI.Button>
            </Items>
            <Items>
              <ReactUI.Button size="small" groupHorizontally icon={<AngleLeftIcon />}>
                Prev
              </ReactUI.Button>
              <ReactUI.Button size="small" groupHorizontally iconAlt={<AngleRightIcon />}>
                Next
              </ReactUI.Button>
            </Items>
            <Items>
              <ReactUI.Button groupHorizontally icon={<AngleLeftIcon />} />
              <ReactUI.Button groupHorizontally icon={<AngleRightIcon />} />
            </Items>
          </ReactUI.I18N.I18N>
        </DemoSection>

        <DemoSection title="Checkbox">
          <Items>
            <Item>
              <ReactUI.Checkbox label="Not checked" value={false} />
            </Item>
            <Item>
              <ReactUI.Checkbox label="Checked" value={true} />
            </Item>
            <Item>
              <ReactUI.Checkbox label="Checked" value={true} disabled />
            </Item>
            <Item>
              <ReactUI.Checkbox label="Checked" value={false} disabled />
            </Item>
          </Items>
        </DemoSection>

        <DemoSection title="Checkbox group">
          <DemoVariant title="Vertical layout">
            <ReactUI.CheckboxGroup
              options={[
                {label: 'Dog', value: 'dog'},
                {label: 'Cat', value: 'cat'}]}
              value={['cat']}
              />
          </DemoVariant>
          <DemoVariant title="Horizontal layout">
            <ReactUI.CheckboxGroup
              layout="horizontal"
              options={[
                {label: 'Dog', value: 'dog'},
                {label: 'Cat', value: 'cat'}]}
              value={['cat']}
              />
          </DemoVariant>

          <DemoVariant title="Disabled">
            <ReactUI.CheckboxGroup
              disabled
              options={[
                {label: 'Dog', value: 'dog'},
                {label: 'Cat', value: 'cat'}]}
              value={['cat']}
              />
          </DemoVariant>

        </DemoSection>

        <DemoSection title="Radiogroup">

          <DemoVariant title="Vertical layout">
            <ReactUI.RadioGroup
              options={[
                {label: 'Dog', value: 'dog'},
                {label: 'Cat', value: 'cat'}]}
              value="cat"
              />
          </DemoVariant>

          <DemoVariant title="Horizontal layout">
            <ReactUI.RadioGroup
              layout="horizontal"
              options={[
                {label: 'Dog', value: 'dog'},
                {label: 'Cat', value: 'cat'}]}
              value="cat"
              />
          </DemoVariant>

          <DemoVariant title="Disabled state">
            <ReactUI.RadioGroup
              layout="horizontal"
              disabled
              options={[
                {label: 'Dog', value: 'dog'},
                {label: 'Cat', value: 'cat'}]}
              value="cat"
              />
          </DemoVariant>
        </DemoSection>

        <DemoSection title="<Input />">
          <Items>
            <InputDemo>
              <ReactUI.Input />
            </InputDemo>
          </Items>
          <Items>
            <ReactUI.Input variant={{focus: true}} />
          </Items>
          <Items>
            <ReactUI.Input variant={{error: true}} />
          </Items>
          <Items>
            <ReactUI.Input variant={{error: true, focus: true}} />
          </Items>
          <Items>
            <ReactUI.Input disabled />
          </Items>
        </DemoSection>

        <DemoSection title="<NumberInput />">
          <InputDemo>
            <ReactUI.NumberInput />
          </InputDemo>
        </DemoSection>

        <DemoSection title="<Textarea />">
          <Items>
            <ReactUI.Textarea />
          </Items>
          <Items>
            <ReactUI.Textarea variant={{error: true}} />
          </Items>
          <Items>
            <ReactUI.Textarea disabled />
          </Items>
        </DemoSection>

        <DemoSection title="<Card />">

          <DemoVariant title="<Card />">
            <ReactUI.Card padding="x-small">
              Children
            </ReactUI.Card>
          </DemoVariant>

          <DemoVariant title="<Card header={...} />">
            <ReactUI.Card header="Title" padding="x-small">
              Children
            </ReactUI.Card>
          </DemoVariant>

          <DemoVariant title="<Card header={...} footer={...} />">
            <ReactUI.Card
              header="Title"
              footer={<ReactUI.FlatButton size="small">Submit</ReactUI.FlatButton>}
              padding="x-small">
              Children
            </ReactUI.Card>
          </DemoVariant>

          <DemoVariant title="<Card variant={{success: true}} />">
            <ReactUI.Card padding="x-small" variant={{success: true}}>
              Children
            </ReactUI.Card>
          </DemoVariant>

          <DemoVariant title="<Card variant={{success: true}} header={...} />">
            <ReactUI.Card variant={{success: true}} header="Title" padding="x-small">
              Children
            </ReactUI.Card>
          </DemoVariant>

        </DemoSection>

        <DemoSection title="<Menu />">
          <ReactUI.Card width={300}>
            <ReactUI.Block paddingH="small" marginTop="small">
              <ReactUI.LabelText>Menu</ReactUI.LabelText>
            </ReactUI.Block>
            <ReactUI.Block marginV="x-small">
              <ReactUI.QuietButton
                attach={{left: true, right: true}}
                width="100%"
                textAlign="left">
                First item
              </ReactUI.QuietButton>
              <ReactUI.QuietButton
                attach={{left: true, right: true}}
                width="100%"
                textAlign="left">
                Second item
              </ReactUI.QuietButton>
              <ReactUI.QuietButton
                attach={{left: true, right: true}}
                width="100%"
                textAlign="left">
                Third item
              </ReactUI.QuietButton>
            </ReactUI.Block>
          </ReactUI.Card>
        </DemoSection>

        <DemoSection title="<ProgressBar />">
          <ReactUI.Block maxWidth={300}>
            <Items>
              <ReactUI.ProgressBar progress={0} />
            </Items>
            <Items>
              <ReactUI.ProgressBar progress={0.2334234} />
            </Items>
            <Items>
              <ReactUI.ProgressBar progress={0.49} />
            </Items>
            <Items>
              <ReactUI.ProgressBar progress={0.76} />
            </Items>
            <Items>
              <ReactUI.ProgressBar progress={1} />
            </Items>
          </ReactUI.Block>
        </DemoSection>

      </Block>
    </Block>
  );
}
<|endoftext|>


<commit_before>describe("Do the Jasmine tests even work", function(){
  it("works", function(){
    expect(true).toEqual(true);
  });
});

// OK whew

describe("Game", function(){
  it("exists", function(){
    var game = new Game("0020200000000000");
    expect(game).toEqual(jasmine.any(Game));
  });

  it("has a default board string", function(){
    var game = new Game();
    expect(game.board_string).toEqual("0020200000000000")
  });

  it("has 16 cell values (ie digits)", function(){
    var game = new Game();
    expect(game.board_string.length).toEqual(15)
  });
});
<commit_msg>New tests<commit_after>describe("Do the Jasmine tests even work", function(){
  it("works", function(){
    expect(true).toEqual(true);
  });
});

// OK whew

describe("Game", function(){
  it("exists", function(){
    var game = new Game("0020200000000000");
    expect(game).toEqual(jasmine.any(Game));
  });

  it("has a default board string", function(){
    var game = new Game();
    expect(game.board_string).toEqual("0020200000000000")
  });

  it("has 16 cell values (ie digits)", function(){
    var game = new Game();
    expect(game.board_string.length).toEqual(16)
  });

  it("", function(){

  })
});
<|endoftext|>


<commit_before>(function($) {
      devsite.devsite.Init($, {'FULL_SITE_SEARCH_ENABLED': 1, 'ENABLE_BLOCKED_VIDEO_PLACEHOLDER': 0, 'VERSION_HASH': '0000000000', 'SITE_NAME': 'Paramour', 'HISTORY_ENABLED': 1, 'SUBPATH': '', 'ENABLE_BLOCKED_LINK_TOOLTIP': 0, 'ALLOWED_HOSTS': ['.github.io'], 'BLOCK_RSS_FEEDS': 0, 'SCRIPTSAFE_DOMAIN': '.github.io'},
'[]', 'en',
true, '',
{"00000000000000000000000000000000": false},
'/',
'https://ephellon.github.io/Paramour/');

  var timer, blink = false, last = {}, ltr = $("html").css(["writing-mode"]), isJS = false,
      swapicon = $("#swapButton span > div.docs-icon-redo, #swapButton span > div.docs-icon-undo"),
      runicons = $("#runButton div.docs-icon-run, #runButton div.docs-icon-debug"),
      icons = {
        swap: ["docs-icon-undo", "docs-icon-redo"],
        run: ["docs-icon-run", "docs-icon-debug"]
      },
      last_active, display, tinyurl, Paramour = Paramour || window.Paramour;

  if(Paramour == undefined)
    Paramour = function(string){return string};

  ltr = (ltr == "" || ltr == "vertical-lr");
  tinyurl = tinyurl || window.tinyurl;

  function swapIcons(element, pack, bool) {
    bool = bool || false;
    return element
      .toggleClass(icons[pack][0], bool)
      .toggleClass(icons[pack][1], !bool);
  }

  function encodeHTML(string) {
    return string.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
  }

  function decodeHTML(string) {
    return string.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
  }

  function getCurrent(index) {
    return last_active = (last_active == undefined)?
      $(".pretty-input > textarea.active, .pretty-input > textarea.last-active, .pretty-input > textarea").slice(0, 1):
    (last_active instanceof $)?
      last_active:
    $(last_active),
      display = last_active.siblings(".prettyprint"),
      (index != undefined && index != null)? (display = display[index], last_active[index]): last_active;
  }

  function updateCursor() {
    var textarea  = getCurrent(0),
        start     = textarea.selectionStart,
        end       = textarea.selectionEnd,
        value     = textarea.value || "",
        length    = value.length,
        direction = textarea.selectionDirection;

    if(direction == undefined || direction == null)
      direction = ((last.start > start || end < last.end) && ltr)? "left": "right";
    else
      direction = (direction != "forward" && ltr)? "left": "right";

    if((last.start = start) == (last.end = end))
      return encodeHTML(value.slice(0, start)) +
        '' +
        encodeHTML(value.slice(end, length));
    else
      return encodeHTML(value.slice(0, start)) +
        '' +
        encodeHTML(value.slice(start, end)) +
        '' +
        encodeHTML(value.slice(end, length));
  }

  function updateDisplay() {
    return updateCursor() + "
";
  }

  function updateHTML() {
    clearTimeout(timer);
    timer = setTimeout(function() {
      getCurrent();
      display.html(updateDisplay);
      prettyPrint();
    }, 100);
  }

  $(".pretty-input > textarea")
  .on("keyup", function(event) {
    updateHTML();
  })
  .on("mousemove", updateHTML)
  .on("mousedown", updateHTML)
  .on("scroll", function(event) {
    var T = "scrollTop", L = "scrollLeft",
        t = getCurrent(0), s = display,
        a = t[T], b = t[L], o = {};

    if(a == (last[t]||o)[T] && b == (last[t]||o)[L])
      return;
    else
      s[T] = a, s[L] = b;

    if(a > s[T])
      last[T] = t[T] = s[T] - 1;
    if(b > s[L])
      last[L] = t[L] = s[L] - 1;
  })
  .on("focus", function(event) {
    $(last_active = event.target).toggleClass("active", true);
  })
  .on("blur", function(event) {
    $(".pretty-input > textarea.last-active")
      .toggleClass("last-active", false);
    $(event.target)
      .toggleClass("active", false)
      .toggleClass("last-active", true);
  });

  $("#saveButton").click(function(event) {
    if(!isJS)
      $("#swapButton").click();

    var zip = new JSZip(), name = "Paramour - " + (+(new Date)).toString(36),
        textarea = getCurrent(), value = textarea.val(), output = Paramour(value);

    zip.file(name + ".par", value);
    zip.file(name + ".js", output);

    zip.generateAsync({type: "blob"})
    .then(function(blob) {         // 1) generate the zip file
      saveAs(blob, name + ".zip"); // 2) trigger the download
    }, function(err) {
      $("#blob").text(err);
    });
  });

  $("#runButton").click(function(event) {
    var self = $(event.target), textarea = getCurrent(), value = textarea.val();

    try {
      eval(value = Paramour(value));
      last.error = undefined;
      if(!isJS) $("#swapButton").click();
      self.attr("title", "Run");
      display.toggleClass("lang-paramour", false).toggleClass("lang-javascript", true);
    } catch(error) {
      value = textarea.val();
      last.error = error;
      if(isJS) $("#swapButton").click();
      self.attr("title", "Uncaught: " + error.message);
      display.toggleClass("lang-paramour", true).toggleClass("lang-javascript", false);
      alert(error);
    }

    swapIcons(runicons, "run", !isJS);
    textarea.val(value);

    $("#swapButton").click();
  });

  $("#linkButton").click(function(event) {
    if(!tinyurl)
      throw Error("The tinyurl API is not loaded.");

    if(isJS) $("#swapButton").click();

    var textarea = getCurrent(),
        url      = "https://ephellon.github.io/Paramour/extras/?code=" + Mio.enc(textarea.val()),
        self     = $(event.target);
    tinyurl(url, function() {
      var url = tinyurl.url;
      try {
        alert("The URL [" + url + "] was " + (document.execCommand("copy", false, url)? "": "not ") + "copied to the clipboard.");
      } catch(e) {
        alert("The URL [" + url + "] cannot be copied to the clipboard.");
      }
    });
  });

  $("#helpButton").click(function(event) {
    window.open("https://ephellon.github.io/Paramour/help/", "blank_");
  });

  $("#swapButton").click(function(event) {
    var textarea = getCurrent(0), value = textarea.value;

    swapIcons(swapicon, "swap", isJS = !isJS);

    if(isJS)
      textarea.value = Paramour(last.hold = value);
    else
      textarea.value = last.hold = last.hold || value;

    event.target.setAttribute("title", "View " + ((!isJS)? "JavaScript": "Paramour"));

    updateHTML();
  });

  last_active = getCurrent(), display.html(last_active.val());

  setInterval(function() {
    $(".cursor").css({"border-color": (blink = !blink)? "#ffffff": "#212121"});
  }, 500);

// The Navigation Menu
// Mustache + jQuery

function loadMenu() {
  var base_url = "https://ephellon.github.io/Paramour/",
  menu_data =
  {
    new_menu: [
      { title: "Overview",        date: "08/22/2017 01:20 CST", href: base_url },
      { title: "Executable .JAR", date: "08/22/2017 01:20 CST", href: base_url + "extras/Paramour.zip" },
      { title: "Change Log",      date: "08/22/2017 01:20 CST", href: base_url + "changelog.md" }
    ],
    acc_menu: [
      { title: "5-Minute Demos",
        items: [
          {title: "99 Bottles of Beer", href: base_url + "extras/#99"},
          {title: "Pyramid Class",      href: base_url + "extras/#Pyramid"},
          {title: "Toggle Class",       href: base_url + "extras/#Toggle"},
          {title: "String Radix Suite", href: base_url + "extras/#String Radii"}
        ]},

        { title: "Comments",
        items: [
          {title: "Basic Comments",      href: base_url + "comments/"},
          {title: "Phantoms",            href: base_url + "comments/phantoms/"},
          {title: "Docstrings",          href: base_url + "comments/docstrings/"},
          {title: "Type Annotations",    href: base_url + "comments/type-annotations/"},
          {title: "Version Controlling", href: base_url + "comments/version-control/"},
          {title: "Version Querying",    href: base_url + "comments/version-query/"}
        ]},

        { title: "Keywords",
        items: [
          {title: "Reserved Words",               href: base_url + "keywords/"},
          {title: "Type Controlled Declarations", href: base_url + "keywords/type-declarations/"},
          {title: "Case & Default Statements",    href: base_url + "keywords/case-and-default/"}
        ]},

        { title: "Functions",
        items: [
          {title: "Basic Functions",           href: base_url + "functions/"},
          {title: "Generators",                href: base_url + "functions/generators/"},
          {title: "Type Controlled Functions", href: base_url + "functions/type-functions/"}
        ]},

        { title: "Objects",
        items: [
          {title: "Tuples",  href: base_url + "objects/tuples/"},
          {title: "Arrays",  href: base_url + "objects/arrays/"},
          {title: "RegExps", href: base_url + "objects/regexps/"},
          {title: "Strings", href: base_url + "objects/strings/"}
        ]},

        { title: "Classes",
        items: [
          {title: "Basic Classes",     href: base_url + "classes/tuples/"},
          {title: "Static Methods",    href: base_url + "classes/static/"},
          {title: "Prototype Methods", href: base_url + "classes/prototype/"}
        ]},

        { title: "JS Unit",
        items: [
          {title: "Basic Tests",      href: base_url + "js-unit/"},
          {title: "@Before & @After", href: base_url + "js-unit/before-and-after/"},
          {title: "Advance Tests",    href: base_url + "js-unit/advance/"}
        ]},

        { title: "Help",
        items: [
          {title: "Paramour inside a browser",  href: base_url + "help/in-browser/"},
          {title: "Paramour outside a browser", href: base_url + "help/out-browser/"},
          {title: "Change Log",                 href: base_url + "changelog.md"}
        ]}
    ]},
      template, rendered;
  $.get("https://ephellon.github.io/Paramour/mst/menu.mst", function(file_contents) {
    template = file_contents || $("#template").html();
    rendered = Mustache.render(template, menu_data);
    $("#target").html(rendered); // #template for testing purposes

    $(".devsite-nav-item > a[track-type='leftNav']")
    .click(function(event) {
      $(event.target)
      // .siblings("a[track-type='leftNav']")
        .toggleClass("devsite-nav-toggle-expanded")
        .toggleClass("devsite-nav-toggle-collapsed")
      .siblings("ul")
        .toggleClass("devsite-nav-section-expanded")
        .toggleClass("devsite-nav-section-collapsed");
    });
  });
};

  loadMenu();

})(jQuery);
devsite.localInit = function() {};
<commit_msg>Update main.js<commit_after>(function($) {
      devsite.devsite.Init($, {'FULL_SITE_SEARCH_ENABLED': 1, 'ENABLE_BLOCKED_VIDEO_PLACEHOLDER': 0, 'VERSION_HASH': '0000000000', 'SITE_NAME': 'Paramour', 'HISTORY_ENABLED': 1, 'SUBPATH': '', 'ENABLE_BLOCKED_LINK_TOOLTIP': 0, 'ALLOWED_HOSTS': ['.github.io'], 'BLOCK_RSS_FEEDS': 0, 'SCRIPTSAFE_DOMAIN': '.github.io'},
'[]', 'en',
true, '',
{"00000000000000000000000000000000": false},
'/',
'https://ephellon.github.io/Paramour/');

  var timer, blink = false, last = {}, ltr = $("html").css(["writing-mode"]), isJS = false,
      swapicon = $("#swapButton span > div.docs-icon-redo, #swapButton span > div.docs-icon-undo"),
      runicons = $("#runButton div.docs-icon-run, #runButton div.docs-icon-debug"),
      icons = {
        swap: ["docs-icon-undo", "docs-icon-redo"],
        run: ["docs-icon-run", "docs-icon-debug"]
      },
      last_active, display, tinyurl, Paramour = Paramour || window.Paramour;

  if(Paramour == undefined)
    Paramour = function(string){return string};

  ltr = (ltr == "" || ltr == "vertical-lr");
  tinyurl = tinyurl || window.tinyurl;

  function swapIcons(element, pack, bool) {
    bool = bool || false;
    return element
      .toggleClass(icons[pack][0], bool)
      .toggleClass(icons[pack][1], !bool);
  }

  function encodeHTML(string) {
    return string.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
  }

  function decodeHTML(string) {
    return string.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
  }

  function getCurrent(index) {
    return last_active = (last_active == undefined)?
      $(".pretty-input > textarea.active, .pretty-input > textarea.last-active, .pretty-input > textarea").slice(0, 1):
    (last_active instanceof $)?
      last_active:
    $(last_active),
      display = last_active.siblings(".prettyprint"),
      (index != undefined && index != null)? (display = display[index], last_active[index]): last_active;
  }

  function updateCursor() {
    var textarea  = getCurrent(0),
        start     = textarea.selectionStart,
        end       = textarea.selectionEnd,
        value     = textarea.value || "",
        length    = value.length,
        direction = textarea.selectionDirection;

    if(direction == undefined || direction == null)
      direction = ((last.start > start || end < last.end) && ltr)? "left": "right";
    else
      direction = (direction != "forward" && ltr)? "left": "right";

    if((last.start = start) == (last.end = end))
      return encodeHTML(value.slice(0, start)) +
        '' +
        encodeHTML(value.slice(end, length));
    else
      return encodeHTML(value.slice(0, start)) +
        '' +
        encodeHTML(value.slice(start, end)) +
        '' +
        encodeHTML(value.slice(end, length));
  }

  function updateDisplay() {
    return updateCursor() + "
";
  }

  function updateHTML() {
    clearTimeout(timer);
    timer = setTimeout(function() {
      getCurrent();
      display.html(updateDisplay);
      prettyPrint();
    }, 100);
  }

  $(".pretty-input > textarea")
  .on("keyup", function(event) {
    updateHTML();
  })
  .on("mousemove", updateHTML)
  .on("mousedown", updateHTML)
  .on("scroll", function(event) {
    var T = "scrollTop", L = "scrollLeft",
        t = getCurrent(0), s = display,
        a = t[T], b = t[L], o = {};

    if(a == (last[t]||o)[T] && b == (last[t]||o)[L])
      return;
    else
      s[T] = a, s[L] = b;

    if(a > s[T])
      last[T] = t[T] = s[T] - 1;
    if(b > s[L])
      last[L] = t[L] = s[L] - 1;
  })
  .on("focus", function(event) {
    $(last_active = event.target).toggleClass("active", true);
  })
  .on("blur", function(event) {
    $(".pretty-input > textarea.last-active")
      .toggleClass("last-active", false);
    $(event.target)
      .toggleClass("active", false)
      .toggleClass("last-active", true);
  });

  $("#saveButton").click(function(event) {
    if(!isJS)
      $("#swapButton").click();

    var zip = new JSZip(), name = "Paramour - " + (+(new Date)).toString(36),
        textarea = getCurrent(), value = textarea.val(), output = Paramour(value);

    zip.file(name + ".par", value);
    zip.file(name + ".js", output);

    zip.generateAsync({type: "blob"})
    .then(function(blob) {         // 1) generate the zip file
      saveAs(blob, name + ".zip"); // 2) trigger the download
    }, function(err) {
      $("#blob").text(err);
    });
  });

  $("#runButton").click(function(event) {
    var self = $(event.target), textarea = getCurrent(), value = textarea.val();

    try {
      eval(value = Paramour(value));
      last.error = undefined;
      if(!isJS) $("#swapButton").click();
      self.attr("title", "Run");
      display.toggleClass("lang-paramour", false).toggleClass("lang-javascript", true);
    } catch(error) {
      value = textarea.val();
      last.error = error;
      if(isJS) $("#swapButton").click();
      self.attr("title", "Uncaught: " + error.message);
      display.toggleClass("lang-paramour", true).toggleClass("lang-javascript", false);
      alert(error);
    }

    swapIcons(runicons, "run", !isJS);
    textarea.val(value);

    $("#swapButton").click();
  });

  $("#linkButton").click(function(event) {
    if(!tinyurl)
      throw Error("The tinyurl API is not loaded.");

    if(isJS) $("#swapButton").click();

    var textarea = getCurrent(),
        url      = "https://ephellon.github.io/Paramour/extras/?code=" + Mio.enc(textarea.val()),
        self     = $(event.target);
    tinyurl(url, function() {
      var url = tinyurl.url;
      try {
        alert("The URL [" + url + "] was " + (document.execCommand("copy", false, url)? "": "not ") + "copied to the clipboard.");
      } catch(e) {
        alert("The URL [" + url + "] cannot be copied to the clipboard.");
      }
    });
  });

  $("#helpButton").click(function(event) {
    window.open("https://ephellon.github.io/Paramour/help/", "blank_");
  });

  $("#swapButton").click(function(event) {
    var textarea = getCurrent(0), value = textarea.value;

    swapIcons(swapicon, "swap", isJS = !isJS);

    if(isJS)
      try {
        textarea.value = Paramour(last.hold = value);
      } catch(e) {
        swapIcons(swapicon, "swap", isJS = !isJS);
        return alert(e);
      }
    else
      textarea.value = last.hold = last.hold || value;

    event.target.setAttribute("title", "View " + ((!isJS)? "JavaScript": "Paramour"));

    updateHTML();
  });

  last_active = getCurrent(), display.html(last_active.val());

  setInterval(function() {
    $(".cursor").css({"border-color": (blink = !blink)? "#ffffff": "#212121"});
  }, 500);

// The Navigation Menu
// Mustache + jQuery

function loadMenu() {
  var base_url = "https://ephellon.github.io/Paramour/",
  menu_data =
  {
    new_menu: [
      { title: "Overview",        date: "08/22/2017 01:20 CST", href: base_url },
      { title: "Executable .JAR", date: "08/22/2017 01:20 CST", href: base_url + "extras/Paramour.zip" },
      { title: "Change Log",      date: "08/22/2017 01:20 CST", href: base_url + "changelog.md" }
    ],
    acc_menu: [
      { title: "5-Minute Demos",
        items: [
          {title: "99 Bottles of Beer", href: base_url + "extras/#99"},
          {title: "Pyramid Class",      href: base_url + "extras/#Pyramid"},
          {title: "Toggle Class",       href: base_url + "extras/#Toggle"},
          {title: "String Radix Suite", href: base_url + "extras/#String Radii"}
        ]},

        { title: "Comments",
        items: [
          {title: "Basic Comments",      href: base_url + "comments/"},
          {title: "Phantoms",            href: base_url + "comments/phantoms/"},
          {title: "Docstrings",          href: base_url + "comments/docstrings/"},
          {title: "Type Annotations",    href: base_url + "comments/type-annotations/"},
          {title: "Version Controlling", href: base_url + "comments/version-control/"},
          {title: "Version Querying",    href: base_url + "comments/version-query/"}
        ]},

        { title: "Keywords",
        items: [
          {title: "Reserved Words",               href: base_url + "keywords/"},
          {title: "Type Controlled Declarations", href: base_url + "keywords/type-declarations/"},
          {title: "Case & Default Statements",    href: base_url + "keywords/case-and-default/"}
        ]},

        { title: "Functions",
        items: [
          {title: "Basic Functions",           href: base_url + "functions/"},
          {title: "Generators",                href: base_url + "functions/generators/"},
          {title: "Type Controlled Functions", href: base_url + "functions/type-functions/"}
        ]},

        { title: "Objects",
        items: [
          {title: "Tuples",  href: base_url + "objects/tuples/"},
          {title: "Arrays",  href: base_url + "objects/arrays/"},
          {title: "RegExps", href: base_url + "objects/regexps/"},
          {title: "Strings", href: base_url + "objects/strings/"}
        ]},

        { title: "Classes",
        items: [
          {title: "Basic Classes",     href: base_url + "classes/tuples/"},
          {title: "Static Methods",    href: base_url + "classes/static/"},
          {title: "Prototype Methods", href: base_url + "classes/prototype/"}
        ]},

        { title: "JS Unit",
        items: [
          {title: "Basic Tests",      href: base_url + "js-unit/"},
          {title: "@Before & @After", href: base_url + "js-unit/before-and-after/"},
          {title: "Advance Tests",    href: base_url + "js-unit/advance/"}
        ]},

        { title: "Help",
        items: [
          {title: "Paramour inside a browser",  href: base_url + "help/in-browser/"},
          {title: "Paramour outside a browser", href: base_url + "help/out-browser/"},
          {title: "Change Log",                 href: base_url + "changelog.md"}
        ]}
    ]},
      template, rendered;
  $.get("https://ephellon.github.io/Paramour/mst/menu.mst", function(file_contents) {
    template = file_contents || $("#template").html();
    rendered = Mustache.render(template, menu_data);
    $("#target").html(rendered); // #template for testing purposes

    $(".devsite-nav-item > a[track-type='leftNav']")
    .click(function(event) {
      $(event.target)
      // .siblings("a[track-type='leftNav']")
        .toggleClass("devsite-nav-toggle-expanded")
        .toggleClass("devsite-nav-toggle-collapsed")
      .siblings("ul")
        .toggleClass("devsite-nav-section-expanded")
        .toggleClass("devsite-nav-section-collapsed");
    });
  });
};

  loadMenu();

})(jQuery);
devsite.localInit = function() {};
<|endoftext|>


<commit_before>/**
 * @ngdoc service
 * @name  core.service:AlertService
 * @requires ng.$q
 * @requires ng.$interval
 *
 * @description
 * 	Alert service which tracks responses from the web socket API.
 * 	Stores responses categorized by type, controller, or endpoint. The id is popped
 * 	from an array of keys(sequential integers) and recycled upon removal
 * 	of the alert. Old alerts removed using an interval.
 *
 */
core.service("AlertService", function ($q, $interval, $timeout) {

    var AlertService = this;

    /**
     * @ngdoc property
     * @name  core.service:AlertService#types
     * @propertyOf core.service:AlertService
     *
     * @description
     *  The available alert types. These are declared in the
     *  {@link coreConfig coreConfig}
     *
     */
    var types = coreConfig.alerts.types;

    /**
     * @ngdoc property
     * @name  core.service:AlertService#classes
     * @propertyOf core.service:AlertService
     *
     * @description
     *  The classes to be apploed to each alert type. These are declared in the
     *  {@link coreConfig coreConfig}
     *
     */
    var classes = coreConfig.alerts.classes;

    /**
     * @ngdoc property
     * @name  core.service:AlertService#store
     * @propertyOf core.service:AlertService
     *
     * @description
     *  An object to store alerts.
     *
     */
    var store = {};

    // create stores for the types
    for (var i in types) {
        store[types[i]] = {
            defer: $q.defer(),
            list: []
        };
    }

    /**
     * @ngdoc property
     * @name  core.service:AlertService#queue
     * @propertyOf core.service:AlertService
     *
     * @description
     *  An object to store queues.
     *
     */
    var queue = {};

    /**
     * @ngdoc property
     * @name  core.service:AlertService#exclusive
     * @propertyOf core.service:AlertService
     *
     * @description
     *  An array of exclusive channels.
     *
     */
    var exclusive = [];

    /**
     * @ngdoc property
     * @name  core.service:AlertService#keys
     * @propertyOf core.service:AlertService
     *
     * @description
     *  An array of available keys.
     *
     */
    var keys = [];

    // create the initial keys
    for (var id = 0; id < 1000; id++) {
        keys.push(id);
    }

    /**
     * @ngdoc method
     * @name  core.service:AlertService#Alert
     * @methodOf core.service:AlertService
     * @param {string} message
     * 	message on the API response
     * @param {string} type
     * 	mapped response type on the API response
     * @param {string} channel
     * 	channel on which the response returned
     * @returns {Alert} returns a new Alert.
     *
     * @description
     * 	Constructor for an Alert.
     */
    var Alert = function (message, type, channel) {
        this.id = keys.pop();
        this.message = message ? message : '';
        this.type = type ? type : 'UNKNOWN';
        this.channel = channel ? channel : 'unassigned';
        this.time = new Date().getTime();
        if (classes[type] === undefined) {
            this.class = classes.DEFAULT;
        } else {
            this.class = classes[type];
        }
        return this;
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#AlertService.create
     * @methodOf core.service:AlertService
     * @param {string} facet
     *  either type, controller, or endpoint
     *
     * @description
     *  Method to create a store with the given facet.
     *
     */
    AlertService.create = function (facet, exclusion) {
        if (store[facet] !== undefined) return;
        store[facet] = {
            defer: $q.defer(),
            list: []
        };
        if (exclusion) {
            AlertService.clearTypeStores();
            exclusive.push(facet);
        }
        if (queue[facet] !== undefined) {
            for (var i in queue[facet]) {
                AlertService.add(queue[facet][i].meta, queue[facet][i].channel);
            }
            delete queue[facet];
        }
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#AlertService.get
     * @methodOf core.service:AlertService
     * @param {string} facet
     *  either type, controller, or endpoint
     * @return {object}
     *  returns store object containing promise and current list of alerts
     *
     * @description
     *  Method to get a store from the alert service.
     *  A store consists of the promise and a list of alerts.
     *
     */
    AlertService.get = function (facet) {
        if (facet === undefined) return [];
        return store[facet];
    };

    /**
     * @ngdoc property
     * @name core.directive:alerts#firstPass
     * @propertyOf core.directive:alerts
     *
     * @description
     * A variable to allow time to initialize before adding to type stores.
     */
    var initializing = true;

    /**
     * @ngdoc method
     * @name  core.service:AlertService#add
     * @methodOf core.service:AlertService
     * @param {string} facet
     *  An facet of a type, channel, or endpoint.
     * @param {object} meta
     *  An API response meta containing message and type.
     * @param {string} channel
     *  The channel on which the response returned.
     * @returns {Alert} returns a new Alert.
     *
     * @description
     *  Method to check store for facet and either add if not already in store
     *  or add to the queue
     *
     */
    var add = function (facet, meta, channel) {
        var alert = new Alert(meta.message, meta.status, channel);

        if (store[facet] !== undefined) {
            // add alert to store by facet
            if (isNotStored(facet, meta, channel)) {
                store[facet].list.push(alert);
                store[facet].defer.notify(alert);
            }
        } else {
            // queue alert
            enqueue(facet, meta, channel);
        }

        return alert;
    };

    var isDefined = angular.isDefined;
    var isUndefined = angular.isDefined;

    AlertService.addAlertServiceError = function(error) {
        var status, message, channel;

        if (isDefined(error.data)) {
            status = isDefined(error.data.status) ? error.data.status : error.status;
            message = error.data.message;
            channel = error.data.path;
        }

        if (isUndefined(message)) {
            message = isDefined(error.data.meta) && isDefined(error.data.meta.message) ? error.data.meta.message : error.statusText;
        }

        if (isUndefined(channel) && isDefined(error.config) && isDefined(error.config.url)) {
            channel = error.config.url.replace(appConfig.webService, '');
        }

        if (isDefined(status) && isDefined(message) && isDefined(channel)) {
            AlertService.add({
                status: "ERROR",
                message: '(' + status + ') ' + message
            }, channel);
        } else {
            if (isUndefined(status)) {
                console.warn('No error status!');
            }
            if (isUndefined(message)) {
                console.warn('No error message!');
            }
            if (isUndefined(channel)) {
                console.warn('No alert channel!');
            }
            console.warn(error);
        }
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#AlertService.add
     * @methodOf core.service:AlertService
     * @param {object} meta
     *  An API response meta containing message and type.
     * @param {string} channel
     *  The channel on which the response returned.
     * @returns {Alert} returns a new Alert.
     *
     * @description
     *  Method to add an alert to the appropriate stores.
     *  Adds to both the store for type and store for channel.
     *
     */
    AlertService.add = function (meta, channel) {

        var alert;

        if (channel !== undefined) {

            if (channel.indexOf('/') === 0) {
                channel = channel.substring(1, channel.length);
            }

            var actionResponse = channel + ':' + meta.action;

            // add alert to store by endpoint
            alert = add(actionResponse, meta, channel);

            // return if endpoint is exclusive
            if (exclusive.indexOf(actionResponse) >= 0) {
                return alert;
            }

            var endpoint = channel;

            // add alert to store by endpoint
            alert = add(endpoint, meta, channel);

            // return if endpoint is exclusive
            if (exclusive.indexOf(endpoint) >= 0) {
                return alert;
            }

            var controller = channel.substr(0, channel.lastIndexOf("/"));

            // add alert to store by controller
            alert = add(controller, meta, channel);

            // return if controller is exclusive
            if (exclusive.indexOf(controller) >= 0) {
                return alert;
            }
        }

        // allow time for any exclusive channels to be created
        // before adding to stores by type
        if (initializing) {
            var emptyAlert = {};
            $timeout(function () {
                initializing = false;
                angular.extend(emptyAlert, AlertService.add(meta, channel));
            });
            return emptyAlert;
        }

        // add alert to store by type
        return add(meta.status, meta, channel);
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#remove
     * @methodOf core.service:AlertService
     * @param {string} facet
     *  An facet of a type, channel, or endpoint
     * @param {object} alert
     *  The Alert to be removed.
     *
     * @description
     *  Method to remove alert from all store by facet.
     *
     */
    var remove = function (facet, alert) {
        if (store[facet] !== undefined) {
            for (var i in store[facet].list) {
                if (store[facet].list[i].id === alert.id) {
                    store[facet].defer.notify(alert);
                    store[facet].list.splice(i, 1);
                    break;
                }
            }
        }
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#AlertService.remove
     * @methodOf core.service:AlertService
     * @param {object} alert
     *  The Alert to be removed.
     *
     * @description
     *  Method to remove an alert from the store.
     *  Removes from both type store, controller store, and endpoint store.
     *
     */
    AlertService.remove = function (alert) {

        alert.remove = true;

        // remove alert from store by type
        remove(alert.type, alert);

        var endpoint = alert.channel;

        // remove alert from store by endpoint
        remove(endpoint, alert);

        var controller = alert.channel.substr(0, alert.channel.lastIndexOf("/"));

        // remove alert from store by controller
        remove(controller, alert);

        keys.push(alert.id);
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#AlertService.removeAll
     * @methodOf core.service:AlertService
     * @param {string} facet
     *  The channel from which to remove all alerts.
     *
     * @description
     *  Method to remove all alert from a channel.
     *
     */
    AlertService.removeAll = function (facet) {
        if (store[facet] !== undefined) {
            for (var i = store[facet].list.length - 1; i >= 0; i--) {
                AlertService.remove(store[facet].list[i]);
            }
        }
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#AlertService.clearTypeStores
     * @methodOf core.service:AlertService
     *
     * @description
     *  Method to remove all alert in the type stores.
     *
     */
    AlertService.clearTypeStores = function () {
        var types = coreConfig.alerts.types;
        for (var i in types) {
            AlertService.removeAll(types[i]);
        }
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#enqueue
     * @methodOf core.service:AlertService
     * @param {string} facet
     *  type, controller, or endpoint
     * @param {object} meta
     *  API response meta containing type and message
     * @param {string} channel
     *  on which the response returned
     * @return {array} returns array of duplicates with specified values
     *
     * @description
     *  Enqueue alert if not already queued.
     *
     */
    var enqueue = function (facet, meta, channel) {
        if (isNotQueued(facet, meta, channel)) {
            queue[facet].push({
                'meta': meta,
                'channel': channel
            });
        }
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#isNotQueued
     * @methodOf core.service:AlertService
     * @param {string} facet
     *  type, controller, or endpoint
     * @param {object} meta
     *  API response meta containing type and message
     * @param {string} channel
     *  on which the response returned
     * @return {array} returns array of duplicates with specified values
     *
     * @description
     *  Method to check to see if queue does not contain
     *  alert with same type, message, and channel.
     *
     */
    var isNotQueued = function (facet, meta, channel) {
        if (queue[facet] === undefined) {
            queue[facet] = [];
            return true;
        }
        var queued = queue[facet].filter(function (alert) {
            return alert.meta.type === meta.status &&
                alert.meta.message === meta.message &&
                alert.channel === channel;
        });
        return queued.length === 0;
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#isNotStored
     * @methodOf core.service:AlertService
     * @param {string} facet
     *  type, controller, or endpoint
     * @param {object} meta
     *  API response meta containing type and message
     * @param {string} channel
     *  on which the response returned
     * @return {array} returns array of duplicates with specified values
     *
     * @description
     *  Method to check to see if store does not contain
     *  alert with same type, message, and channel.
     *
     */
    var isNotStored = function (facet, meta, channel) {
        var list = store[facet].list.filter(function (alert) {
            var channelMatch = channel !== undefined ? alert.channel === channel : true;
            return alert.type === meta.status &&
                alert.message === meta.message &&
                channelMatch;
        });
        return list.length === 0;
    };

    // remove old alerts and recycle keys
    $interval(function () {

        var now = new Date().getTime();

        var recycle = [];

        for (var t in store) {
            // do not flush errors
            if (t !== 'ERROR') {
                for (var j = store[t].list.length - 1; j >= 0; j--) {

                    var alert = store[t].list[j];

                    if (alert.time < now - (coreConfig.alerts.flush / 2) && !alert.fixed) {
                        alert.remove = true;

                        store[t].defer.notify(alert);
                        store[t].list.splice(j, 1);

                        // don't recycle the same id twice
                        if (recycle.indexOf(alert.id) < 0) {
                            recycle.push(alert.id);
                        }
                    }
                }
            }
        }

        keys = keys.concat(recycle);

    }, coreConfig.alerts.flush);

});
<commit_msg>corrected isUndefined assignment from angular.isUndefined<commit_after>/**
 * @ngdoc service
 * @name  core.service:AlertService
 * @requires ng.$q
 * @requires ng.$interval
 *
 * @description
 * 	Alert service which tracks responses from the web socket API.
 * 	Stores responses categorized by type, controller, or endpoint. The id is popped
 * 	from an array of keys(sequential integers) and recycled upon removal
 * 	of the alert. Old alerts removed using an interval.
 *
 */
core.service("AlertService", function ($q, $interval, $timeout) {

    var AlertService = this;

    /**
     * @ngdoc property
     * @name  core.service:AlertService#types
     * @propertyOf core.service:AlertService
     *
     * @description
     *  The available alert types. These are declared in the
     *  {@link coreConfig coreConfig}
     *
     */
    var types = coreConfig.alerts.types;

    /**
     * @ngdoc property
     * @name  core.service:AlertService#classes
     * @propertyOf core.service:AlertService
     *
     * @description
     *  The classes to be apploed to each alert type. These are declared in the
     *  {@link coreConfig coreConfig}
     *
     */
    var classes = coreConfig.alerts.classes;

    /**
     * @ngdoc property
     * @name  core.service:AlertService#store
     * @propertyOf core.service:AlertService
     *
     * @description
     *  An object to store alerts.
     *
     */
    var store = {};

    // create stores for the types
    for (var i in types) {
        store[types[i]] = {
            defer: $q.defer(),
            list: []
        };
    }

    /**
     * @ngdoc property
     * @name  core.service:AlertService#queue
     * @propertyOf core.service:AlertService
     *
     * @description
     *  An object to store queues.
     *
     */
    var queue = {};

    /**
     * @ngdoc property
     * @name  core.service:AlertService#exclusive
     * @propertyOf core.service:AlertService
     *
     * @description
     *  An array of exclusive channels.
     *
     */
    var exclusive = [];

    /**
     * @ngdoc property
     * @name  core.service:AlertService#keys
     * @propertyOf core.service:AlertService
     *
     * @description
     *  An array of available keys.
     *
     */
    var keys = [];

    // create the initial keys
    for (var id = 0; id < 1000; id++) {
        keys.push(id);
    }

    /**
     * @ngdoc method
     * @name  core.service:AlertService#Alert
     * @methodOf core.service:AlertService
     * @param {string} message
     * 	message on the API response
     * @param {string} type
     * 	mapped response type on the API response
     * @param {string} channel
     * 	channel on which the response returned
     * @returns {Alert} returns a new Alert.
     *
     * @description
     * 	Constructor for an Alert.
     */
    var Alert = function (message, type, channel) {
        this.id = keys.pop();
        this.message = message ? message : '';
        this.type = type ? type : 'UNKNOWN';
        this.channel = channel ? channel : 'unassigned';
        this.time = new Date().getTime();
        if (classes[type] === undefined) {
            this.class = classes.DEFAULT;
        } else {
            this.class = classes[type];
        }
        return this;
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#AlertService.create
     * @methodOf core.service:AlertService
     * @param {string} facet
     *  either type, controller, or endpoint
     *
     * @description
     *  Method to create a store with the given facet.
     *
     */
    AlertService.create = function (facet, exclusion) {
        if (store[facet] !== undefined) return;
        store[facet] = {
            defer: $q.defer(),
            list: []
        };
        if (exclusion) {
            AlertService.clearTypeStores();
            exclusive.push(facet);
        }
        if (queue[facet] !== undefined) {
            for (var i in queue[facet]) {
                AlertService.add(queue[facet][i].meta, queue[facet][i].channel);
            }
            delete queue[facet];
        }
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#AlertService.get
     * @methodOf core.service:AlertService
     * @param {string} facet
     *  either type, controller, or endpoint
     * @return {object}
     *  returns store object containing promise and current list of alerts
     *
     * @description
     *  Method to get a store from the alert service.
     *  A store consists of the promise and a list of alerts.
     *
     */
    AlertService.get = function (facet) {
        if (facet === undefined) return [];
        return store[facet];
    };

    /**
     * @ngdoc property
     * @name core.directive:alerts#firstPass
     * @propertyOf core.directive:alerts
     *
     * @description
     * A variable to allow time to initialize before adding to type stores.
     */
    var initializing = true;

    /**
     * @ngdoc method
     * @name  core.service:AlertService#add
     * @methodOf core.service:AlertService
     * @param {string} facet
     *  An facet of a type, channel, or endpoint.
     * @param {object} meta
     *  An API response meta containing message and type.
     * @param {string} channel
     *  The channel on which the response returned.
     * @returns {Alert} returns a new Alert.
     *
     * @description
     *  Method to check store for facet and either add if not already in store
     *  or add to the queue
     *
     */
    var add = function (facet, meta, channel) {
        var alert = new Alert(meta.message, meta.status, channel);

        if (store[facet] !== undefined) {
            // add alert to store by facet
            if (isNotStored(facet, meta, channel)) {
                store[facet].list.push(alert);
                store[facet].defer.notify(alert);
            }
        } else {
            // queue alert
            enqueue(facet, meta, channel);
        }

        return alert;
    };

    var isDefined = angular.isDefined;
    var isUndefined = angular.isUndefined;

    AlertService.addAlertServiceError = function(error) {
        var status, message, channel;

        if (isDefined(error.data)) {
            status = isDefined(error.data.status) ? error.data.status : error.status;
            message = error.data.message;
            channel = error.data.path;
        }

        if (isUndefined(message)) {
            message = isDefined(error.data.meta) && isDefined(error.data.meta.message) ? error.data.meta.message : error.statusText;
        }

        if (isUndefined(channel) && isDefined(error.config) && isDefined(error.config.url)) {
            channel = error.config.url.replace(appConfig.webService, '');
        }

        if (isDefined(status) && isDefined(message) && isDefined(channel)) {
            AlertService.add({
                status: "ERROR",
                message: '(' + status + ') ' + message
            }, channel);
        } else {
            if (isUndefined(status)) {
                console.warn('No error status!');
            }
            if (isUndefined(message)) {
                console.warn('No error message!');
            }
            if (isUndefined(channel)) {
                console.warn('No alert channel!');
            }
            console.warn(error);
        }
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#AlertService.add
     * @methodOf core.service:AlertService
     * @param {object} meta
     *  An API response meta containing message and type.
     * @param {string} channel
     *  The channel on which the response returned.
     * @returns {Alert} returns a new Alert.
     *
     * @description
     *  Method to add an alert to the appropriate stores.
     *  Adds to both the store for type and store for channel.
     *
     */
    AlertService.add = function (meta, channel) {

        var alert;

        if (channel !== undefined) {

            if (channel.indexOf('/') === 0) {
                channel = channel.substring(1, channel.length);
            }

            var actionResponse = channel + ':' + meta.action;

            // add alert to store by endpoint
            alert = add(actionResponse, meta, channel);

            // return if endpoint is exclusive
            if (exclusive.indexOf(actionResponse) >= 0) {
                return alert;
            }

            var endpoint = channel;

            // add alert to store by endpoint
            alert = add(endpoint, meta, channel);

            // return if endpoint is exclusive
            if (exclusive.indexOf(endpoint) >= 0) {
                return alert;
            }

            var controller = channel.substr(0, channel.lastIndexOf("/"));

            // add alert to store by controller
            alert = add(controller, meta, channel);

            // return if controller is exclusive
            if (exclusive.indexOf(controller) >= 0) {
                return alert;
            }
        }

        // allow time for any exclusive channels to be created
        // before adding to stores by type
        if (initializing) {
            var emptyAlert = {};
            $timeout(function () {
                initializing = false;
                angular.extend(emptyAlert, AlertService.add(meta, channel));
            });
            return emptyAlert;
        }

        // add alert to store by type
        return add(meta.status, meta, channel);
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#remove
     * @methodOf core.service:AlertService
     * @param {string} facet
     *  An facet of a type, channel, or endpoint
     * @param {object} alert
     *  The Alert to be removed.
     *
     * @description
     *  Method to remove alert from all store by facet.
     *
     */
    var remove = function (facet, alert) {
        if (store[facet] !== undefined) {
            for (var i in store[facet].list) {
                if (store[facet].list[i].id === alert.id) {
                    store[facet].defer.notify(alert);
                    store[facet].list.splice(i, 1);
                    break;
                }
            }
        }
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#AlertService.remove
     * @methodOf core.service:AlertService
     * @param {object} alert
     *  The Alert to be removed.
     *
     * @description
     *  Method to remove an alert from the store.
     *  Removes from both type store, controller store, and endpoint store.
     *
     */
    AlertService.remove = function (alert) {

        alert.remove = true;

        // remove alert from store by type
        remove(alert.type, alert);

        var endpoint = alert.channel;

        // remove alert from store by endpoint
        remove(endpoint, alert);

        var controller = alert.channel.substr(0, alert.channel.lastIndexOf("/"));

        // remove alert from store by controller
        remove(controller, alert);

        keys.push(alert.id);
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#AlertService.removeAll
     * @methodOf core.service:AlertService
     * @param {string} facet
     *  The channel from which to remove all alerts.
     *
     * @description
     *  Method to remove all alert from a channel.
     *
     */
    AlertService.removeAll = function (facet) {
        if (store[facet] !== undefined) {
            for (var i = store[facet].list.length - 1; i >= 0; i--) {
                AlertService.remove(store[facet].list[i]);
            }
        }
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#AlertService.clearTypeStores
     * @methodOf core.service:AlertService
     *
     * @description
     *  Method to remove all alert in the type stores.
     *
     */
    AlertService.clearTypeStores = function () {
        var types = coreConfig.alerts.types;
        for (var i in types) {
            AlertService.removeAll(types[i]);
        }
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#enqueue
     * @methodOf core.service:AlertService
     * @param {string} facet
     *  type, controller, or endpoint
     * @param {object} meta
     *  API response meta containing type and message
     * @param {string} channel
     *  on which the response returned
     * @return {array} returns array of duplicates with specified values
     *
     * @description
     *  Enqueue alert if not already queued.
     *
     */
    var enqueue = function (facet, meta, channel) {
        if (isNotQueued(facet, meta, channel)) {
            queue[facet].push({
                'meta': meta,
                'channel': channel
            });
        }
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#isNotQueued
     * @methodOf core.service:AlertService
     * @param {string} facet
     *  type, controller, or endpoint
     * @param {object} meta
     *  API response meta containing type and message
     * @param {string} channel
     *  on which the response returned
     * @return {array} returns array of duplicates with specified values
     *
     * @description
     *  Method to check to see if queue does not contain
     *  alert with same type, message, and channel.
     *
     */
    var isNotQueued = function (facet, meta, channel) {
        if (queue[facet] === undefined) {
            queue[facet] = [];
            return true;
        }
        var queued = queue[facet].filter(function (alert) {
            return alert.meta.type === meta.status &&
                alert.meta.message === meta.message &&
                alert.channel === channel;
        });
        return queued.length === 0;
    };

    /**
     * @ngdoc method
     * @name  core.service:AlertService#isNotStored
     * @methodOf core.service:AlertService
     * @param {string} facet
     *  type, controller, or endpoint
     * @param {object} meta
     *  API response meta containing type and message
     * @param {string} channel
     *  on which the response returned
     * @return {array} returns array of duplicates with specified values
     *
     * @description
     *  Method to check to see if store does not contain
     *  alert with same type, message, and channel.
     *
     */
    var isNotStored = function (facet, meta, channel) {
        var list = store[facet].list.filter(function (alert) {
            var channelMatch = channel !== undefined ? alert.channel === channel : true;
            return alert.type === meta.status &&
                alert.message === meta.message &&
                channelMatch;
        });
        return list.length === 0;
    };

    // remove old alerts and recycle keys
    $interval(function () {

        var now = new Date().getTime();

        var recycle = [];

        for (var t in store) {
            // do not flush errors
            if (t !== 'ERROR') {
                for (var j = store[t].list.length - 1; j >= 0; j--) {

                    var alert = store[t].list[j];

                    if (alert.time < now - (coreConfig.alerts.flush / 2) && !alert.fixed) {
                        alert.remove = true;

                        store[t].defer.notify(alert);
                        store[t].list.splice(j, 1);

                        // don't recycle the same id twice
                        if (recycle.indexOf(alert.id) < 0) {
                            recycle.push(alert.id);
                        }
                    }
                }
            }
        }

        keys = keys.concat(recycle);

    }, coreConfig.alerts.flush);

});
<|endoftext|>


<commit_before>var elClipboard = {
    type: "",
    value: ""
};

//To control elClipboard and system clipboard
var newCopied = false;
var isCopiedImage = true;

function setElClipboard(type, value) {
    elClipboard.type = type;
    elClipboard.value = value;
    if (isCopiedImage) {
        isCopiedImage = false;
        newCopied = true;
    }
}

function copyEl() {
    document.execCommand('copy', false, null);
    var currentClicked = me.getCurrentClicked();
    if (currentClicked !== "") {
        if (currentClicked.hasClass("slidethumb")) {
            var slideId = me.slideIdFromThumb(currentClicked);
            setElClipboard("slidethumb", $("#" + slideId).clone());
        }
        else {
            if (currentClicked.hasClass("slidelement") && !currentClicked.hasClass("elementediting")) {
                setElClipboard("slidelement", currentClicked.clone());
            }
        }
    }
    else {
        setElClipboard("", "");
    }
}

function pasteEl() {
    var currentClicked = me.getCurrentClicked();
    switch (elClipboard.type) {
        case "slidethumb":
            if (isInElement($(".slidethumbholder"), currentClicked)) {
                if (isElementByClass("slidethumb", currentClicked)) {
                    me.copySlideToSlide(elClipboard.value);
                    changeContent();//Event for undo redo
                }
                else {
                    me.cloneSlide(elClipboard.value);
                    launchEvent("click", document.getElementsByClassName("slidethumbholder")[0]);
                    changeContent();//Event for undo redo
                }
            }
            break;
        case "slidelement":
            if (isElementByClass("fullslider-slide", currentClicked) || isElementByClass("slidelement", currentClicked)) {
                if (!isElementByClass("elementediting", currentClicked)) {
                    pasteSlidelement();
                }
            }
            else {
                if (isInElement($(".slidethumbholder"), currentClicked)) {
                    if (isElementByClass("slidethumb", currentClicked)) {
                        pasteSlidelement();
                    }
                }
            }
            break;
    }
}

function pasteSlidelement() {
    me.cloneElement(elClipboard.value);
    me.appendClonedElement();
    changeContent();//Event for undo redo
}

key('ctrl+c', function(e) {
    copyEl();
});

//key('ctrl+v', function(e) {
//    pasteEl();
//    changeContent();//Event for undo redo
//});

document.onpaste = function(e)
{
    var items = e.clipboardData.items;

    for (var i = 0; i < items.length; ++i) {
        //If there is an image on clipboard and slide or slide element is current clicked -> paste image
        if ((items[i].kind == 'file' && items[i].type.indexOf('image/') !== -1) && (!newCopied || isCopiedImage) && (isElementByClass("fullslider-slide", me.currentClicked) || isElementByClass("slidelement", me.currentClicked))) { //If clipboard has an image, paste it
            var blob = items[i].getAsFile();
            createImageFromBlob(blob);
            newCopied = false;
            isCopiedImage = true;
            break;
        } else { //Else, paste Fullslider element
            if (i == items.length - 1) {
                pasteEl();
                newCopied = false;
                break;
                isCopiedImage = false;
            }
        }
    }
}; <commit_msg>isCopiedImage<commit_after>var elClipboard = {
    type: "",
    value: ""
};

//To control elClipboard and system clipboard
var newCopied = false;
var isCopiedImage = true;

function setElClipboard(type, value) {
    elClipboard.type = type;
    elClipboard.value = value;
    if (isCopiedImage) {
        isCopiedImage = false;
        newCopied = true;
    }
}

function copyEl() {
    document.execCommand('copy', false, null);
    var currentClicked = me.getCurrentClicked();
    if (currentClicked !== "") {
        if (currentClicked.hasClass("slidethumb")) {
            var slideId = me.slideIdFromThumb(currentClicked);
            setElClipboard("slidethumb", $("#" + slideId).clone());
        }
        else {
            if (currentClicked.hasClass("slidelement") && !currentClicked.hasClass("elementediting")) {
                setElClipboard("slidelement", currentClicked.clone());
            }
        }
    }
    else {
        setElClipboard("", "");
    }
}

function pasteEl() {
    var currentClicked = me.getCurrentClicked();
    switch (elClipboard.type) {
        case "slidethumb":
            if (isInElement($(".slidethumbholder"), currentClicked)) {
                if (isElementByClass("slidethumb", currentClicked)) {
                    me.copySlideToSlide(elClipboard.value);
                    changeContent();//Event for undo redo
                }
                else {
                    me.cloneSlide(elClipboard.value);
                    launchEvent("click", document.getElementsByClassName("slidethumbholder")[0]);
                    changeContent();//Event for undo redo
                }
            }
            break;
        case "slidelement":
            if (isElementByClass("fullslider-slide", currentClicked) || isElementByClass("slidelement", currentClicked)) {
                if (!isElementByClass("elementediting", currentClicked)) {
                    pasteSlidelement();
                }
            }
            else {
                if (isInElement($(".slidethumbholder"), currentClicked)) {
                    if (isElementByClass("slidethumb", currentClicked)) {
                        pasteSlidelement();
                    }
                }
            }
            break;
    }
}

function pasteSlidelement() {
    me.cloneElement(elClipboard.value);
    me.appendClonedElement();
    changeContent();//Event for undo redo
}

key('ctrl+c', function(e) {
    copyEl();
});

//key('ctrl+v', function(e) {
//    pasteEl();
//    changeContent();//Event for undo redo
//});

document.onpaste = function(e)
{
    var items = e.clipboardData.items;

    for (var i = 0; i < items.length; ++i) {
        //If there is an image on clipboard and slide or slide element is current clicked -> paste image
        if ((items[i].kind == 'file' && items[i].type.indexOf('image/') !== -1) && (!newCopied || isCopiedImage) && (isElementByClass("fullslider-slide", me.currentClicked) || isElementByClass("slidelement", me.currentClicked))) { //If clipboard has an image, paste it
            var blob = items[i].getAsFile();
            createImageFromBlob(blob);
            newCopied = false;
            isCopiedImage = true;
            break;
        } else { //Else, paste Fullslider element
            if (i == items.length - 1) {
                pasteEl();
                newCopied = false;
                isCopiedImage = false;
                break;
            }
        }
    }
}; <|endoftext|>