<commit_before>/* eslint-disable no-console, import/namespace */
// @flow
import React from 'react';
import ReactDOM from 'react-dom';
import { act, Simulate } from 'react-dom/test-utils';
import ReactTestRenderer from 'react-test-renderer';
import * as constants from '../../constants';
import StyleSheetManager from '../../models/StyleSheetManager';
import ThemeProvider from '../../models/ThemeProvider';
import StyleSheet from '../../sheet';
import { expectCSSMatches, getCSS, resetStyled } from '../../test/utils';
import createGlobalStyle from '../createGlobalStyle';
import keyframes from '../keyframes';

describe(`createGlobalStyle`, () => {
  let context;

  function setup() {
    const container = document.createElement('div');
    document.body.appendChild(container);

    return {
      container,
      render(comp) {
        ReactDOM.render(comp, container);
      },
      cleanup() {
        resetStyled();
        document.body.removeChild(container);
      },
    };
  }

  beforeEach(() => {
    context = setup();
  });

  afterEach(() => {
    context.cleanup();
  });

  it(`injects global <style> when rendered`, () => {
    const { render } = context;
    const Component = createGlobalStyle`[data-test-inject]{color:red;} `;
    render(<Component />);
    expectCSSMatches(`[data-test-inject]{color:red;} `);
  });

  it(`supports interpolation`, () => {
    const { render } = context;
    const Component = createGlobalStyle`div {color:${props => props.color};} `;
    render(<Component color="orange" />);
    expectCSSMatches(`div{color:orange;} `);
  });

  it(`supports objects with a function`, () => {
    const { render } = setup();
    const Component = createGlobalStyle({
      'h1, h2, h3, h4, h5, h6': {
        fontFamily: ({ theme }) => theme.fonts.heading,
      },
    });
    render(<Component theme={{ fonts: { heading: 'sans-serif' } }} />);
    expectCSSMatches(`h1,h2,h3,h4,h5,h6{ font-family:sans-serif; }`);
  });

  it(`supports nested objects with a function`, () => {
    const { render } = setup();
    const Component1 = createGlobalStyle({
      'div, span': {
        h1: {
          span: {
            fontFamily: ({ theme }) => theme.fonts.heading,
          },
        },
      },
    });
    render(<Component1 theme={{ fonts: { heading: 'sans-serif' } }} />);
    expectCSSMatches(`div h1 span,span h1 span{ font-family:sans-serif; }`);
  });

  it(`supports theming`, () => {
    const { render } = context;
    const Component = createGlobalStyle`div {color:${props => props.theme.color};} `;
    render(
      <ThemeProvider theme={{ color: 'black' }}>
        <Component />
      </ThemeProvider>
    );
    expectCSSMatches(`div{color:black;} `);
  });

  it(`updates theme correctly`, () => {
    const { render } = context;
    const Component = createGlobalStyle`div {color:${props => props.theme.color};} `;
    let update;
    class App extends React.Component {
      state = { color: 'grey' };

      constructor() {
        super();
        update = payload => {
          this.setState(payload);
        };
      }

      render() {
        return (
          <ThemeProvider theme={{ color: this.state.color }}>
            <Component />
          </ThemeProvider>
        );
      }
    }
    render(<App />);
    expectCSSMatches(`div{color:grey;} `);

    update({ color: 'red' });
    expectCSSMatches(`div{color:red;} `);
  });

  it('should work in StrictMode without warnings', () => {
    const { render } = context;
    const spy = jest.spyOn(console, 'error').mockImplementation(() => {});
    const Comp = createGlobalStyle`
      html {
        color: red;
      }
    `;

    act(() => {
      render(
        <React.StrictMode>
          <Comp />
        </React.StrictMode>
      );
    });

    expect(spy).not.toHaveBeenCalled();
  });

  it('should not inject twice in StrictMode', () => {
    jest.spyOn(StyleSheet, 'registerId');

    const { render } = context;
    const spy = jest.spyOn(console, 'error').mockImplementation(() => {});
    const Comp = createGlobalStyle`
      html {
        color: red;
      }
    `;

    act(() => {
      render(
        <React.StrictMode>
          <Comp />
        </React.StrictMode>
      );
    });

    expect(spy).not.toHaveBeenCalled();
    expect(StyleSheet.registerId).toHaveBeenCalledTimes(1);
  });

  it(`renders to StyleSheetManager.target`, () => {
    const { container, render } = context;
    const Component = createGlobalStyle`[data-test-target]{color:red;} `;
    render(

    );

    const style = container.firstChild;
    expect(style.tagName).toBe('STYLE');
    expect(style.textContent).toContain(`[data-test-target]{color:red;}`);
  });

  it(`adds new global rules non-destructively`, () => {
    const { render } = context;
    const Color = createGlobalStyle`[data-test-add]{color:red;} `;
    const Background = createGlobalStyle`[data-test-add]{background:yellow;} `;

    render(
      <React.Fragment>
        <Color />
        <Background />
      </React.Fragment>
    );

    setTimeout(() => {
      expectCSSMatches(`
        [data-test-add]{color:red;}
        [data-test-add]{background:yellow;}
      `);
    });
  });

  it(`stringifies multiple rules correctly`, () => {
    const { render } = context;
    const Component = createGlobalStyle`
      div {
        color: ${props => props.fg};
        background: ${props => props.bg};
      }
    `;
    render(<Component fg="red" bg="green" />);
    expectCSSMatches(`div{color:red;background:green;} `);
  });

  it(`injects multiple <GlobalStyle> components correctly`, () => {
    const { render } = context;

    const A = createGlobalStyle`body { background: palevioletred; }`;
    const B = createGlobalStyle`body { color: white; }`;

    render(
      <React.Fragment>

      </React.Fragment>
    );
    expectCSSMatches(`body{background:palevioletred;} body{color:white;}`);
  });

  it(`removes styling injected styling when unmounted`, () => {
    const ComponentA = createGlobalStyle`[data-test-remove]{color:grey;} `;
    const ComponentB = createGlobalStyle`[data-test-keep]{color:blue;} `;

    class Comp extends React.Component {
      render() {
        return this.props.insert ? <ComponentA /> : <ComponentB />;
      }
    }

    const renderer = ReactTestRenderer.create(<Comp insert />);

    ReactTestRenderer.act(() => {
      expect(getCSS(document).trim()).toContain(`[data-test-remove]{color:grey;}`);
      expect(getCSS(document).trim()).not.toContain(`[data-test-keep]{color:blue;}`);
      renderer.update(<Comp insert={false} />);
    });

    ReactTestRenderer.act(() => {
      expect(getCSS(document).trim()).not.toContain(`[data-test-remove]{color:grey;}`);
      expect(getCSS(document).trim()).toContain(`[data-test-keep]{color:blue;}`);
    });
  });

  it(`removes styling injected for multiple <GlobalStyle> components correctly`, () => {
    const { render } = context;

    const A = createGlobalStyle`body { background: palevioletred; }`;
    const B = createGlobalStyle`body { color: white; }`;

    class Comp extends React.Component {
      state = {
        a: true,
        b: true,
      };

      onClick() {
        if (this.state.a === true && this.state.b === true) {
          this.setState({
            a: true,
            b: false,
          });
        } else if (this.state.a === true && this.state.b === false) {
          this.setState({
            a: false,
            b: false,
          });
        } else {
          this.setState({
            a: true,
            b: true,
          });
        }
      }

      render() {
        return (

 this.onClick()}>
            {this.state.a ?  : null}
            {this.state.b ?  : null}

        );
      }
    }

    render(<Comp />);
    const el = document.querySelector('[data-test-el]');
    expect(getCSS(document).trim()).toMatchInlineSnapshot(
      `"body{background:palevioletred;}body{color:white;}"`
    ); // should have both styles

    Simulate.click(el);
    expect(getCSS(document).trim()).toMatchInlineSnapshot(`"body{background:palevioletred;}"`); // should only have palevioletred

    Simulate.click(el);
    expect(getCSS(document).trim()).toMatchInlineSnapshot(`""`); // should be empty
  });

  it(`removes styling injected for multiple instances of same <GlobalStyle> components correctly`, () => {
    jest.spyOn(console, 'warn').mockImplementation(() => {});

    const { render } = context;

    const A = createGlobalStyle`
      body { background: ${props => props.bgColor}; }
    `;

    render();
    expect(getCSS(document).trim()).toMatchInlineSnapshot(`"body{background:blue;}"`);

    render();
    expect(getCSS(document).trim()).toMatchInlineSnapshot(`"body{background:red;}"`);

    render();
    expect(getCSS(document).trim()).toMatchInlineSnapshot(`""`);
  });

  it(`should warn when children are passed as props`, () => {
    jest.spyOn(console, 'warn').mockImplementation(() => {});

    const { render } = context;
    const Component = createGlobalStyle`
      div {
        color: ${props => props.fg};
        background: ${props => props.bg};
      }
    `;
    render(
      <Component fg="red" bg="green">

      </Component>
    );

    expect(console.warn.mock.calls[0][0]).toMatchInlineSnapshot(
      `"The global style component sc-global-a was given child JSX. createGlobalStyle does not render children."`
    );
  });

  it(`should warn when @import is used`, () => {
    jest.spyOn(console, 'warn').mockImplementation(() => {});

    const { render } = context;
    const Component = createGlobalStyle`
      @import url("something.css");
    `;
    render(<Component />);

    expect(console.warn.mock.calls[0][0]).toMatchInlineSnapshot(
      `"Please do not use @import CSS syntax in createGlobalStyle at this time, as the CSSOM APIs we use in production do not handle it well. Instead, we recommend using a library such as react-helmet to inject a typical <link> meta tag to the stylesheet, or simply embedding it manually in your index.html  section for a simpler app."`
    );
  });

  it('works with keyframes', () => {
    const { render } = context;

    const rotate360 = keyframes`
      from {
        transform: rotate(0deg);
      }

      to {
        transform: rotate(360deg);
      }
    `;

    const GlobalStyle = createGlobalStyle`
      div {
        display: inline-block;
        animation: ${rotate360} 2s linear infinite;
        padding: 2rem 1rem;
        font-size: 1.2rem;
      }
    `;

    render(

        <GlobalStyle />

< 💅 >

    );

    expect(getCSS(document).trim()).toMatchInlineSnapshot(
      `"div{display:inline-block;-webkit-animation:a 2s linear infinite;animation:a 2s linear infinite;padding:2rem 1rem;font-size:1.2rem;}@-webkit-keyframes a{from{-webkit-transform:rotate(0deg);-ms-transform:rotate(0deg);transform:rotate(0deg);}to{-webkit-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg);}}@keyframes a{from{-webkit-transform:rotate(0deg);-ms-transform:rotate(0deg);transform:rotate(0deg);}to{-webkit-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg);}}"`
    );
  });

  it(`removes style tag in StyleSheetManager.target when unmounted after target detached and no other global styles`, () => {
    // Set DISABLE_SPEEDY flag to false to force using speedy tag
    const flag = constants.DISABLE_SPEEDY;
    constants.DISABLE_SPEEDY = false;

    const container = document.createElement('div');
    document.body.appendChild(container);

    const styleContainer = document.createElement('div');
    document.body.appendChild(styleContainer);

    const Component = createGlobalStyle`[data-test-unmount-remove]{color:grey;} `;

    class Comp extends React.Component {
      render() {
        return (

        );
      }
    }

    ReactDOM.render(<Comp />, container);

    // Check styles
    const style = styleContainer.firstChild;
    expect(style.sheet.cssRules[0].selectorText).toBe('[data-test-unmount-remove]');

    // detach container and unmount react component
    try {
      document.body.removeChild(container);
      document.body.removeChild(styleContainer);

      ReactDOM.unmountComponentAtNode(container);
    } catch (e) {
      // eslint-disable-next-line no-undef
      fail('should not throw exception');
    }

    // Reset DISABLE_SPEEDY flag
    constants.DISABLE_SPEEDY = flag;
  });
});
<commit_msg>switch tests to getRenderedCSS<commit_after>/* eslint-disable no-console, import/namespace */
// @flow
import React from 'react';
import ReactDOM from 'react-dom';
import { act, Simulate } from 'react-dom/test-utils';
import ReactTestRenderer from 'react-test-renderer';
import * as constants from '../../constants';
import StyleSheetManager from '../../models/StyleSheetManager';
import ThemeProvider from '../../models/ThemeProvider';
import StyleSheet from '../../sheet';
import { getRenderedCSS, resetStyled } from '../../test/utils';
import createGlobalStyle from '../createGlobalStyle';
import keyframes from '../keyframes';

describe(`createGlobalStyle`, () => {
  let context;

  function setup() {
    const container = document.createElement('div');
    document.body.appendChild(container);

    return {
      container,
      render(comp) {
        ReactDOM.render(comp, container);
      },
      cleanup() {
        resetStyled();
        document.body.removeChild(container);
      },
    };
  }

  beforeEach(() => {
    context = setup();
  });

  afterEach(() => {
    context.cleanup();
  });

  it(`injects global <style> when rendered`, () => {
    const { render } = context;
    const Component = createGlobalStyle`[data-test-inject]{color:red;} `;
    render(<Component />);
    expect(getRenderedCSS()).toMatchInlineSnapshot(`
      "[data-test-inject]{ color:red; }
      "
    `);
  });

  it(`supports interpolation`, () => {
    const { render } = context;
    const Component = createGlobalStyle`div {color:${props => props.color};} `;
    render(<Component color="orange" />);
    expect(getRenderedCSS()).toMatchInlineSnapshot(`
      "div{ color:orange; }
      "
    `);
  });

  it(`supports objects with a function`, () => {
    const { render } = setup();
    const Component = createGlobalStyle({
      'h1, h2, h3, h4, h5, h6': {
        fontFamily: ({ theme }) => theme.fonts.heading,
      },
    });
    render(<Component theme={{ fonts: { heading: 'sans-serif' } }} />);
    expect(getRenderedCSS()).toMatchInlineSnapshot(`
      "h1,h2,h3,h4,h5,h6{ font-family:sans-serif; }
      "
    `);
  });

  it(`supports nested objects with a function`, () => {
    const { render } = setup();
    const Component1 = createGlobalStyle({
      'div, span': {
        h1: {
          span: {
            fontFamily: ({ theme }) => theme.fonts.heading,
          },
        },
      },
    });
    render(<Component1 theme={{ fonts: { heading: 'sans-serif' } }} />);
    expect(getRenderedCSS()).toMatchInlineSnapshot(`
      "div h1 span,span h1 span{ font-family:sans-serif; }
      "
    `);
  });

  it(`supports theming`, () => {
    const { render } = context;
    const Component = createGlobalStyle`div {color:${props => props.theme.color};} `;
    render(
      <ThemeProvider theme={{ color: 'black' }}>
        <Component />
      </ThemeProvider>
    );
    expect(getRenderedCSS()).toMatchInlineSnapshot(`
      "div{ color:black; }
      "
    `);
  });

  it(`updates theme correctly`, () => {
    const { render } = context;
    const Component = createGlobalStyle`div {color:${props => props.theme.color};} `;
    let update;
    class App extends React.Component {
      state = { color: 'grey' };

      constructor() {
        super();
        update = payload => {
          this.setState(payload);
        };
      }

      render() {
        return (
          <ThemeProvider theme={{ color: this.state.color }}>
            <Component />
          </ThemeProvider>
        );
      }
    }
    render(<App />);
    expect(getRenderedCSS()).toMatchInlineSnapshot(`
      "div{ color:grey; }
      "
    `);

    update({ color: 'red' });
    expect(getRenderedCSS()).toMatchInlineSnapshot(`
      "div{ color:red; }
      "
    `);
  });

  it('should work in StrictMode without warnings', () => {
    const { render } = context;
    const spy = jest.spyOn(console, 'error').mockImplementation(() => {});
    const Comp = createGlobalStyle`
      html {
        color: red;
      }
    `;

    act(() => {
      render(
        <React.StrictMode>
          <Comp />
        </React.StrictMode>
      );
    });

    expect(spy).not.toHaveBeenCalled();
  });

  it('should not inject twice in StrictMode', () => {
    jest.spyOn(StyleSheet, 'registerId');

    const { render } = context;
    const spy = jest.spyOn(console, 'error').mockImplementation(() => {});
    const Comp = createGlobalStyle`
      html {
        color: red;
      }
    `;

    act(() => {
      render(
        <React.StrictMode>
          <Comp />
        </React.StrictMode>
      );
    });

    expect(spy).not.toHaveBeenCalled();
    expect(StyleSheet.registerId).toHaveBeenCalledTimes(1);
  });

  it(`renders to StyleSheetManager.target`, () => {
    const { container, render } = context;
    const Component = createGlobalStyle`[data-test-target]{color:red;} `;
    render(

    );

    const style = container.firstChild;
    expect(style.tagName).toBe('STYLE');
    expect(style.textContent).toContain(`[data-test-target]{color:red;}`);
  });

  it(`adds new global rules non-destructively`, () => {
    const { render } = context;
    const Color = createGlobalStyle`[data-test-add]{color:red;} `;
    const Background = createGlobalStyle`[data-test-add]{background:yellow;} `;

    render(
      <React.Fragment>
        <Color />
        <Background />
      </React.Fragment>
    );

    expect(getRenderedCSS()).toMatchInlineSnapshot(`
      "[data-test-add]{ color:red; }
      [data-test-add]{ background:yellow; }
      "
    `);
  });

  it(`stringifies multiple rules correctly`, () => {
    const { render } = context;
    const Component = createGlobalStyle`
      div {
        color: ${props => props.fg};
        background: ${props => props.bg};
      }
    `;
    render(<Component fg="red" bg="green" />);
    expect(getRenderedCSS()).toMatchInlineSnapshot(`
      "div{ color:red; background:green; }
      "
    `);
  });

  it(`injects multiple <GlobalStyle> components correctly`, () => {
    const { render } = context;

    const A = createGlobalStyle`body { background: palevioletred; }`;
    const B = createGlobalStyle`body { color: white; }`;

    render(
      <React.Fragment>

      </React.Fragment>
    );
    expect(getRenderedCSS()).toMatchInlineSnapshot(`
      "body{ background:palevioletred; }
      body{ color:white; }
      "
    `);
  });

  it(`removes styling injected styling when unmounted`, () => {
    const ComponentA = createGlobalStyle`[data-test-remove]{color:grey;} `;
    const ComponentB = createGlobalStyle`[data-test-keep]{color:blue;} `;

    class Comp extends React.Component {
      render() {
        return this.props.insert ? <ComponentA /> : <ComponentB />;
      }
    }

    const renderer = ReactTestRenderer.create(<Comp insert />);

    ReactTestRenderer.act(() => {
      expect(getRenderedCSS()).toMatchInlineSnapshot(`
        "[data-test-remove]{ color:grey; }
        "
      `);

      renderer.update(<Comp insert={false} />);
    });

    ReactTestRenderer.act(() => {
      expect(getRenderedCSS()).toMatchInlineSnapshot(`
        "[data-test-keep]{ color:blue; }
        "
      `);
    });
  });

  it(`removes styling injected for multiple <GlobalStyle> components correctly`, () => {
    const { render } = context;

    const A = createGlobalStyle`body { background: palevioletred; }`;
    const B = createGlobalStyle`body { color: white; }`;

    class Comp extends React.Component {
      state = {
        a: true,
        b: true,
      };

      onClick() {
        if (this.state.a === true && this.state.b === true) {
          this.setState({
            a: true,
            b: false,
          });
        } else if (this.state.a === true && this.state.b === false) {
          this.setState({
            a: false,
            b: false,
          });
        } else {
          this.setState({
            a: true,
            b: true,
          });
        }
      }

      render() {
        return (

 this.onClick()}>
            {this.state.a ?  : null}
            {this.state.b ?  : null}

        );
      }
    }

    render(<Comp />);
    const el = document.querySelector('[data-test-el]');
    expect(getRenderedCSS()).toMatchInlineSnapshot(`
      "body{ background:palevioletred; }
      body{ color:white; }
      "
    `); // should have both styles

    Simulate.click(el);
    expect(getRenderedCSS()).toMatchInlineSnapshot(`
      "body{ background:palevioletred; }
      "
    `); // should only have palevioletred

    Simulate.click(el);
    expect(getRenderedCSS()).toMatchInlineSnapshot(`""`); // should be empty
  });

  it(`removes styling injected for multiple instances of same <GlobalStyle> components correctly`, () => {
    jest.spyOn(console, 'warn').mockImplementation(() => {});

    const { render } = context;

    const A = createGlobalStyle`
      body { background: ${props => props.bgColor}; }
    `;

    render();
    expect(getRenderedCSS()).toMatchInlineSnapshot(`
      "body{ background:blue; }
      "
    `);

    render();
    expect(getRenderedCSS()).toMatchInlineSnapshot(`
      "body{ background:red; }
      "
    `);

    render();
    expect(getRenderedCSS()).toMatchInlineSnapshot(`""`);
  });

  it(`should warn when children are passed as props`, () => {
    jest.spyOn(console, 'warn').mockImplementation(() => {});

    const { render } = context;
    const Component = createGlobalStyle`
      div {
        color: ${props => props.fg};
        background: ${props => props.bg};
      }
    `;
    render(
      <Component fg="red" bg="green">

      </Component>
    );

    expect(console.warn.mock.calls[0][0]).toMatchInlineSnapshot(
      `"The global style component sc-global-a was given child JSX. createGlobalStyle does not render children."`
    );
  });

  it(`should warn when @import is used`, () => {
    jest.spyOn(console, 'warn').mockImplementation(() => {});

    const { render } = context;
    const Component = createGlobalStyle`
      @import url("something.css");
    `;
    render(<Component />);

    expect(console.warn.mock.calls[0][0]).toMatchInlineSnapshot(
      `"Please do not use @import CSS syntax in createGlobalStyle at this time, as the CSSOM APIs we use in production do not handle it well. Instead, we recommend using a library such as react-helmet to inject a typical <link> meta tag to the stylesheet, or simply embedding it manually in your index.html  section for a simpler app."`
    );
  });

  it('works with keyframes', () => {
    const { render } = context;

    const rotate360 = keyframes`
      from {
        transform: rotate(0deg);
      }

      to {
        transform: rotate(360deg);
      }
    `;

    const GlobalStyle = createGlobalStyle`
      div {
        display: inline-block;
        animation: ${rotate360} 2s linear infinite;
        padding: 2rem 1rem;
        font-size: 1.2rem;
      }
    `;

    render(

        <GlobalStyle />

< 💅 >

    );

    expect(getRenderedCSS()).toMatchInlineSnapshot(`
      "div{ display:inline-block; -webkit-animation:a 2s linear infinite; animation:a 2s linear infinite; padding:2rem 1rem; font-size:1.2rem; }
      @-webkit-keyframes a{ from{ -webkit-transform:rotate(0deg); -ms-transform:rotate(0deg); transform:rotate(0deg); }
      to{ -webkit-transform:rotate(360deg); -ms-transform:rotate(360deg); transform:rotate(360deg); }
      }
      @keyframes a{ from{ -webkit-transform:rotate(0deg); -ms-transform:rotate(0deg); transform:rotate(0deg); }
      to{ -webkit-transform:rotate(360deg); -ms-transform:rotate(360deg); transform:rotate(360deg); }
      }
      "
    `);
  });

  it(`removes style tag in StyleSheetManager.target when unmounted after target detached and no other global styles`, () => {
    // Set DISABLE_SPEEDY flag to false to force using speedy tag
    const flag = constants.DISABLE_SPEEDY;
    constants.DISABLE_SPEEDY = false;

    const container = document.createElement('div');
    document.body.appendChild(container);

    const styleContainer = document.createElement('div');
    document.body.appendChild(styleContainer);

    const Component = createGlobalStyle`[data-test-unmount-remove]{color:grey;} `;

    class Comp extends React.Component {
      render() {
        return (

        );
      }
    }

    ReactDOM.render(<Comp />, container);

    // Check styles
    const style = styleContainer.firstChild;
    expect(style.sheet.cssRules[0].selectorText).toBe('[data-test-unmount-remove]');

    // detach container and unmount react component
    try {
      document.body.removeChild(container);
      document.body.removeChild(styleContainer);

      ReactDOM.unmountComponentAtNode(container);
    } catch (e) {
      // eslint-disable-next-line no-undef
      fail('should not throw exception');
    }

    // Reset DISABLE_SPEEDY flag
    constants.DISABLE_SPEEDY = flag;
  });
});
<|endoftext|>


<commit_before>/*global define*/
/*global FantasyLand*/
/*global _*/
(function(global, f){

  'use strict';

  /* istanbul ignore else */
  if(typeof module !== 'undefined'){
    module.exports = f(require('fantasy-land'), require('lodash.curry'));
  }

  else if(typeof define === 'function' && define.amd){
    define(['fantasy-land', 'lodash.curry'], f);
  }

  else{
    global.Fluture = f(FantasyLand, _.curry);
  }

}(global || window || this, function(FL, curry){

  'use strict';

  ////////////////////
  // Error handling //
  ////////////////////

  //A toString function to provide a slightly more meaningful representation of values.
  const toString = x =>
    typeof x === 'string'
    ? JSON.stringify(x)
    : Array.isArray(x)
    ? `[${x.map(toString).join(', ')}]`
    : x && (typeof x.toString === 'function')
    ? x.toString === Object.prototype.toString
    ? `{${Object.keys(x).reduce((o, k) => o.concat(`${toString(k)}: ${toString(x[k])}`), []).join(', ')}}`
    : x.toString()
    : String(x);

  function error$invalidArgument(it, at, expected, actual){
    throw new TypeError(
      `${it} expects argument ${at} to ${expected}\n  Actual: ${toString(actual)}`
    );
  }

  function error$invalidContext(it, actual){
    throw new TypeError(
      `${it} was invoked outside the context of a Future. You might want to use`
      + ` a dispatcher instead\n  Called on: ${toString(actual)}`
    )
  }

  //Check input to Future.
  function check$Future(fork){
    if(typeof fork !== 'function') error$invalidArgument('Future', 0, 'be a function', fork);
  }

  //Check input to Future#fork.
  function check$fork(it, rej, res){
    if(!(it instanceof FutureClass)) error$invalidContext('Future#chain', it);
    if(typeof rej !== 'function') error$invalidArgument('Future#fork', 0, 'be a function', rej);
    if(typeof res !== 'function') error$invalidArgument('Future#fork', 1, 'be a function', res);
  }

  //Check input to Future#chain.
  function check$chain(it, f){
    if(!(it instanceof FutureClass)) error$invalidContext('Future#chain', it);
    if(typeof f !== 'function') error$invalidArgument('Future#chain', 0, 'be a function', f);
  }

  //Check output from the function passed to Future#chain.
  function check$chain$f(m, f, x){
    if(!(m instanceof FutureClass)) throw new TypeError(
      'Future#chain expects the function its given to return a Future'
      + `\n  Actual: ${toString(m)}\n  From calling: ${toString(f)}\n  With: ${toString(x)}`
    );
  }

  function check$chainRej(it, f){
    if(!(it instanceof FutureClass)) error$invalidContext('Future.chainRej', it);
    if(typeof f !== 'function') error$invalidArgument('Future.chainRej', 0, 'a function', f);
  }

  function check$chainRej$f(m, f, x){
    if(!(m instanceof FutureClass)) throw new TypeError(
      'Future.chainRej expects the function its given to return a Future'
      + `\n  Actual: ${toString(m)}\n  From calling: ${toString(f)}\n  With: ${toString(x)}`
    );
  }

  //Check input to Future#map.
  function check$map(it, f){
    if(!(it instanceof FutureClass)) error$invalidContext('Future#map', it);
    if(typeof f !== 'function') error$invalidArgument('Future#map', 0, 'be a function', f);
  }

  //Check input to Future#ap.
  function check$ap(it, m){
    if(!(it instanceof FutureClass)) error$invalidContext('Future#map', it);
    if(!(m instanceof FutureClass)) error$invalidArgument('Future#ap', 0, 'be a Future', m);
  }

  //Check resolution value of the Future on which #ap was called.
  function check$ap$f(f){
    if(typeof f !== 'function') throw new TypeError(
      `Future#ap can only b used on Future<Function> but was used on: ${toString(f)}`
    );
  }

  function check$race(it, m){
    if(!(it instanceof FutureClass)) error$invalidContext('Future.race', it);
    if(!(m instanceof FutureClass)) error$invalidArgument('Future.race', 0, 'be a function', m);
  }

  function check$cache(m){
    if(!(m instanceof FutureClass)) error$invalidArgument('Future.cache', 0, 'be a Future', m);
  }

  function check$cache$settle(oldState, newState, oldValue, newValue){
    if(oldState > 1) throw new Error(
      'Future.cache expects the Future it wraps to only resolve or reject once; '
      + ' a cached Future tried to ' + (newState === 2 ? 'reject' : 'resolve') + ' a second time.'
      + ' Please check your cached Future and make sure it does not call res or rej multiple times'
      + '\n  It was ' + (oldState === 2 ? 'rejected' : 'resolved') + ' with: ' + toString(oldValue)
      + '\n  It got ' + (newState === 2 ? 'rejected' : 'resolved') + ' with: ' + toString(newValue)
    );
  }

  function check$after(n){
    if(typeof n !== 'number') error$invalidArgument('Future.after', 0, 'be a number', n);
  }

  function check$try(f){
    if(typeof f !== 'function') error$invalidArgument('Future.try', 0, 'be a function', f);
  }

  function check$node(f){
    if(typeof f !== 'function') error$invalidArgument('Future.node', 0, 'be a function', f);
  }

  ////////////
  // Future //
  ////////////

  //Constructor.
  function FutureClass(f){
    this._f = f;
  }

  //A createFuture function which pretends to be Future.
  function Future(f){
    check$Future(f);
    return new FutureClass(f);
  }

  //The of method.
  function Future$of(x){
    return new FutureClass(function Future$of$fork(rej, res){
      res(x)
    });
  }

  function Future$fork(rej, res){
    check$fork(this, rej, res);
    this._f(rej, res);
  }

  function Future$chain(f){
    check$chain(this, f);
    const _this = this;
    return new FutureClass(function Future$chain$fork(rej, res){
      _this._f(rej, function Future$chain$res(x){
        const m = f(x);
        check$chain$f(m, f, x);
        m._f(rej, res);
      });
    });
  }

  function Future$chainRej(f){
    check$chainRej(this, f);
    const _this = this;
    return new FutureClass(function Future$chainRej$fork(rej, res){
      _this._f(function Future$chainRej$rej(x){
        const m = f(x);
        check$chainRej$f(m, f, x);
        m._f(rej, res);
      }, res);
    });
  }

  function Future$map(f){
    check$map(this, f);
    const _this = this;
    return new FutureClass(function Future$map$fork(rej, res){
      _this._f(rej, function Future$map$res(x){
        res(f(x));
      });
    });
  }

  function Future$ap(m){
    check$ap(this, m);
    const _this = this;
    return new FutureClass(function Future$ap$fork(g, h){
      let _f, _x, ok1, ok2, ko;
      const rej = x => ko || (ko = 1, g(x));
      _this._f(rej, function Future$ap$resThis(f){
        if(!ok2) return void (ok1 = 1, _f = f);
        check$ap$f(f);
        h(f(_x));
      });
      m._f(rej, function Future$ap$resThat(x){
        if(!ok1) return void (ok2 = 1, _x = x)
        check$ap$f(_f);
        h(_f(x));
      });
    });
  }

  function Future$toString(){
    return `Future(${toString(this._f)})`;
  }

  function Future$race(m){
    check$race(this, m);
    const _this = this;
    return new FutureClass(function Future$race$fork(rej, res){
      let settled = false;
      const once = f => a => settled || (settled = true, f(a));
      _this._f(once(rej), once(res));
      m._f(once(rej), once(res));
    });
  }

  //Give Future a prototype.
  FutureClass.prototype = Future.prototype = {
    _f: null,
    fork: Future$fork,
    [FL.of]: Future$of,
    of: Future$of,
    [FL.chain]: Future$chain,
    chain: Future$chain,
    chainRej: Future$chainRej,
    [FL.map]: Future$map,
    map: Future$map,
    [FL.ap]: Future$ap,
    ap: Future$ap,
    toString: Future$toString,
    race: Future$race
  };

  //Expose `of` statically as well.
  Future[FL.of] = Future.of = Future$of;

  //Expose Future statically for ease of destructuring.
  Future.Future = Future;

  /////////////////
  // Dispatchers //
  /////////////////

  //Creates a dispatcher for a unary method.
  function createUnaryDispatcher(method){
    return curry(function dispatch(a, m){
      if(m && typeof m[method] === 'function') return m[method](a);
      error$invalidArgument(`Future.${method}`, 1, `have a "${method}" method`, m);
    });
  }

  //Creates a dispatcher for a binary method.
  function createBinaryDispatcher(method){
    return curry(function dispatch(a, b, m){
      if(m && typeof m[method] === 'function') return m[method](a, b);
      error$invalidArgument(`Future.${method}`, 2, `have a "${method}" method`, m);
    });
  }

  //chain :: Chain m => (a -> m b) -> m a -> m b
  Future.chain = createUnaryDispatcher('chain');

  //chainRej :: (a -> Future a c) -> Future a b -> Future a c
  Future.chainRej = createUnaryDispatcher('chainRej');

  //map :: Functor m => (a -> b) -> m a -> m b
  Future.map = createUnaryDispatcher('map');

  //ap :: Apply m => m (a -> b) -> m a -> m b
  Future.ap = curry(function dispatch$ap(m, a){
    if(m && typeof m.ap === 'function') return m.ap(a);
    error$invalidArgument('Future.ap', 0, 'have a "ap" method', m);
  });

  //fork :: (a -> Void) -> (b -> Void) -> Future a b -> Void
  Future.fork = createBinaryDispatcher('fork');

  //race :: Future a b -> Future a b -> Future a b
  Future.race = createUnaryDispatcher('race');

  ///////////////
  // Utilities //
  ///////////////

  // Cache a Future.
  // Returns a Future which caches the resolution value of the given Future so
  // that whenever it's forked, it can load the value from cache rather than
  // reexecuting the chain.
  Future.cache = function Future$cache(m){
    check$cache(m);
    let que = [];
    let value, state;
    const settleWith = newState => function Future$cache$settle(newValue){
      check$cache$settle(state, newState, value, newValue);
      value = newValue; state = newState;
      for(let i = 0, l = que.length; i < l; i++){
        que[i][state](value);
        que[i] = undefined;
      }
      que = undefined;
    };
    return new FutureClass(function Future$cache$fork(rej, res){
      switch(state){
        case 1: que.push({2: rej, 3: res}); break;
        case 2: rej(value); break;
        case 3: res(value); break;
        default:
          state = 1;
          que.push({2: rej, 3: res});
          m.fork(settleWith(2), settleWith(3));
      }
    });
  };

  //Create a Future which rejects witth the given value.
  Future.reject = function Future$reject(x){
    return new FutureClass(function Future$reject$fork(rej){
      rej(x);
    });
  };

  //Create a Future which resolves after the given time with the given value.
  Future.after = curry(function Future$after(n, x){
    check$after(n);
    return new FutureClass(function Future$after$fork(rej, res){
      setTimeout(res, n, x);
    })
  });

  //Create a Future which resolves with the return value of the given function,
  //or rejects with the exception thrown by the given function.
  Future.try = function Future$try(f){
    check$try(f);
    return new FutureClass(function Future$try$fork(rej, res){
      try{
        res(f());
      }
      catch(err){
        rej(err);
      }
    });
  };

  //node :: ((err, a) -> Void) -> Future[Error, a]
  Future.node = function Future$node(f){
    check$node(f);
    return new FutureClass(function Future$node$fork(rej, res){
      f((a, b) => a ? rej(a) : res(b));
    });
  };

  //Export Future factory.
  return Future;

}));
<commit_msg>Use Future$toString for Future#inspect<commit_after>/*global define*/
/*global FantasyLand*/
/*global _*/
(function(global, f){

  'use strict';

  /* istanbul ignore else */
  if(typeof module !== 'undefined'){
    module.exports = f(require('fantasy-land'), require('lodash.curry'));
  }

  else if(typeof define === 'function' && define.amd){
    define(['fantasy-land', 'lodash.curry'], f);
  }

  else{
    global.Fluture = f(FantasyLand, _.curry);
  }

}(global || window || this, function(FL, curry){

  'use strict';

  ////////////////////
  // Error handling //
  ////////////////////

  //A toString function to provide a slightly more meaningful representation of values.
  const toString = x =>
    typeof x === 'string'
    ? JSON.stringify(x)
    : Array.isArray(x)
    ? `[${x.map(toString).join(', ')}]`
    : x && (typeof x.toString === 'function')
    ? x.toString === Object.prototype.toString
    ? `{${Object.keys(x).reduce((o, k) => o.concat(`${toString(k)}: ${toString(x[k])}`), []).join(', ')}}`
    : x.toString()
    : String(x);

  function error$invalidArgument(it, at, expected, actual){
    throw new TypeError(
      `${it} expects argument ${at} to ${expected}\n  Actual: ${toString(actual)}`
    );
  }

  function error$invalidContext(it, actual){
    throw new TypeError(
      `${it} was invoked outside the context of a Future. You might want to use`
      + ` a dispatcher instead\n  Called on: ${toString(actual)}`
    )
  }

  //Check input to Future.
  function check$Future(fork){
    if(typeof fork !== 'function') error$invalidArgument('Future', 0, 'be a function', fork);
  }

  //Check input to Future#fork.
  function check$fork(it, rej, res){
    if(!(it instanceof FutureClass)) error$invalidContext('Future#chain', it);
    if(typeof rej !== 'function') error$invalidArgument('Future#fork', 0, 'be a function', rej);
    if(typeof res !== 'function') error$invalidArgument('Future#fork', 1, 'be a function', res);
  }

  //Check input to Future#chain.
  function check$chain(it, f){
    if(!(it instanceof FutureClass)) error$invalidContext('Future#chain', it);
    if(typeof f !== 'function') error$invalidArgument('Future#chain', 0, 'be a function', f);
  }

  //Check output from the function passed to Future#chain.
  function check$chain$f(m, f, x){
    if(!(m instanceof FutureClass)) throw new TypeError(
      'Future#chain expects the function its given to return a Future'
      + `\n  Actual: ${toString(m)}\n  From calling: ${toString(f)}\n  With: ${toString(x)}`
    );
  }

  function check$chainRej(it, f){
    if(!(it instanceof FutureClass)) error$invalidContext('Future.chainRej', it);
    if(typeof f !== 'function') error$invalidArgument('Future.chainRej', 0, 'a function', f);
  }

  function check$chainRej$f(m, f, x){
    if(!(m instanceof FutureClass)) throw new TypeError(
      'Future.chainRej expects the function its given to return a Future'
      + `\n  Actual: ${toString(m)}\n  From calling: ${toString(f)}\n  With: ${toString(x)}`
    );
  }

  //Check input to Future#map.
  function check$map(it, f){
    if(!(it instanceof FutureClass)) error$invalidContext('Future#map', it);
    if(typeof f !== 'function') error$invalidArgument('Future#map', 0, 'be a function', f);
  }

  //Check input to Future#ap.
  function check$ap(it, m){
    if(!(it instanceof FutureClass)) error$invalidContext('Future#map', it);
    if(!(m instanceof FutureClass)) error$invalidArgument('Future#ap', 0, 'be a Future', m);
  }

  //Check resolution value of the Future on which #ap was called.
  function check$ap$f(f){
    if(typeof f !== 'function') throw new TypeError(
      `Future#ap can only b used on Future<Function> but was used on: ${toString(f)}`
    );
  }

  function check$race(it, m){
    if(!(it instanceof FutureClass)) error$invalidContext('Future.race', it);
    if(!(m instanceof FutureClass)) error$invalidArgument('Future.race', 0, 'be a function', m);
  }

  function check$cache(m){
    if(!(m instanceof FutureClass)) error$invalidArgument('Future.cache', 0, 'be a Future', m);
  }

  function check$cache$settle(oldState, newState, oldValue, newValue){
    if(oldState > 1) throw new Error(
      'Future.cache expects the Future it wraps to only resolve or reject once; '
      + ' a cached Future tried to ' + (newState === 2 ? 'reject' : 'resolve') + ' a second time.'
      + ' Please check your cached Future and make sure it does not call res or rej multiple times'
      + '\n  It was ' + (oldState === 2 ? 'rejected' : 'resolved') + ' with: ' + toString(oldValue)
      + '\n  It got ' + (newState === 2 ? 'rejected' : 'resolved') + ' with: ' + toString(newValue)
    );
  }

  function check$after(n){
    if(typeof n !== 'number') error$invalidArgument('Future.after', 0, 'be a number', n);
  }

  function check$try(f){
    if(typeof f !== 'function') error$invalidArgument('Future.try', 0, 'be a function', f);
  }

  function check$node(f){
    if(typeof f !== 'function') error$invalidArgument('Future.node', 0, 'be a function', f);
  }

  ////////////
  // Future //
  ////////////

  //Constructor.
  function FutureClass(f){
    this._f = f;
  }

  //A createFuture function which pretends to be Future.
  function Future(f){
    check$Future(f);
    return new FutureClass(f);
  }

  //The of method.
  function Future$of(x){
    return new FutureClass(function Future$of$fork(rej, res){
      res(x)
    });
  }

  function Future$fork(rej, res){
    check$fork(this, rej, res);
    this._f(rej, res);
  }

  function Future$chain(f){
    check$chain(this, f);
    const _this = this;
    return new FutureClass(function Future$chain$fork(rej, res){
      _this._f(rej, function Future$chain$res(x){
        const m = f(x);
        check$chain$f(m, f, x);
        m._f(rej, res);
      });
    });
  }

  function Future$chainRej(f){
    check$chainRej(this, f);
    const _this = this;
    return new FutureClass(function Future$chainRej$fork(rej, res){
      _this._f(function Future$chainRej$rej(x){
        const m = f(x);
        check$chainRej$f(m, f, x);
        m._f(rej, res);
      }, res);
    });
  }

  function Future$map(f){
    check$map(this, f);
    const _this = this;
    return new FutureClass(function Future$map$fork(rej, res){
      _this._f(rej, function Future$map$res(x){
        res(f(x));
      });
    });
  }

  function Future$ap(m){
    check$ap(this, m);
    const _this = this;
    return new FutureClass(function Future$ap$fork(g, h){
      let _f, _x, ok1, ok2, ko;
      const rej = x => ko || (ko = 1, g(x));
      _this._f(rej, function Future$ap$resThis(f){
        if(!ok2) return void (ok1 = 1, _f = f);
        check$ap$f(f);
        h(f(_x));
      });
      m._f(rej, function Future$ap$resThat(x){
        if(!ok1) return void (ok2 = 1, _x = x)
        check$ap$f(_f);
        h(_f(x));
      });
    });
  }

  function Future$toString(){
    return `Future(${toString(this._f)})`;
  }

  function Future$race(m){
    check$race(this, m);
    const _this = this;
    return new FutureClass(function Future$race$fork(rej, res){
      let settled = false;
      const once = f => a => settled || (settled = true, f(a));
      _this._f(once(rej), once(res));
      m._f(once(rej), once(res));
    });
  }

  //Give Future a prototype.
  FutureClass.prototype = Future.prototype = {
    _f: null,
    fork: Future$fork,
    [FL.of]: Future$of,
    of: Future$of,
    [FL.chain]: Future$chain,
    chain: Future$chain,
    chainRej: Future$chainRej,
    [FL.map]: Future$map,
    map: Future$map,
    [FL.ap]: Future$ap,
    ap: Future$ap,
    toString: Future$toString,
    inspect: Future$toString,
    race: Future$race
  };

  //Expose `of` statically as well.
  Future[FL.of] = Future.of = Future$of;

  //Expose Future statically for ease of destructuring.
  Future.Future = Future;

  /////////////////
  // Dispatchers //
  /////////////////

  //Creates a dispatcher for a unary method.
  function createUnaryDispatcher(method){
    return curry(function dispatch(a, m){
      if(m && typeof m[method] === 'function') return m[method](a);
      error$invalidArgument(`Future.${method}`, 1, `have a "${method}" method`, m);
    });
  }

  //Creates a dispatcher for a binary method.
  function createBinaryDispatcher(method){
    return curry(function dispatch(a, b, m){
      if(m && typeof m[method] === 'function') return m[method](a, b);
      error$invalidArgument(`Future.${method}`, 2, `have a "${method}" method`, m);
    });
  }

  //chain :: Chain m => (a -> m b) -> m a -> m b
  Future.chain = createUnaryDispatcher('chain');

  //chainRej :: (a -> Future a c) -> Future a b -> Future a c
  Future.chainRej = createUnaryDispatcher('chainRej');

  //map :: Functor m => (a -> b) -> m a -> m b
  Future.map = createUnaryDispatcher('map');

  //ap :: Apply m => m (a -> b) -> m a -> m b
  Future.ap = curry(function dispatch$ap(m, a){
    if(m && typeof m.ap === 'function') return m.ap(a);
    error$invalidArgument('Future.ap', 0, 'have a "ap" method', m);
  });

  //fork :: (a -> Void) -> (b -> Void) -> Future a b -> Void
  Future.fork = createBinaryDispatcher('fork');

  //race :: Future a b -> Future a b -> Future a b
  Future.race = createUnaryDispatcher('race');

  ///////////////
  // Utilities //
  ///////////////

  // Cache a Future.
  // Returns a Future which caches the resolution value of the given Future so
  // that whenever it's forked, it can load the value from cache rather than
  // reexecuting the chain.
  Future.cache = function Future$cache(m){
    check$cache(m);
    let que = [];
    let value, state;
    const settleWith = newState => function Future$cache$settle(newValue){
      check$cache$settle(state, newState, value, newValue);
      value = newValue; state = newState;
      for(let i = 0, l = que.length; i < l; i++){
        que[i][state](value);
        que[i] = undefined;
      }
      que = undefined;
    };
    return new FutureClass(function Future$cache$fork(rej, res){
      switch(state){
        case 1: que.push({2: rej, 3: res}); break;
        case 2: rej(value); break;
        case 3: res(value); break;
        default:
          state = 1;
          que.push({2: rej, 3: res});
          m.fork(settleWith(2), settleWith(3));
      }
    });
  };

  //Create a Future which rejects witth the given value.
  Future.reject = function Future$reject(x){
    return new FutureClass(function Future$reject$fork(rej){
      rej(x);
    });
  };

  //Create a Future which resolves after the given time with the given value.
  Future.after = curry(function Future$after(n, x){
    check$after(n);
    return new FutureClass(function Future$after$fork(rej, res){
      setTimeout(res, n, x);
    })
  });

  //Create a Future which resolves with the return value of the given function,
  //or rejects with the exception thrown by the given function.
  Future.try = function Future$try(f){
    check$try(f);
    return new FutureClass(function Future$try$fork(rej, res){
      try{
        res(f());
      }
      catch(err){
        rej(err);
      }
    });
  };

  //node :: ((err, a) -> Void) -> Future[Error, a]
  Future.node = function Future$node(f){
    check$node(f);
    return new FutureClass(function Future$node$fork(rej, res){
      f((a, b) => a ? rej(a) : res(b));
    });
  };

  //Export Future factory.
  return Future;

}));
<|endoftext|>


<commit_before>(function(po) {
  po.loupe = function() {
    var loupe = po.map(),
        container = po.svg("g"),
        clipId = "org.polymaps." + po.id(),
        clipHref = "url(#" + clipId + ")",
        clipPath = container.appendChild(po.svg("clipPath")),
        clipCircle = clipPath.appendChild(po.svg("circle")),
        back = po.svg("circle"),
        fore = po.svg("circle"),
        visible = true,
        r = 128,
        rr = [64, 384],
        k = 1,
        map,
        f0,
        m0,
        p0,
        p1 = {x: 0, y: 0},
        repeatInterval,
        repeatRate = 30,
        repeatPan = {x: 0, y: 0};

    loupe
        .size({x: r * 2, y: r * 2})
        .container(container)
        .centerRange(null)
        .zoomRange(null)
        .on("move", move);

    container.appendChild(back).setAttribute("class", "back");
    container.appendChild(fore).setAttribute("class", "fore");
    clipPath.setAttribute("id", clipId);
    container.setAttribute("class", "map loupe");

    back.addEventListener("mousedown", mousedown, false);
    fore.addEventListener("mousedown", foredown, false);
    fore.setAttribute("cursor", "ew-resize");
    window.addEventListener("mouseup", mouseup, false);
    window.addEventListener("mousemove", mousemove, false);

    function move() {
      var p = map.locationPoint(loupe.center()),
          z0 = map.zoom(),
          z1 = loupe.zoom();
      if (z0 != z1) {
        loupe.off("move", move).zoom(z0).on("move", move);
        clipCircle.setAttribute("r", r * (k = Math.pow(2, Math.round(z0) - z0)));
      }
      container.setAttribute("transform", "translate(" + (p.x - r) + "," + (p.y - r) + ")");
    }

    function foredown(e) {
      f0 = true;
      document.body.style.setProperty("cursor", "ew-resize", null);
      map.focusableParent().focus();
      return cancel(e);
    }

    function foremove(e) {
      var p0 = map.mouse(e),
          p1 = map.locationPoint(loupe.center()),
          dx = p1.x - p0.x,
          dy = p1.y - p0.y,
           r = Math.sqrt(dx * dx + dy * dy);
      loupe.radius(r ^ (r & 1));
      return cancel(e);
    }

    function mousedown(e) {
      m0 = map.mouse(e);
      p0 = map.locationPoint(loupe.center());
      map.focusableParent().focus();
      return cancel(e);
    }

    function mousemove(e) {
      if (f0) return foremove(e);
      if (!m0) return;
      var m1 = map.mouse(e),
          size = map.size();

      // determine the new loupe point, and whether it's offscreen
      p1.x = p0.x - m0.x + m1.x;
      p1.y = p0.y - m0.y + m1.y;
      repeatPan.x = p1.x < 0 ? -p1.x : p1.x > size.x ? size.x - p1.x : 0;
      repeatPan.y = p1.y < 0 ? -p1.y : p1.y > size.y ? size.y - p1.y : 0;

      // if the loupe is offscreen, start a new pan interval
      if (repeatPan.x || repeatPan.y) {
        repeatPan.x /= 10;
        repeatPan.y /= 10;
        if (!repeatInterval) repeatInterval = setInterval(mouserepeat, repeatRate);
      } else if (repeatInterval) {
        repeatInterval = clearInterval(repeatInterval);
      }

      loupe.center(map.pointLocation(p1));
      return cancel(e);
    }

    function mouserepeat() {
      map.panBy(repeatPan);
      loupe.center(map.pointLocation(p1));
    }

    function mouseup(e) {
      if (f0) {
        f0 = null;
        document.body.style.removeProperty("cursor");
      }
      if (m0) {
        if (repeatInterval) repeatInterval = clearInterval(repeatInterval);
        m0 = p0 = null;
      }
      return cancel(e);
    }

    function cancel(e) {
      e.stopPropagation();
      e.preventDefault();
      return false;
    }

    loupe.map = function(x) {
      if (!arguments.length) return map;
      if (map) {
        map.container().removeChild(loupe.container());
        map.off("move", move).off("resize", move);
      }
      if (map = x) {
        map.on("move", move).on("resize", move);
        map.container().appendChild(loupe.container());
        move();
      }
      return loupe;
    };

    var __add__ = loupe.add;
    loupe.add = function(x) {
      x.map(loupe);
      if (x.container) {
        x = x.container();
        x.setAttribute("clip-path", clipHref);
        x.setAttribute("pointer-events", "none");
      }
      container.appendChild(fore); // move to end
      return loupe;
    };

    loupe.radiusRange = function(x) {
      if (!arguments.length) return rr;
      rr = x;
      return loupe.radius(r);
    };

    loupe.radius = function(x) {
      if (!arguments.length) return r;
      r = rr ? Math.max(rr[0], Math.min(rr[1], x)) : x;
      back.setAttribute("cx", r);
      back.setAttribute("cy", r);
      back.setAttribute("r", r);
      fore.setAttribute("cx", r);
      fore.setAttribute("cy", r);
      fore.setAttribute("r", r);
      clipCircle.setAttribute("r", r * k);
      loupe.size({x: r * 2, y: r * 2})
      if (map) move();
      return loupe;
    };

    loupe.visible = function(x) {
      if (!arguments.length) return visible;
      visible = x;
      if (x) g.removeAttribute("visibility");
      else g.setAttribute("visibility", "hidden");
      return loupe;
    };

    loupe.radius(r); // initialize circles

    return loupe;
  };
})(org.polymaps);
<commit_msg>Fix a bug in loupe implementation.<commit_after>(function(po) {
  po.loupe = function() {
    var loupe = po.map(),
        container = po.svg("g"),
        clipId = "org.polymaps." + po.id(),
        clipHref = "url(#" + clipId + ")",
        clipPath = container.appendChild(po.svg("clipPath")),
        clipCircle = clipPath.appendChild(po.svg("circle")),
        back = po.svg("circle"),
        fore = po.svg("circle"),
        visible = true,
        r = 128,
        rr = [64, 384],
        k = 1,
        map,
        f0,
        m0,
        p0,
        p1 = {x: 0, y: 0},
        repeatInterval,
        repeatRate = 30,
        repeatPan = {x: 0, y: 0};

    loupe
        .size({x: r * 2, y: r * 2})
        .container(container)
        .centerRange(null)
        .zoomRange(null)
        .on("move", move);

    container.appendChild(back).setAttribute("class", "back");
    container.appendChild(fore).setAttribute("class", "fore");
    clipPath.setAttribute("id", clipId);
    container.setAttribute("class", "map loupe");

    back.addEventListener("mousedown", mousedown, false);
    fore.addEventListener("mousedown", foredown, false);
    fore.setAttribute("fill", "none");
    fore.setAttribute("cursor", "ew-resize");
    window.addEventListener("mouseup", mouseup, false);
    window.addEventListener("mousemove", mousemove, false);

    function move() {
      if (!map) return;
      var p = map.locationPoint(loupe.center()),
          z0 = map.zoom(),
          z1 = loupe.zoom();
      if (z0 != z1) {
        loupe.off("move", move).zoom(z0).on("move", move);
        clipCircle.setAttribute("r", r * (k = Math.pow(2, Math.round(z0) - z0)));
      }
      container.setAttribute("transform", "translate(" + (p.x - r) + "," + (p.y - r) + ")");
    }

    function foredown(e) {
      f0 = true;
      document.body.style.setProperty("cursor", "ew-resize", null);
      map.focusableParent().focus();
      return cancel(e);
    }

    function foremove(e) {
      var p0 = map.mouse(e),
          p1 = map.locationPoint(loupe.center()),
          dx = p1.x - p0.x,
          dy = p1.y - p0.y,
           r = Math.sqrt(dx * dx + dy * dy);
      loupe.radius(r ^ (r & 1));
      return cancel(e);
    }

    function mousedown(e) {
      m0 = map.mouse(e);
      p0 = map.locationPoint(loupe.center());
      map.focusableParent().focus();
      return cancel(e);
    }

    function mousemove(e) {
      if (f0) return foremove(e);
      if (!m0) return;
      var m1 = map.mouse(e),
          size = map.size();

      // determine the new loupe point, and whether it's offscreen
      p1.x = p0.x - m0.x + m1.x;
      p1.y = p0.y - m0.y + m1.y;
      repeatPan.x = p1.x < 0 ? -p1.x : p1.x > size.x ? size.x - p1.x : 0;
      repeatPan.y = p1.y < 0 ? -p1.y : p1.y > size.y ? size.y - p1.y : 0;

      // if the loupe is offscreen, start a new pan interval
      if (repeatPan.x || repeatPan.y) {
        repeatPan.x /= 10;
        repeatPan.y /= 10;
        if (!repeatInterval) repeatInterval = setInterval(mouserepeat, repeatRate);
      } else if (repeatInterval) {
        repeatInterval = clearInterval(repeatInterval);
      }

      loupe.center(map.pointLocation(p1));
      return cancel(e);
    }

    function mouserepeat() {
      map.panBy(repeatPan);
      loupe.center(map.pointLocation(p1));
    }

    function mouseup(e) {
      if (f0) {
        f0 = null;
        document.body.style.removeProperty("cursor");
      }
      if (m0) {
        if (repeatInterval) repeatInterval = clearInterval(repeatInterval);
        m0 = p0 = null;
      }
      return cancel(e);
    }

    function cancel(e) {
      e.stopPropagation();
      e.preventDefault();
      return false;
    }

    loupe.map = function(x) {
      if (!arguments.length) return map;
      if (map) {
        map.container().removeChild(loupe.container());
        map.off("move", move).off("resize", move);
      }
      if (map = x) {
        map.on("move", move).on("resize", move);
        map.container().appendChild(loupe.container());
        move();
      }
      return loupe;
    };

    var __add__ = loupe.add;
    loupe.add = function(x) {
      x.map(loupe);
      if (x.container) {
        x = x.container();
        x.setAttribute("clip-path", clipHref);
        x.setAttribute("pointer-events", "none");
      }
      container.appendChild(fore); // move to end
      return loupe;
    };

    loupe.radiusRange = function(x) {
      if (!arguments.length) return rr;
      rr = x;
      return loupe.radius(r);
    };

    loupe.radius = function(x) {
      if (!arguments.length) return r;
      r = rr ? Math.max(rr[0], Math.min(rr[1], x)) : x;
      back.setAttribute("cx", r);
      back.setAttribute("cy", r);
      back.setAttribute("r", r);
      fore.setAttribute("cx", r);
      fore.setAttribute("cy", r);
      fore.setAttribute("r", r);
      clipCircle.setAttribute("r", r * k);
      loupe.size({x: r * 2, y: r * 2})
      if (map) move();
      return loupe;
    };

    loupe.visible = function(x) {
      if (!arguments.length) return visible;
      visible = x;
      if (x) g.removeAttribute("visibility");
      else g.setAttribute("visibility", "hidden");
      return loupe;
    };

    loupe.radius(r); // initialize circles

    return loupe;
  };
})(org.polymaps);
<|endoftext|>


<commit_before>var createIpValidator = require('is-my-ip-valid')

var reEmailWhitespace = /\s/
var reHostnameFirstPass = /^[a-zA-Z0-9.-]+$/
var reHostnamePart = /^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])$/
var rePhoneFirstPass = /^\+[0-9][0-9 ]{5,27}[0-9]$/
var rePhoneDoubleSpace = / {2}/
var rePhoneGlobalSpace = / /g

exports['date-time'] = /^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}[tT ]\d{2}:\d{2}:\d{2}(?:\.\d+|)([zZ]|[+-]\d{2}:\d{2})$/
exports['date'] = /^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}$/
exports['time'] = /^\d{2}:\d{2}:\d{2}$/
exports['email'] = function (input) { return (input.indexOf('@') !== -1) && (!reEmailWhitespace.test(input)) }
exports['ip-address'] = exports['ipv4'] = createIpValidator({ version: 4 })
exports['ipv6'] = createIpValidator({ version: 6 })
exports['uri'] = /^[a-zA-Z][a-zA-Z0-9+-.]*:[^\s]*$/
exports['color'] = /(#?([0-9A-Fa-f]{3,6})\b)|(aqua)|(black)|(blue)|(fuchsia)|(gray)|(green)|(lime)|(maroon)|(navy)|(olive)|(orange)|(purple)|(red)|(silver)|(teal)|(white)|(yellow)|(rgb\(\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*\))|(rgb\(\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*\))/
exports['hostname'] = function (input) {
  if (!(reHostnameFirstPass.test(input))) return false

  var parts = input.split('.')

  for (var i = 0; i < parts.length; i++) {
    if (!(reHostnamePart.test(parts[i]))) return false
  }

  return true
}
exports['alpha'] = /^[a-zA-Z]+$/
exports['alphanumeric'] = /^[a-zA-Z0-9]+$/
exports['style'] = /\s*(.+?):\s*([^;]+);?/g
exports['phone'] = function (input) {
  if (!(rePhoneFirstPass.test(input))) return false
  if (rePhoneDoubleSpace.test(input)) return false

  var digits = input.substring(1).replace(rePhoneGlobalSpace, '').length

  return (digits >= 7 && digits <= 15)
}
exports['utc-millisec'] = /^[0-9]{1,15}\.?[0-9]{0,15}$/
<commit_msg>Fix a ReDoS in 'style' format<commit_after>var createIpValidator = require('is-my-ip-valid')

var reEmailWhitespace = /\s/
var reHostnameFirstPass = /^[a-zA-Z0-9.-]+$/
var reHostnamePart = /^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])$/
var rePhoneFirstPass = /^\+[0-9][0-9 ]{5,27}[0-9]$/
var rePhoneDoubleSpace = / {2}/
var rePhoneGlobalSpace = / /g

exports['date-time'] = /^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}[tT ]\d{2}:\d{2}:\d{2}(?:\.\d+|)([zZ]|[+-]\d{2}:\d{2})$/
exports['date'] = /^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}$/
exports['time'] = /^\d{2}:\d{2}:\d{2}$/
exports['email'] = function (input) { return (input.indexOf('@') !== -1) && (!reEmailWhitespace.test(input)) }
exports['ip-address'] = exports['ipv4'] = createIpValidator({ version: 4 })
exports['ipv6'] = createIpValidator({ version: 6 })
exports['uri'] = /^[a-zA-Z][a-zA-Z0-9+-.]*:[^\s]*$/
exports['color'] = /(#?([0-9A-Fa-f]{3,6})\b)|(aqua)|(black)|(blue)|(fuchsia)|(gray)|(green)|(lime)|(maroon)|(navy)|(olive)|(orange)|(purple)|(red)|(silver)|(teal)|(white)|(yellow)|(rgb\(\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*\))|(rgb\(\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*\))/
exports['hostname'] = function (input) {
  if (!(reHostnameFirstPass.test(input))) return false

  var parts = input.split('.')

  for (var i = 0; i < parts.length; i++) {
    if (!(reHostnamePart.test(parts[i]))) return false
  }

  return true
}
exports['alpha'] = /^[a-zA-Z]+$/
exports['alphanumeric'] = /^[a-zA-Z0-9]+$/
exports['style'] = /.:\s*[^;]/g
exports['phone'] = function (input) {
  if (!(rePhoneFirstPass.test(input))) return false
  if (rePhoneDoubleSpace.test(input)) return false

  var digits = input.substring(1).replace(rePhoneGlobalSpace, '').length

  return (digits >= 7 && digits <= 15)
}
exports['utc-millisec'] = /^[0-9]{1,15}\.?[0-9]{0,15}$/
<|endoftext|>


<commit_before>miro.onReady(() => {
  const icon24 =
    '<g id="Layer_1"><path d="M2.796,2.468 L2.749,22.468" fill-opacity="0" stroke="#000000" stroke-width="2"/><path d="M3.5,21.5 L23.564,21.5" fill-opacity="0" stroke="#000000" stroke-width="2"/><path d="M2.796,14.783 C3.209,13.972 3.594,13.171 4.059,12.371 C4.623,11.401 5.385,10.556 5.953,9.606 C6.402,8.857 7.01,8.19 7.426,7.395 C7.433,7.382 7.577,7.143 7.584,7.143 C7.752,7.143 8.14,9.507 8.163,9.606 C8.417,10.699 9.623,17.334 10.268,17.95 C10.54,18.21 10.69,17.331 10.846,16.995 C11.092,16.467 11.363,15.957 11.636,15.437 C12.745,13.317 13.466,11.153 14.687,9.053 C15.97,6.848 15.997,5.125 18.107,8.148 C18.173,8.244 19.421,9.809 19.475,9.757 C20.284,8.984 20.992,7.211 21.527,6.188" fill-opacity="0" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></g>'

  miro.initialize({
    extensionPoints: {
      bottomBar: {
        title: 'ardoq - miro',
        svgIcon: icon24,
        onClick: () => {
          miro.board.ui.openLeftSidebar('sidebar.html')
        },
      },
    },
  })
})
<commit_msg>Update index.js<commit_after>miro.onReady(() => {
  const icon24 =
    '<g id="Layer_1"><path d="M2.796,2.468 L2.749,22.468" fill-opacity="0" stroke="#000000" stroke-width="2"/><path d="M3.5,21.5 L23.564,21.5" fill-opacity="0" stroke="#000000" stroke-width="2"/><path d="M2.796,14.783 C3.209,13.972 3.594,13.171 4.059,12.371 C4.623,11.401 5.385,10.556 5.953,9.606 C6.402,8.857 7.01,8.19 7.426,7.395 C7.433,7.382 7.577,7.143 7.584,7.143 C7.752,7.143 8.14,9.507 8.163,9.606 C8.417,10.699 9.623,17.334 10.268,17.95 C10.54,18.21 10.69,17.331 10.846,16.995 C11.092,16.467 11.363,15.957 11.636,15.437 C12.745,13.317 13.466,11.153 14.687,9.053 C15.97,6.848 15.997,5.125 18.107,8.148 C18.173,8.244 19.421,9.809 19.475,9.757 C20.284,8.984 20.992,7.211 21.527,6.188" fill-opacity="0" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></g>'

  miro.initialize({
    extensionPoints: {
      bottomBar: {
        title: 'ardoq - miro',
        svgIcon: icon24,
        onClick: () => {
          miro.board.ui.openLeftSidebar('ardoq-miro/sidebar.html')
        },
      },
    },
  })
})
<|endoftext|>


<commit_before>(function () {
  app = angular.module('app',[]);

  app.controller('PLCtrl',function($scope) {
    /* EDIT THE FOLLOWING FOR REAL DATA */

    /* playlists -> get playlists from Parse */
    $scope.playlists = [];

    $scope.onClick = function(playlist) {
      var restaurant = Parse.Object.extend("Restaurant");
      var query = new Parse.Query(restaurant);

      query.equalTo("sporklists", playlist.id);
      query.limit(1000);
      query.withinMiles("location", new Parse.GeoPoint(position.latitude, position.longitude), 50);
      query.find({
        success: function(results) {
          updateSporklist(playlist.get("name"), results);
        },
        error: function(error) {
          alert("Error: " + error.code + " " + error.message);
        }
      });

      $scope.mouseenter = function() {
        console.log("asdf");
        $(this).children('.delete').show();
      }

      $scope.mouseleave = function() {
        $(this).children('.delete').hide();
      }

      $scope.onDeleteClick = function(plist) {
        plist.destroy({
          success: function(myObject) {
            retrieveSporklists(parseUser);
          },
          error: function(myObject, error) {
            // The delete failed.
            // error is a Parse.Error with an error code and message.
          }
        });
      }
    }

    $scope.mouseenter = function() {
      $($(this).children()[0]).css("visibility", "visible");
    }
  });

  app.controller('NewPLCtrl', function($scope) {
    $scope.onClick = function() {
      if (parseUser == null) {
        return;
      }

      $("#new-sporklist").css("visibility", "visible");
      $("#new-sporklist").focus();
      $('#new-sporklist').keyup(function(e){
        if(e.keyCode == 13) {
            var sporklist = Parse.Object.extend("Sporklist");
            var newList = new sporklist();
            newList.set("name", $("#new-sporklist").val());
            newList.set("author", parseUser.getUsername());
            newList.save();

            parseUser.fetch({
              success: function(myObject) {
                var sporklist = Parse.Object.extend("Sporklist");
                var query = new Parse.Query(sporklist);

                query.equalTo("author", parseUser.getUsername());
                query.limit(1000);

                query.find({
                    success: function(results) {
                        updateSporklists(results);
                    },
                    error: function(error) {
                        alert("Error: " + error.code + " " + error.message);
                    }
                });
              },
              error: function(myObject, error) {
                // The object was not refreshed successfully.
                // error is a Parse.Error with an error code and message.
              }
            });

            $(this).css("visibility", "hidden");
            $(this).val("");
        } else if (e.keyCode == 27) {
            $(this).css("visibility", "hidden");
            $(this).val("");
        }
      });
    };
  });

  app.controller('MainCtrl',function($scope) {
    /* The defaults for the home page.
     * The only thing that should show is the sidebar and the fb login.
     */
    $scope.user = false;
    $scope.friend = false;
    $scope.sporklist = false;
    $scope.search = false;
    $scope.map = false;
  });

  app.controller('MeCtrl', function($scope) {
    $scope.name = "";
    $scope.friendList = [];
    $scope.onClick = function(friend) {
      updateFriend(friend);
    };
  });

  app.controller('FriendCtrl', function($scope) {
    $scope.name = "";
    $scope.sporklists = [];

    $scope.onClick = function(sporklist) {
      var restaurant = Parse.Object.extend("Restaurant");
      var query = new Parse.Query(restaurant);

      query.equalTo("sporklists", sporklist.id);
      query.limit(1000);
      query.withinMiles("location", new Parse.GeoPoint(position.latitude, position.longitude), 50);
      query.find({
        success: function(results) {
          updateSporklist(sporklist.get("name"), results);
        },
        error: function(error) {
          alert("Error: " + error.code + " " + error.message);
        }
      });
    }
  })

  app.controller('sporkCtrl', function($scope) {
    $scope.name = "";
    $scope.restaurants = [];

    $scope.follow = function (obj) {
      window.open(obj.get('url'));
    };
  });

  app.controller('SearchCtrl', function($scope) {
    $scope.results = [];
  });

}());

function retrieveSporklists(user) {
    var sporklist = Parse.Object.extend("Sporklist");
    var query = new Parse.Query(sporklist);

    query.equalTo("author", user.getUsername());
    query.limit(1000);

    query.find({
        success: function(results) {
            updateSporklists(results);
        },
        error: function(error) {
            alert("Error: " + error.code + " " + error.message);
        }
    });
}
<commit_msg>adsfawef<commit_after>(function () {
  app = angular.module('app',[]);

  app.controller('PLCtrl',function($scope) {
    /* EDIT THE FOLLOWING FOR REAL DATA */

    /* playlists -> get playlists from Parse */
    $scope.playlists = [];

    $scope.onClick = function(playlist) {
      var restaurant = Parse.Object.extend("Restaurant");
      var query = new Parse.Query(restaurant);

      query.equalTo("sporklists", playlist.id);
      query.limit(1000);
      query.withinMiles("location", new Parse.GeoPoint(position.latitude, position.longitude), 50);
      query.find({
        success: function(results) {
          updateSporklist(playlist.get("name"), results);
        },
        error: function(error) {
          alert("Error: " + error.code + " " + error.message);
        }
      });

      $scope.mouseenter = function() {
        console.log("asdf");
        $(this).children('.delete').show();
      }

      $scope.mouseleave = function() {
        $(this).children('.delete').hide();
      }

      $scope.onDeleteClick = function(plist) {
        plist.destroy({
          success: function(myObject) {
            retrieveSporklists(parseUser);
          },
          error: function(myObject, error) {
            console.log(error);
          }
        });
      }
    }

    $scope.mouseenter = function() {
      $($(this).children()[0]).css("visibility", "visible");
    }
  });

  app.controller('NewPLCtrl', function($scope) {
    $scope.onClick = function() {
      if (parseUser == null) {
        return;
      }

      $("#new-sporklist").css("visibility", "visible");
      $("#new-sporklist").focus();
      $('#new-sporklist').keyup(function(e){
        if(e.keyCode == 13) {
            var sporklist = Parse.Object.extend("Sporklist");
            var newList = new sporklist();
            newList.set("name", $("#new-sporklist").val());
            newList.set("author", parseUser.getUsername());
            newList.save();

            parseUser.fetch({
              success: function(myObject) {
                var sporklist = Parse.Object.extend("Sporklist");
                var query = new Parse.Query(sporklist);

                query.equalTo("author", parseUser.getUsername());
                query.limit(1000);

                query.find({
                    success: function(results) {
                        updateSporklists(results);
                    },
                    error: function(error) {
                        alert("Error: " + error.code + " " + error.message);
                    }
                });
              },
              error: function(myObject, error) {
                // The object was not refreshed successfully.
                // error is a Parse.Error with an error code and message.
              }
            });

            $(this).css("visibility", "hidden");
            $(this).val("");
        } else if (e.keyCode == 27) {
            $(this).css("visibility", "hidden");
            $(this).val("");
        }
      });
    };
  });

  app.controller('MainCtrl',function($scope) {
    /* The defaults for the home page.
     * The only thing that should show is the sidebar and the fb login.
     */
    $scope.user = false;
    $scope.friend = false;
    $scope.sporklist = false;
    $scope.search = false;
    $scope.map = false;
  });

  app.controller('MeCtrl', function($scope) {
    $scope.name = "";
    $scope.friendList = [];
    $scope.onClick = function(friend) {
      updateFriend(friend);
    };
  });

  app.controller('FriendCtrl', function($scope) {
    $scope.name = "";
    $scope.sporklists = [];

    $scope.onClick = function(sporklist) {
      var restaurant = Parse.Object.extend("Restaurant");
      var query = new Parse.Query(restaurant);

      query.equalTo("sporklists", sporklist.id);
      query.limit(1000);
      query.withinMiles("location", new Parse.GeoPoint(position.latitude, position.longitude), 50);
      query.find({
        success: function(results) {
          updateSporklist(sporklist.get("name"), results);
        },
        error: function(error) {
          alert("Error: " + error.code + " " + error.message);
        }
      });
    }
  })

  app.controller('sporkCtrl', function($scope) {
    $scope.name = "";
    $scope.restaurants = [];

    $scope.follow = function (obj) {
      window.open(obj.get('url'));
    };
  });

  app.controller('SearchCtrl', function($scope) {
    $scope.results = [];
  });

}());

function retrieveSporklists(user) {
    var sporklist = Parse.Object.extend("Sporklist");
    var query = new Parse.Query(sporklist);

    query.equalTo("author", user.getUsername());
    query.limit(1000);

    query.find({
        success: function(results) {
            updateSporklists(results);
        },
        error: function(error) {
            alert("Error: " + error.code + " " + error.message);
        }
    });
}
<|endoftext|>


<commit_before>'use strict';

angular.module('angularApp')
    .service('Auth', function Auth($http, Uris, $q) {
        // AngularJS will instantiate a singleton by calling "new" on this function
        var that = this;
        this.status = function () {
            return $http.get(Uris.JSON_ROOT + 'login/status').then(function (status) {
                angular.extend(that, status.data);

                if (status.data.auth) {
                    console.log('Auth is', that.user, status.data.user);
                    return true;
                } else {
                    console.log('rejecting!');
                    return $q.reject();
                }
            });
        };

        this.isUQSLQ = function () {
            return this.user && ((that.user.indexOf('uq') !== -1 || that.user.indexOf('slq') !== -1) || that.role === 'root');
        };

        /**
         * Checks if the current user can delete something
         *
         * @param  {[type]} uri [description]
         * @return {[type]}     [description]
         */
        this.canDelete = function (uri) {
            return this.role === 'root' || (this.user && uri.indexOf(this.user) !== -1);
        };

        this.isEditor = function () {
            return this.role === 'editor' || this.role === 'root';
        };

        this.clear = function() {
          // from http://stackoverflow.com/a/19316998
          for(var k in this) if(!this[k].constructor.toString().match(/^function Function\(/)) delete this[k];
        };

    });<commit_msg>minor, added comment<commit_after>'use strict';

angular.module('angularApp')
    .service('Auth', function Auth($http, Uris, $q) {
        // AngularJS will instantiate a singleton by calling "new" on this function
        var that = this;
        this.status = function () {
            return $http.get(Uris.JSON_ROOT + 'login/status').then(function (status) {
                angular.extend(that, status.data);

                if (status.data.auth) {
                    console.log('Auth is', that.user, status.data.user);
                    return true;
                } else {
                    console.log('rejecting!');
                    return $q.reject();
                }
            });
        };

        this.isUQSLQ = function () {
            return this.user && ((that.user.indexOf('uq') !== -1 || that.user.indexOf('slq') !== -1) || that.role === 'root');
        };

        /**
         * Checks if the current user can delete something
         *
         * @param  {[type]} uri [description]
         * @return {[type]}     [description]
         */
        this.canDelete = function (uri) {
            return this.role === 'root' || (this.user && uri.indexOf(this.user) !== -1);
        };

        this.isEditor = function () {
            return this.role === 'editor' || this.role === 'root';
        };

        this.clear = function() {
          // remove all properties from this singleton. from http://stackoverflow.com/a/19316998
          for(var k in this) if(!this[k].constructor.toString().match(/^function Function\(/)) delete this[k];
        };

    });<|endoftext|>