<commit_before>/**
 * Copyright 2018-present Facebook.
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 * @format
 */

import type {Filter} from 'flipper';
import type {TableColumns} from '../table/types';
import {PureComponent} from 'react';
import Toolbar from '../Toolbar.js';
import FlexRow from '../FlexRow.js';
import Input from '../Input.js';
import {colors} from '../colors.js';
import Text from '../Text.js';
import FlexBox from '../FlexBox.js';
import Glyph from '../Glyph.js';
import FilterToken from './FilterToken.js';
import styled from '../../styled/index.js';

const SearchBar = styled(Toolbar)({
  height: 42,
  padding: 6,
});

export const SearchBox = styled(FlexBox)({
  backgroundColor: colors.white,
  borderRadius: '999em',
  border: `1px solid ${colors.light15}`,
  height: '100%',
  width: '100%',
  alignItems: 'center',
  paddingLeft: 4,
});

export const SearchInput = styled(Input)(props => ({
  border: props.focus ? '1px solid black' : 0,
  padding: 0,
  fontSize: '1em',
  flexGrow: 1,
  height: 'auto',
  lineHeight: '100%',
  marginLeft: 2,
  width: '100%',
  '&::-webkit-input-placeholder': {
    color: colors.placeholder,
    fontWeight: 300,
  },
}));

const Clear = styled(Text)({
  position: 'absolute',
  right: 6,
  top: '50%',
  marginTop: -9,
  fontSize: 16,
  width: 17,
  height: 17,
  borderRadius: 999,
  lineHeight: '15.5px',
  textAlign: 'center',
  backgroundColor: 'rgba(0,0,0,0.1)',
  color: colors.white,
  display: 'block',
  '&:hover': {
    backgroundColor: 'rgba(0,0,0,0.15)',
  },
});

export const SearchIcon = styled(Glyph)({
  marginRight: 3,
  marginLeft: 3,
  marginTop: -1,
  minWidth: 16,
});

const Actions = styled(FlexRow)({
  marginLeft: 8,
  flexShrink: 0,
});

export type SearchableProps = {|
  addFilter: (filter: Filter) => void,
  searchTerm: string,
  filters: Array<Filter>,
|};

type Props = {|
  placeholder?: string,
  actions: React.Node,
  tableKey: string,
  columns?: TableColumns,
  onFilterChange: (filters: Array<Filter>) => void,
  defaultFilters: Array<Filter>,
|};

type State = {
  filters: Array<Filter>,
  focusedToken: number,
  searchTerm: string,
  hasFocus: boolean,
};

const Searchable = (
  Component: React.ComponentType<any>,
): React.ComponentType<any> =>
  class extends PureComponent<Props, State> {
    static defaultProps = {
      placeholder: 'Search...',
    };

    state: State = {
      filters: this.props.defaultFilters || [],
      focusedToken: -1,
      searchTerm: '',
      hasFocus: false,
    };

    _inputRef: ?HTMLInputElement;

    componentDidMount() {
      window.document.addEventListener('keydown', this.onKeyDown);
      const {defaultFilters} = this.props;
      let savedState;

      if (this.getTableKey()) {
        try {
          savedState = JSON.parse(
            window.localStorage.getItem(this.getPersistKey()) || 'null',
          );
        } catch (e) {
          window.localStorage.removeItem(this.getPersistKey());
        }
      }

      if (savedState) {
        if (defaultFilters != null) {
          // merge default filter with persisted filters
          const savedStateFilters = savedState.filters;
          defaultFilters.forEach(defaultFilter => {
            const filterIndex = savedStateFilters.findIndex(
              f => f.key === defaultFilter.key,
            );
            if (filterIndex > -1) {
              if (defaultFilter.type === 'enum') {
                savedStateFilters[filterIndex].enum = defaultFilter.enum;
              }
              const filters = new Set(
                savedStateFilters[filterIndex].enum.map(filter => filter.value),
              );
              savedStateFilters[filterIndex].value = savedStateFilters[
                filterIndex
              ].value.filter(value => filters.has(value));
            }
          });
        }
        this.setState({
          searchTerm: savedState.searchTerm || this.state.searchTerm,
          filters: savedState.filters || this.state.filters,
        });
      }
    }

    componentDidUpdate(prevProps: Props, prevState: State) {
      if (
        this.getTableKey() &&
        (prevState.searchTerm !== this.state.searchTerm ||
          prevState.filters !== this.state.filters)
      ) {
        window.localStorage.setItem(
          this.getPersistKey(),
          JSON.stringify({
            searchTerm: this.state.searchTerm,
            filters: this.state.filters,
          }),
        );
        if (this.props.onFilterChange != null) {
          this.props.onFilterChange(this.state.filters);
        }
      } else if (prevProps.defaultFilters !== this.props.defaultFilters) {
        const mergedFilters = [...this.state.filters];
        this.props.defaultFilters.forEach((defaultFilter: Filter) => {
          const filterIndex = mergedFilters.findIndex(
            (f: Filter) => f.key === defaultFilter.key,
          );
          if (filterIndex > -1) {
            mergedFilters[filterIndex] = defaultFilter;
          } else {
            mergedFilters.push(defaultFilter);
          }
        });
        this.setState({
          filters: mergedFilters,
        });
      }
    }

    componentWillUnmount() {
      window.document.removeEventListener('keydown', this.onKeyDown);
    }

    getTableKey = (): ?string => {
      if (this.props.tableKey) {
        return this.props.tableKey;
      } else if (this.props.columns) {
        // if we have a table, we are using it's colums to uniquely identify
        // the table (in case there is more than one table rendered at a time)
        return (
          'TABLE_COLUMNS_' +
          Object.keys(this.props.columns)
            .join('_')
            .toUpperCase()
        );
      }
    };

    onKeyDown = (e: SyntheticKeyboardEvent<>) => {
      const ctrlOrCmd = e =>
        (e.metaKey && process.platform === 'darwin') ||
        (e.ctrlKey && process.platform !== 'darwin');

      if (e.key === 'f' && ctrlOrCmd(e) && this._inputRef) {
        e.preventDefault();
        if (this._inputRef) {
          this._inputRef.focus();
        }
      } else if (e.key === 'Escape' && this._inputRef) {
        this._inputRef.blur();
        this.setState({searchTerm: ''});
      } else if (e.key === 'Backspace' && this.hasFocus()) {
        if (
          this.state.focusedToken === -1 &&
          this.state.searchTerm === '' &&
          this._inputRef &&
          !this.state.filters[this.state.filters.length - 1].persistent
        ) {
          this._inputRef.blur();
          this.setState({focusedToken: this.state.filters.length - 1});
        } else {
          this.removeFilter(this.state.focusedToken);
        }
      } else if (
        e.key === 'Delete' &&
        this.hasFocus() &&
        this.state.focusedToken > -1
      ) {
        this.removeFilter(this.state.focusedToken);
      } else if (e.key === 'Enter' && this.hasFocus() && this._inputRef) {
        this.matchTags(this._inputRef.value, true);
      }
    };

    onChangeSearchTerm = (e: SyntheticInputEvent<HTMLInputElement>) =>
      this.matchTags(e.target.value, false);

    matchTags = (searchTerm: string, matchEnd: boolean) => {
      const filterPattern = matchEnd
        ? /([a-z][a-z0-9]*[!]?[:=][^\s]+)($|\s)/gi
        : /([a-z][a-z0-9]*[!]?[:=][^\s]+)\s/gi;
      const match = searchTerm.match(filterPattern);
      if (match && match.length > 0) {
        match.forEach((filter: string) => {
          const separator =
            filter.indexOf(':') > filter.indexOf('=') ? ':' : '=';
          let [key, ...value] = filter.split(separator);
          value = value.join(separator).trim();
          let type = 'include';
          // if value starts with !, it's an exclude filter
          if (value.indexOf('!') === 0) {
            type = 'exclude';
            value = value.substring(1);
          }
          // if key ends with !, it's an exclude filter
          if (key.indexOf('!') === key.length - 1) {
            type = 'exclude';
            key = key.slice(0, -1);
          }
          this.addFilter({
            type,
            key,
            value,
          });
        });

        searchTerm = searchTerm.replace(filterPattern, '');
      }
      this.setState({searchTerm});
    };

    setInputRef = (ref: ?HTMLInputElement) => {
      this._inputRef = ref;
    };

    addFilter = (filter: Filter) => {
      const filterIndex = this.state.filters.findIndex(
        f => f.key === filter.key,
      );
      if (filterIndex > -1) {
        const filters = [...this.state.filters];
        const defaultFilter: Filter = this.props.defaultFilters[filterIndex];
        if (
          defaultFilter != null &&
          defaultFilter.type === 'enum' &&
          filters[filterIndex].type === 'enum'
        ) {
          filters[filterIndex].enum = defaultFilter.enum;
        }
        this.setState({filters});
        // filter for this key already exists
        return;
      }
      // persistent filters are always at the front
      const filters =
        filter.persistent === true
          ? [filter, ...this.state.filters]
          : this.state.filters.concat(filter);
      this.setState({
        filters,
        focusedToken: -1,
      });
    };

    removeFilter = (index: number) => {
      const filters = this.state.filters.filter((_, i) => i !== index);
      const focusedToken = -1;
      this.setState({filters, focusedToken}, () => {
        if (this._inputRef) {
          this._inputRef.focus();
        }
      });
    };

    replaceFilter = (index: number, filter: Filter) => {
      const filters = [...this.state.filters];
      filters.splice(index, 1, filter);
      this.setState({filters});
    };

    onInputFocus = () =>
      this.setState({
        focusedToken: -1,
        hasFocus: true,
      });

    onInputBlur = () =>
      setTimeout(
        () =>
          this.setState({
            hasFocus: false,
          }),
        100,
      );

    onTokenFocus = (focusedToken: number) => this.setState({focusedToken});

    onTokenBlur = () => this.setState({focusedToken: -1});

    hasFocus = (): boolean => {
      return this.state.focusedToken !== -1 || this.state.hasFocus;
    };

    clear = () =>
      this.setState({
        filters: this.state.filters.filter(
          f => f.persistent != null && f.persistent === true,
        ),
        searchTerm: '',
      });

    getPersistKey = () => `SEARCHABLE_STORAGE_KEY_${this.getTableKey() || ''}`;

    render(): React.Node {
      const {placeholder, actions, ...props} = this.props;
      return [
        <SearchBar position="top" key="searchbar">
          <SearchBox tabIndex={-1}>
            <SearchIcon
              name="magnifying-glass"
              color={colors.macOSTitleBarIcon}
              size={16}
            />
            {this.state.filters.map((filter, i) => (
              <FilterToken
                key={`${filter.key}:${filter.type}`}
                index={i}
                filter={filter}
                focused={i === this.state.focusedToken}
                onFocus={this.onTokenFocus}
                onDelete={this.removeFilter}
                onReplace={this.replaceFilter}
                onBlur={this.onTokenBlur}
              />
            ))}
            <SearchInput
              placeholder={placeholder}
              onChange={this.onChangeSearchTerm}
              value={this.state.searchTerm}
              innerRef={this.setInputRef}
              onFocus={this.onInputFocus}
              onBlur={this.onInputBlur}
            />
            {(this.state.searchTerm || this.state.filters.length > 0) && (
              <Clear onClick={this.clear}>×</Clear>
            )}
          </SearchBox>
          {actions != null && <Actions>{actions}</Actions>}
        </SearchBar>,
        <Component
          {...props}
          key="table"
          addFilter={this.addFilter}
          searchTerm={this.state.searchTerm}
          filters={this.state.filters}
        />,
      ];
    }
  };

/**
 * Higher-order-component that allows adding a searchbar on top of the wrapped
 * component. See SearchableManagedTable for usage with a table.
 */
export default Searchable;
<commit_msg>debounce search<commit_after>/**
 * Copyright 2018-present Facebook.
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 * @format
 */

import type {Filter} from 'flipper';
import type {TableColumns} from '../table/types';
import {PureComponent} from 'react';
import Toolbar from '../Toolbar.js';
import FlexRow from '../FlexRow.js';
import Input from '../Input.js';
import {colors} from '../colors.js';
import Text from '../Text.js';
import FlexBox from '../FlexBox.js';
import Glyph from '../Glyph.js';
import FilterToken from './FilterToken.js';
import styled from '../../styled/index.js';
import debounce from 'lodash.debounce';

const SearchBar = styled(Toolbar)({
  height: 42,
  padding: 6,
});

export const SearchBox = styled(FlexBox)({
  backgroundColor: colors.white,
  borderRadius: '999em',
  border: `1px solid ${colors.light15}`,
  height: '100%',
  width: '100%',
  alignItems: 'center',
  paddingLeft: 4,
});

export const SearchInput = styled(Input)(props => ({
  border: props.focus ? '1px solid black' : 0,
  padding: 0,
  fontSize: '1em',
  flexGrow: 1,
  height: 'auto',
  lineHeight: '100%',
  marginLeft: 2,
  width: '100%',
  '&::-webkit-input-placeholder': {
    color: colors.placeholder,
    fontWeight: 300,
  },
}));

const Clear = styled(Text)({
  position: 'absolute',
  right: 6,
  top: '50%',
  marginTop: -9,
  fontSize: 16,
  width: 17,
  height: 17,
  borderRadius: 999,
  lineHeight: '15.5px',
  textAlign: 'center',
  backgroundColor: 'rgba(0,0,0,0.1)',
  color: colors.white,
  display: 'block',
  '&:hover': {
    backgroundColor: 'rgba(0,0,0,0.15)',
  },
});

export const SearchIcon = styled(Glyph)({
  marginRight: 3,
  marginLeft: 3,
  marginTop: -1,
  minWidth: 16,
});

const Actions = styled(FlexRow)({
  marginLeft: 8,
  flexShrink: 0,
});

export type SearchableProps = {|
  addFilter: (filter: Filter) => void,
  searchTerm: string,
  filters: Array<Filter>,
|};

type Props = {|
  placeholder?: string,
  actions: React.Node,
  tableKey: string,
  columns?: TableColumns,
  onFilterChange: (filters: Array<Filter>) => void,
  defaultFilters: Array<Filter>,
|};

type State = {
  filters: Array<Filter>,
  focusedToken: number,
  searchTerm: string,
  hasFocus: boolean,
};

const Searchable = (
  Component: React.ComponentType<any>,
): React.ComponentType<any> =>
  class extends PureComponent<Props, State> {
    static defaultProps = {
      placeholder: 'Search...',
    };

    state: State = {
      filters: this.props.defaultFilters || [],
      focusedToken: -1,
      searchTerm: '',
      hasFocus: false,
    };

    _inputRef: ?HTMLInputElement;

    componentDidMount() {
      window.document.addEventListener('keydown', this.onKeyDown);
      const {defaultFilters} = this.props;
      let savedState;

      if (this.getTableKey()) {
        try {
          savedState = JSON.parse(
            window.localStorage.getItem(this.getPersistKey()) || 'null',
          );
        } catch (e) {
          window.localStorage.removeItem(this.getPersistKey());
        }
      }

      if (savedState) {
        if (defaultFilters != null) {
          // merge default filter with persisted filters
          const savedStateFilters = savedState.filters;
          defaultFilters.forEach(defaultFilter => {
            const filterIndex = savedStateFilters.findIndex(
              f => f.key === defaultFilter.key,
            );
            if (filterIndex > -1) {
              if (defaultFilter.type === 'enum') {
                savedStateFilters[filterIndex].enum = defaultFilter.enum;
              }
              const filters = new Set(
                savedStateFilters[filterIndex].enum.map(filter => filter.value),
              );
              savedStateFilters[filterIndex].value = savedStateFilters[
                filterIndex
              ].value.filter(value => filters.has(value));
            }
          });
        }
        this.setState({
          searchTerm: savedState.searchTerm || this.state.searchTerm,
          filters: savedState.filters || this.state.filters,
        });
      }
    }

    componentDidUpdate(prevProps: Props, prevState: State) {
      if (
        this.getTableKey() &&
        (prevState.searchTerm !== this.state.searchTerm ||
          prevState.filters !== this.state.filters)
      ) {
        window.localStorage.setItem(
          this.getPersistKey(),
          JSON.stringify({
            searchTerm: this.state.searchTerm,
            filters: this.state.filters,
          }),
        );
        if (this.props.onFilterChange != null) {
          this.props.onFilterChange(this.state.filters);
        }
      } else if (prevProps.defaultFilters !== this.props.defaultFilters) {
        const mergedFilters = [...this.state.filters];
        this.props.defaultFilters.forEach((defaultFilter: Filter) => {
          const filterIndex = mergedFilters.findIndex(
            (f: Filter) => f.key === defaultFilter.key,
          );
          if (filterIndex > -1) {
            mergedFilters[filterIndex] = defaultFilter;
          } else {
            mergedFilters.push(defaultFilter);
          }
        });
        this.setState({
          filters: mergedFilters,
        });
      }
    }

    componentWillUnmount() {
      window.document.removeEventListener('keydown', this.onKeyDown);
    }

    getTableKey = (): ?string => {
      if (this.props.tableKey) {
        return this.props.tableKey;
      } else if (this.props.columns) {
        // if we have a table, we are using it's colums to uniquely identify
        // the table (in case there is more than one table rendered at a time)
        return (
          'TABLE_COLUMNS_' +
          Object.keys(this.props.columns)
            .join('_')
            .toUpperCase()
        );
      }
    };

    onKeyDown = (e: SyntheticKeyboardEvent<>) => {
      const ctrlOrCmd = e =>
        (e.metaKey && process.platform === 'darwin') ||
        (e.ctrlKey && process.platform !== 'darwin');

      if (e.key === 'f' && ctrlOrCmd(e) && this._inputRef) {
        e.preventDefault();
        if (this._inputRef) {
          this._inputRef.focus();
        }
      } else if (e.key === 'Escape' && this._inputRef) {
        this._inputRef.blur();
        this.setState({searchTerm: ''});
      } else if (e.key === 'Backspace' && this.hasFocus()) {
        if (
          this.state.focusedToken === -1 &&
          this.state.searchTerm === '' &&
          this._inputRef &&
          !this.state.filters[this.state.filters.length - 1].persistent
        ) {
          this._inputRef.blur();
          this.setState({focusedToken: this.state.filters.length - 1});
        } else {
          this.removeFilter(this.state.focusedToken);
        }
      } else if (
        e.key === 'Delete' &&
        this.hasFocus() &&
        this.state.focusedToken > -1
      ) {
        this.removeFilter(this.state.focusedToken);
      } else if (e.key === 'Enter' && this.hasFocus() && this._inputRef) {
        this.matchTags(this._inputRef.value, true);
      }
    };

    onChangeSearchTerm = (e: SyntheticInputEvent<HTMLInputElement>) => {
      this.setState({searchTerm: e.target.value});
      this.matchTags(e.target.value, false);
    };

    matchTags = debounce((searchTerm: string, matchEnd: boolean) => {
      const filterPattern = matchEnd
        ? /([a-z][a-z0-9]*[!]?[:=][^\s]+)($|\s)/gi
        : /([a-z][a-z0-9]*[!]?[:=][^\s]+)\s/gi;
      const match = searchTerm.match(filterPattern);
      if (match && match.length > 0) {
        match.forEach((filter: string) => {
          const separator =
            filter.indexOf(':') > filter.indexOf('=') ? ':' : '=';
          let [key, ...value] = filter.split(separator);
          value = value.join(separator).trim();
          let type = 'include';
          // if value starts with !, it's an exclude filter
          if (value.indexOf('!') === 0) {
            type = 'exclude';
            value = value.substring(1);
          }
          // if key ends with !, it's an exclude filter
          if (key.indexOf('!') === key.length - 1) {
            type = 'exclude';
            key = key.slice(0, -1);
          }
          this.addFilter({
            type,
            key,
            value,
          });
        });

        searchTerm = searchTerm.replace(filterPattern, '');
      }
    }, 200);

    setInputRef = (ref: ?HTMLInputElement) => {
      this._inputRef = ref;
    };

    addFilter = (filter: Filter) => {
      const filterIndex = this.state.filters.findIndex(
        f => f.key === filter.key,
      );
      if (filterIndex > -1) {
        const filters = [...this.state.filters];
        const defaultFilter: Filter = this.props.defaultFilters[filterIndex];
        if (
          defaultFilter != null &&
          defaultFilter.type === 'enum' &&
          filters[filterIndex].type === 'enum'
        ) {
          filters[filterIndex].enum = defaultFilter.enum;
        }
        this.setState({filters});
        // filter for this key already exists
        return;
      }
      // persistent filters are always at the front
      const filters =
        filter.persistent === true
          ? [filter, ...this.state.filters]
          : this.state.filters.concat(filter);
      this.setState({
        filters,
        focusedToken: -1,
      });
    };

    removeFilter = (index: number) => {
      const filters = this.state.filters.filter((_, i) => i !== index);
      const focusedToken = -1;
      this.setState({filters, focusedToken}, () => {
        if (this._inputRef) {
          this._inputRef.focus();
        }
      });
    };

    replaceFilter = (index: number, filter: Filter) => {
      const filters = [...this.state.filters];
      filters.splice(index, 1, filter);
      this.setState({filters});
    };

    onInputFocus = () =>
      this.setState({
        focusedToken: -1,
        hasFocus: true,
      });

    onInputBlur = () =>
      setTimeout(
        () =>
          this.setState({
            hasFocus: false,
          }),
        100,
      );

    onTokenFocus = (focusedToken: number) => this.setState({focusedToken});

    onTokenBlur = () => this.setState({focusedToken: -1});

    hasFocus = (): boolean => {
      return this.state.focusedToken !== -1 || this.state.hasFocus;
    };

    clear = () =>
      this.setState({
        filters: this.state.filters.filter(
          f => f.persistent != null && f.persistent === true,
        ),
        searchTerm: '',
      });

    getPersistKey = () => `SEARCHABLE_STORAGE_KEY_${this.getTableKey() || ''}`;

    render(): React.Node {
      const {placeholder, actions, ...props} = this.props;
      return [
        <SearchBar position="top" key="searchbar">
          <SearchBox tabIndex={-1}>
            <SearchIcon
              name="magnifying-glass"
              color={colors.macOSTitleBarIcon}
              size={16}
            />
            {this.state.filters.map((filter, i) => (
              <FilterToken
                key={`${filter.key}:${filter.type}`}
                index={i}
                filter={filter}
                focused={i === this.state.focusedToken}
                onFocus={this.onTokenFocus}
                onDelete={this.removeFilter}
                onReplace={this.replaceFilter}
                onBlur={this.onTokenBlur}
              />
            ))}
            <SearchInput
              placeholder={placeholder}
              onChange={this.onChangeSearchTerm}
              value={this.state.searchTerm}
              innerRef={this.setInputRef}
              onFocus={this.onInputFocus}
              onBlur={this.onInputBlur}
            />
            {(this.state.searchTerm || this.state.filters.length > 0) && (
              <Clear onClick={this.clear}>×</Clear>
            )}
          </SearchBox>
          {actions != null && <Actions>{actions}</Actions>}
        </SearchBar>,
        <Component
          {...props}
          key="table"
          addFilter={this.addFilter}
          searchTerm={this.state.searchTerm}
          filters={this.state.filters}
        />,
      ];
    }
  };

/**
 * Higher-order-component that allows adding a searchbar on top of the wrapped
 * component. See SearchableManagedTable for usage with a table.
 */
export default Searchable;
<|endoftext|>


<commit_before>var tape = require('tape')
  , serializeSelection = require('..')

var html = '
hello, world!
'

// PhantomJS doesn't support bind yet
Function.prototype.bind = Function.prototype.bind || function (thisp) {
    var fn = this;
    return function () {
        return fn.apply(thisp, arguments);
    };
};

function create(tag) {
  return document.createElement(tag)
}

function remove(el) {
  el.parentNode.removeChild(el)
}

function insert(el, container) {
  container = container || document.documentElement
  container.appendChild(el)
}

function setup(fn) {
  var el = create('div')
  el.innerHTML = html
  insert(el)

  function teardown() {
    remove(el)
  }

  return function (t) {
    fn(t, el)
    teardown()
  }
}

function test(msg, fn) {
  tape(msg, setup(fn))
}

test('should save a selection correctly', function (t, el) {
  var sel = window.getSelection()
    , range = document.createRange()
    , node = el.querySelector('p').firstChild
    , state

  range.setStart(node, 1)
  range.setEnd(node, 4)
  sel.addRange(range)

  state = serializeSelection.save(el)

  t.equal(state.start, 1)
  t.equal(state.end, 4)
  t.equal(state.content, 'ell')
  t.end()
})

test('should restore a selection correctly', function (t, el) {
  var sel
    , range
    , node = el.querySelector('p').firstChild
    , state = { start: 1, end: 4 }

  sel = serializeSelection.restore(state, el)
  range = sel.getRangeAt(0)

  t.equal(range.startContainer, el.querySelector('p').firstChild)
  t.equal(range.endContainer, el.querySelector('p').firstChild)
  t.equal(range.startOffset, 1)
  t.equal(range.endOffset, 4)
  t.equal(range.toString(), 'ell')
  t.end()
})
<commit_msg>Add test for ignoring text before reference el<commit_after>var tape = require('tape')
  , serializeSelection = require('..')

var html = '
hello, world!
'

// PhantomJS doesn't support bind yet
Function.prototype.bind = Function.prototype.bind || function (thisp) {
    var fn = this;
    return function () {
        return fn.apply(thisp, arguments);
    };
};

function create(tag) {
  return document.createElement(tag)
}

function remove(el) {
  el.parentNode.removeChild(el)
}

function insert(el, container) {
  container = container || document.documentElement
  container.appendChild(el)
}

function setup(fn) {
  var el = create('div')
  el.innerHTML = html
  insert(el)

  function teardown() {
    remove(el)
  }

  return function (t) {
    fn(t, el)
    teardown()
  }
}

function test(msg, fn) {
  tape(msg, setup(fn))
}

test('should save a selection correctly', function (t, el) {
  var sel = window.getSelection()
    , range = document.createRange()
    , node = el.querySelector('p').firstChild
    , state

  range.setStart(node, 1)
  range.setEnd(node, 4)
  sel.addRange(range)

  state = serializeSelection.save(el)

  t.equal(state.start, 1)
  t.equal(state.end, 4)
  t.equal(state.content, 'ell')
  t.end()
})

test('should restore a selection correctly', function (t, el) {
  var sel
    , range
    , node = el.querySelector('p').firstChild
    , state = { start: 1, end: 4 }

  sel = serializeSelection.restore(state, el)
  range = sel.getRangeAt(0)

  t.equal(range.startContainer, el.querySelector('p').firstChild)
  t.equal(range.endContainer, el.querySelector('p').firstChild)
  t.equal(range.startOffset, 1)
  t.equal(range.endOffset, 4)
  t.equal(range.toString(), 'ell')
  t.end()
})

test('should ignore text outside reference element', function (t, el) {
  var sel = window.getSelection()
    , range = document.createRange()
    , node
    , state

  el.innerHTML = '
stuff before reference el
' + el.innerHTML

  node = el.querySelector('p').firstChild
  range.setStart(node, 1)
  range.setEnd(node, 4)
  sel.addRange(range)

  state = serializeSelection.save(node)

  t.equal(state.start, 1)
  t.equal(state.end, 4)
  t.equal(state.content, 'ell')
  t.end()
})
<|endoftext|>


<commit_before>'use strict';

angular.module('core').controller('GridController', ['$scope','$http', 'Authentication',
	function($scope, $http, Authentication) {

    // Authenticated User
    var user = Authentication.user;

    // I need to move this to the User service
    var loadPics = function(user_id, instagram_id){
      $http({
        method: "GET",
        url: "/users/load_media",
        params: {"user_id": user_id, "instagram_id": instagram_id}
      }).then(function(res){
        console.log(res)
      });
    }

    // Function available on Scope to sync with Instagram
    $scope.getPicsYo = function (){
      var instagram_id = user.providerData.data.id;
      loadPics(user._id, instagram_id);
    };
	}
]);
<commit_msg>some late sugar<commit_after>'use strict';

angular.module('core').controller('GridController', ['$scope','$http', 'Authentication',
	function($scope, $http, Authentication) {

    // Authenticated User
    var user = Authentication.user;

    // I need to move this to the User service
    var loadPics = function(user_id, instagram_id){
      $http({
        method: "GET",
        url: "/users/load_media",
        params: {"user_id": user_id, "instagram_id": instagram_id}
      }).then(function(res){
        console.log(res)
      });
    }

    // Function available on Scope to sync with Instagram
    $scope.getPicsYo = function (){
      var instagram_id = user.providerData.data.id;
      loadPics(user._id, instagram_id);
    };

	}
]);
<|endoftext|>


<commit_before>/*!
Deck JS - deck.svg
Copyright (c) 2012 Rémi Emonet, as a major refactor from an early version from Rémi Barraquand.
*/

/*
This module provides a support for managed svg inclusion (allowing proper DOM access subsequently for animations, etc.).
*/

(function($, deck, undefined) {
    var $d = $(document);
    var may = function(f) {return f ? f : function() {}};

    $.extend(true, $[deck].defaults, {
        classes: {
            svgPlaceholder: 'deck-svg'
        },
	selectors: {
            svgObject: "object[type='deckjs/svg'], div.svg-object"
        },
        alert: {
            missingSVG: true
        }
    });

    function walk(node, fn) {
        if (node) do {
            if (node.nodeType === 1) {
                fn.call(node);
                walk(node.firstChild, fn);
            }
        } while (node = node.nextSibling);
    }
    var svgPatcher = {
        styleToAttributes: function(root, svgfile) {
            walk(root, function() {
                var $n = $(this);
                if ($n.attr("style")) {
                    $($n.attr("style").trim().split(/ *; */)).each(function(index, style) {
                        if (style && style.substring(0,1) != "-") {
                            var s = style.trim().split(/ *: */);
                            $n.attr(s[0], s[1]);
                        }
                    });
                }
                $n.attr("style", null);
            })
        },
        referencingAttributes: ["clip-path", "color-profile", "fill", "filter", "marker-start", "marker-mid", "marker-end", "mask", "stroke"],
        nextId: 1,
        generateId: function(oldId) {
            var id = "uniquesvg"+svgPatcher.nextId;
            svgPatcher.nextId++;
            return id;
        },
        makeReferencedIdsUnique: function(root, svgfile, continuation) {
            var andThen = continuation || function(){}
            var byId = {};
            var referencersIds = {};
            var pushAdd = function(k, o) {
                if (referencersIds[k]) {
                    referencersIds[k].push(o);
                } else {
                    referencersIds[k] = [ o ];
                }
            };
            // gather all ids and references
            walk(root, function() {
                var that = this;
                var $n = $(this);
                var id = that.id;
                if (id) {
                    byId[id] = this;
                }
                $(svgPatcher.referencingAttributes).each(function(i,attr) {
                    var val = $n.attr(attr);
                    if (val) {
                        var groups = val.trim().match(/^url\(#(.+?)\)$/)
                        if (groups) pushAdd(groups[1], {o:that, a:attr})
                    }
                });
                var xlink = $n.attr("xlink:href");
                if (xlink) {
                    var groups = xlink.trim().match(/^#(.+?)$/)
                    if (groups) pushAdd(groups[1], {o:that, a:"xlink:href"})
                }
            })
            // patch used ids and references (keep unreferenced ids fixed (to allow for identification from the editor to the css, even if classes should be preferred))
            var newIds = {};
            for (id in referencersIds) {
                var newId = svgPatcher.generateId(id);
                byId[id].id = newId;
                newIds[id] = newId;
            }

            setTimeout( // to help firefox in having updated ids
                (function() {
                for (id in referencersIds) {
                    var newId = newIds[id];
                    var refs = referencersIds[id];
                    $(refs).each(function(i,pair){
                        var prev = $(pair.o).attr(pair.a);
                        if (pair.a == "xlink:href") {
                            pair.o.setAttributeNS($.svg.xlinkNS, "href", prev.replace("#" + id, "#" + newId));
                        } else {
                            $(pair.o).attr(pair.a, prev.replace("#" + id, "#" + newId));
                        }
                    })
                        }
                    andThen();
                }), 0)

        }
    }

    /*
      jQuery.deck('Init')
    */
    $[deck]("animWaitMore"); // ensure we wait for the initialization of "svg" ext to end "anim" init
    $d.bind('deck.init', function() {
        var opts = $[deck]('getOptions');
        var container = $[deck]('getContainer');

        /*
          Load parameters from an Object element
        */
        var loadObjectParams = function(objectElement) {
            var attributes = {};
            $(objectElement).children("param").each(function(index){
                attributes[$(this).attr("name")] = $(this).attr("value");
            });
            $.each(objectElement.attributes, function (index, attr) {
                if ("data-" == attr.name.substr(0, 5)) {
                    attributes[attr.name.substr(5)] = attr.value;
                }
            });
            return attributes;
        }

        /*
          Return true if default params are set.
        */
        var validateParams = function(params) {
            return params['src'];// && params['width'] && params['height'];// && params['animator'];
        }

        /*
          Create SVG placeholder
        */
        var createSVG = function(object, attributes) {
            var $canvas, $control, $next, $reload, $placeholder;

            /* Create svg canvas */
            $canvas = $("<div />").attr({
                'id':  $(object).attr('id'),
                'data-src': attributes['src'],
                'class': opts.classes.svgPlaceholder + " " + $(object).attr('class')
            }).css({
                'height': attributes['height'],
                'width': attributes['width']
            });
            return $canvas;
        }

        /* Go through all toplevel slides */
        $($[deck]('getSlides')).each( function(i, $el) {
            var $slide = $[deck]('getSlide', i);

            /* Find all the object of type deckjs/svg */
            if ($slide == null) return true;
            $slide.find(opts.selectors.svgObject).each(function(index, obj) {
                /* Load attributes and validate them */
                var attributes = loadObjectParams(obj);
                if (!validateParams(attributes) ) {
                    throw "Error while initializing "+$(obj).attr('id')+", please ensure you have setup the required parameters."
                    return false;
                }

                /* Create SVG placeholder */
                var SVG = createSVG(obj, attributes);
                $(obj).replaceWith(SVG);

                // Finaly load the SVG data
                $[deck]("animWaitMore");

                var notDisabled = function(k) {
                    var kk = 'no'+k;
                    var disabled = attributes[kk] && attributes[kk] == "true"
                    return !disabled;
                };

                SVG.svg({
                    loadURL: attributes['src'],
                    onLoad: function($svg, w, h) {
                        var px = function (str) {return str.replace("px", "")}
                        var aa = $($svg.root());
                        if (aa.attr('viewBox') == undefined) {
                            if (w==undefined || h==undefined) {
                                if (opts.alert.missingSVG) alert(
                                    "There seem to be a problem with the loading of\n   '"+attributes['src'] + "'\n"
                                        +"\nMaybe the file does not exist?"
                                        +"\nOr maybe"
                                        +"\n - it has no w or h attribute?"
                                        +"\n - you're using chrome with local files?"
                                        +"\n   ⇒ try to restart chrome with '--disable-web-security'");
                                $[deck]("animWaitLess");
                            } else {
                                var to = "0 0 " + px(w) + " " + px(h);
                                $svg.root().setAttribute("viewBox", to);
                                aa.attr("svgViewBox", to);
                                if (attributes['stretch'] == 'true') $svg.root().setAttribute('preserveAspectRatio', "none");
                                if (notDisabled('stylerewrite')) {
                                    svgPatcher.styleToAttributes($svg.root(), attributes['src']);
                                }
                                if (notDisabled('idrewrite')) {
                                    svgPatcher.makeReferencedIdsUnique($svg.root(), attributes['src'], function() {
                                        $[deck]("animWaitLess");
                                    });
                                } else {
                                    $[deck]("animWaitLess");
                                }
                            }
                        }
                    }
                });
            });
        });
        $[deck]("animWaitLess");
    })

})(jQuery, 'deck');

<commit_msg>[svg] added todo (allow css classes to disable filters (to allow easy use from smartsyntax))<commit_after>/*!
Deck JS - deck.svg
Copyright (c) 2012 Rémi Emonet, as a major refactor from an early version from Rémi Barraquand.
*/

/*
This module provides a support for managed svg inclusion (allowing proper DOM access subsequently for animations, etc.).
*/

(function($, deck, undefined) {
    var $d = $(document);
    var may = function(f) {return f ? f : function() {}};

    $.extend(true, $[deck].defaults, {
        classes: {
            svgPlaceholder: 'deck-svg'
        },
	selectors: {
            svgObject: "object[type='deckjs/svg'], div.svg-object"
            // TODO: allow some classes to disable different filter/processing steps
        },
        alert: {
            missingSVG: true
        }
    });

    function walk(node, fn) {
        if (node) do {
            if (node.nodeType === 1) {
                fn.call(node);
                walk(node.firstChild, fn);
            }
        } while (node = node.nextSibling);
    }
    var svgPatcher = {
        styleToAttributes: function(root, svgfile) {
            walk(root, function() {
                var $n = $(this);
                if ($n.attr("style")) {
                    $($n.attr("style").trim().split(/ *; */)).each(function(index, style) {
                        if (style && style.substring(0,1) != "-") {
                            var s = style.trim().split(/ *: */);
                            $n.attr(s[0], s[1]);
                        }
                    });
                }
                $n.attr("style", null);
            })
        },
        referencingAttributes: ["clip-path", "color-profile", "fill", "filter", "marker-start", "marker-mid", "marker-end", "mask", "stroke"],
        nextId: 1,
        generateId: function(oldId) {
            var id = "uniquesvg"+svgPatcher.nextId;
            svgPatcher.nextId++;
            return id;
        },
        makeReferencedIdsUnique: function(root, svgfile, continuation) {
            var andThen = continuation || function(){}
            var byId = {};
            var referencersIds = {};
            var pushAdd = function(k, o) {
                if (referencersIds[k]) {
                    referencersIds[k].push(o);
                } else {
                    referencersIds[k] = [ o ];
                }
            };
            // gather all ids and references
            walk(root, function() {
                var that = this;
                var $n = $(this);
                var id = that.id;
                if (id) {
                    byId[id] = this;
                }
                $(svgPatcher.referencingAttributes).each(function(i,attr) {
                    var val = $n.attr(attr);
                    if (val) {
                        var groups = val.trim().match(/^url\(#(.+?)\)$/)
                        if (groups) pushAdd(groups[1], {o:that, a:attr})
                    }
                });
                var xlink = $n.attr("xlink:href");
                if (xlink) {
                    var groups = xlink.trim().match(/^#(.+?)$/)
                    if (groups) pushAdd(groups[1], {o:that, a:"xlink:href"})
                }
            })
            // patch used ids and references (keep unreferenced ids fixed (to allow for identification from the editor to the css, even if classes should be preferred))
            var newIds = {};
            for (id in referencersIds) {
                var newId = svgPatcher.generateId(id);
                byId[id].id = newId;
                newIds[id] = newId;
            }

            setTimeout( // to help firefox in having updated ids
                (function() {
                for (id in referencersIds) {
                    var newId = newIds[id];
                    var refs = referencersIds[id];
                    $(refs).each(function(i,pair){
                        var prev = $(pair.o).attr(pair.a);
                        if (pair.a == "xlink:href") {
                            pair.o.setAttributeNS($.svg.xlinkNS, "href", prev.replace("#" + id, "#" + newId));
                        } else {
                            $(pair.o).attr(pair.a, prev.replace("#" + id, "#" + newId));
                        }
                    })
                        }
                    andThen();
                }), 0)

        }
    }

    /*
      jQuery.deck('Init')
    */
    $[deck]("animWaitMore"); // ensure we wait for the initialization of "svg" ext to end "anim" init
    $d.bind('deck.init', function() {
        var opts = $[deck]('getOptions');
        var container = $[deck]('getContainer');

        /*
          Load parameters from an Object element
        */
        var loadObjectParams = function(objectElement) {
            var attributes = {};
            $(objectElement).children("param").each(function(index){
                attributes[$(this).attr("name")] = $(this).attr("value");
            });
            $.each(objectElement.attributes, function (index, attr) {
                if ("data-" == attr.name.substr(0, 5)) {
                    attributes[attr.name.substr(5)] = attr.value;
                }
            });
            return attributes;
        }

        /*
          Return true if default params are set.
        */
        var validateParams = function(params) {
            return params['src'];// && params['width'] && params['height'];// && params['animator'];
        }

        /*
          Create SVG placeholder
        */
        var createSVG = function(object, attributes) {
            var $canvas, $control, $next, $reload, $placeholder;

            /* Create svg canvas */
            $canvas = $("<div />").attr({
                'id':  $(object).attr('id'),
                'data-src': attributes['src'],
                'class': opts.classes.svgPlaceholder + " " + $(object).attr('class')
            }).css({
                'height': attributes['height'],
                'width': attributes['width']
            });
            return $canvas;
        }

        /* Go through all toplevel slides */
        $($[deck]('getSlides')).each( function(i, $el) {
            var $slide = $[deck]('getSlide', i);

            /* Find all the object of type deckjs/svg */
            if ($slide == null) return true;
            $slide.find(opts.selectors.svgObject).each(function(index, obj) {
                /* Load attributes and validate them */
                var attributes = loadObjectParams(obj);
                if (!validateParams(attributes) ) {
                    throw "Error while initializing "+$(obj).attr('id')+", please ensure you have setup the required parameters."
                    return false;
                }

                /* Create SVG placeholder */
                var SVG = createSVG(obj, attributes);
                $(obj).replaceWith(SVG);

                // Finaly load the SVG data
                $[deck]("animWaitMore");

                var notDisabled = function(k) {
                    var kk = 'no'+k;
                    var disabled = attributes[kk] && attributes[kk] == "true"
                    return !disabled;
                };

                SVG.svg({
                    loadURL: attributes['src'],
                    onLoad: function($svg, w, h) {
                        var px = function (str) {return str.replace("px", "")}
                        var aa = $($svg.root());
                        if (aa.attr('viewBox') == undefined) {
                            if (w==undefined || h==undefined) {
                                if (opts.alert.missingSVG) alert(
                                    "There seem to be a problem with the loading of\n   '"+attributes['src'] + "'\n"
                                        +"\nMaybe the file does not exist?"
                                        +"\nOr maybe"
                                        +"\n - it has no w or h attribute?"
                                        +"\n - you're using chrome with local files?"
                                        +"\n   ⇒ try to restart chrome with '--disable-web-security'");
                                $[deck]("animWaitLess");
                            } else {
                                var to = "0 0 " + px(w) + " " + px(h);
                                $svg.root().setAttribute("viewBox", to);
                                aa.attr("svgViewBox", to);
                                if (attributes['stretch'] == 'true') $svg.root().setAttribute('preserveAspectRatio', "none");
                                if (notDisabled('stylerewrite')) {
                                    svgPatcher.styleToAttributes($svg.root(), attributes['src']);
                                }
                                if (notDisabled('idrewrite')) {
                                    svgPatcher.makeReferencedIdsUnique($svg.root(), attributes['src'], function() {
                                        $[deck]("animWaitLess");
                                    });
                                } else {
                                    $[deck]("animWaitLess");
                                }
                            }
                        }
                    }
                });
            });
        });
        $[deck]("animWaitLess");
    })

})(jQuery, 'deck');

<|endoftext|>


<commit_before>(function() {
	window.matrixView = {

		// prepare dialog, when component is unconnected
		toUnconnectedState: function(formWindow) {
			formWindow.find(".matrix-container").remove();
			var container = $("
" + gettext("This component should be connected to a selected file or an executed task in order to view results.") + "
");
			formWindow.append(container);
			formWindow.dialog("option", "buttons", window.matrixView.reducedButtons());
			formWindow.dialog("option", "width", "auto");
		},

		reducedButtons: function() {
			var buttons = [{
				"text": gettext('Cancel'),
				"class": "btn",
				"click": function(ev) {
					$(this).dialog("close");
				}
			}];
			return buttons;
		},

		// all buttons for this component
		allButtons: function() {
			var buttons = [{
				"text": gettext('Download'),
				"class": "btn btn-primary",
				"click": function(ev) {
					var formWindow = $(this);
					var downloadOptions = $(this).find(".download-options").clone(true);
					downloadOptions.dialog({
						"title": gettext("Select file type and destination"),
						"modal": true,
						"minWidth": 450,
						"open": function() {
							var dialog = $(this).closest(".ui-dialog");
							dialog.find(".ui-dialog-titlebar > button").remove();
						},
						"buttons": [{
							"text": gettext("OK"),
							"class": "btn btn-primary",
							"click": function(ev) {
								var format = $(this).find("input[name=file-type]:checked").val();
								var dst = $(this).find("input[name=file-destination]:checked").val();
								if (dst == 'midas') {
									$(".not-implemented").show();
								} else {
									$(this).dialog("destroy");
									var url = window.componentFormUrls['MATRIX VIEW'];
									var data = window.matrixView.getOutputParamDetails(formWindow);
									document.location.href = url + "?download=True&format=" + format + "&pv_name=" + data.pv_name + "&dataset_url=" + data.dataset_url;
								}
							}
						},
						{
							"text": gettext("Cancel"),
							"class": "btn",
							"click": function(ev) {
								$(".not-implemented").hide();
								$(this).dialog("destroy");
							}
						}]
					});
				}
			}];
			var reducedButtons = window.matrixView.reducedButtons();
			return buttons.concat(reducedButtons);
		},

		// update dialog content with new data
		update: function(formWindow) {
			var url = window.componentFormUrls['MATRIX VIEW'];
			formWindow.find(".matrix-container").remove();
			var container = $("

");
            formWindow.dialog("option", "buttons", this.reducedButtons());
			formWindow.append(container);
			var data = window.matrixView.getOutputParamDetails(formWindow);
            if (!data["dataset_url"]) {
                this.toUnconnectedState(formWindow);
                return;
            }
			window.utils.showProgress();
			$.ajax({
				url: url,
				data: data,
				context: container
			}).done(function(resp) {
				$(this).html(resp);
				if (!/<[a-z][\s\S]*>/i.test(resp)) {
					// non-html (failure) response
				} else {
					formWindow.dialog("option", "buttons", window.matrixView.allButtons());
					formWindow.dialog("option", "width", "auto");
					var table = $(formWindow).find(".file-content-table");
					var dataTable = window.matrixView.initTable(table);
				}
				window.utils.hideProgress();
			});
		},

		initTable: function(table) {
			return table.dataTable({
				"sScrollY": 400,
				"sScrollX": "100%",
				"bInfo": false,
				"bPaginate": false,
				"bFilter": false,
				"bDestroy": true,
			});
		},

		// get details of a parameter, that is connected to the current component input connection
		getOutputParamDetails: function(dialog) {
			var inParam = dialog.find("input[value=INPUT_CONNECTION]");
			var srcRefField = inParam.closest("div").find("input[id$=source_ref]");
			var oParamField = window.experimentForm.getOutputParam(srcRefField);
			if (oParamField) {
				return {
					dataset_url: oParamField.val()
				}
			}
			return {}
		},

		doubleClick: function(componentType, formWindow) {
			if (componentType == 'MATRIX VIEW') {
				formWindow.dialog("option", "width", 614);
				formWindow.dialog("open");
				this.update(formWindow);
			}
		}
	}
})();

<commit_msg>Cosmetic fixes to matrix view.<commit_after>(function() {
	window.matrixView = {

		// prepare dialog, when component is unconnected
		toUnconnectedState: function(formWindow) {
			formWindow.find(".matrix-container").remove();
			var container = $("
" + gettext("This component should be connected to a selected file or an executed task in order to view results.") + "
");
			formWindow.append(container);
			formWindow.dialog("option", "buttons", window.matrixView.reducedButtons());
			formWindow.dialog("option", "width", "auto");
		},

		reducedButtons: function() {
			var buttons = [{
				"text": gettext('Cancel'),
				"class": "btn",
				"click": function(ev) {
					$(this).dialog("close");
				}
			}];
			return buttons;
		},

		// all buttons for this component
		allButtons: function() {
			var buttons = [{
				"text": gettext('Download'),
				"class": "btn btn-primary",
				"click": function(ev) {
					var formWindow = $(this);
					var downloadOptions = $(this).find(".download-options").clone(true);
					downloadOptions.dialog({
						"title": gettext("Select file type and destination"),
						"modal": true,
						"minWidth": 450,
						"open": function() {
							var dialog = $(this).closest(".ui-dialog");
							dialog.find(".ui-dialog-titlebar > button").remove();
						},
						"buttons": [{
							"text": gettext("OK"),
							"class": "btn btn-primary",
							"click": function(ev) {
								var format = $(this).find("input[name=file-type]:checked").val();
								var dst = $(this).find("input[name=file-destination]:checked").val();
								if (dst == 'midas') {
									$(this).find(".not-implemented").show();
								} else {
									$(this).dialog("destroy");
									var url = window.componentFormUrls['MATRIX VIEW'];
									var data = window.matrixView.getOutputParamDetails(formWindow);
									document.location.href = url + "?download=True&format=" + format + "&pv_name=" + data.pv_name + "&dataset_url=" + data.dataset_url;
								}
							}
						},
						{
							"text": gettext("Cancel"),
							"class": "btn",
							"click": function(ev) {
								$(".not-implemented").hide();
								$(this).dialog("destroy");
							}
						}]
					});
				}
			}];
			var reducedButtons = window.matrixView.reducedButtons();
			return buttons.concat(reducedButtons);
		},

		// update dialog content with new data
		update: function(formWindow) {
			var data = window.matrixView.getOutputParamDetails(formWindow);
            if (!data["dataset_url"]) {
                this.toUnconnectedState(formWindow);
                return;
            }
			var url = window.componentFormUrls['MATRIX VIEW'];
			formWindow.find(".matrix-container").remove();
			var container = $("

");
            formWindow.dialog("option", "buttons", this.reducedButtons());
			formWindow.append(container);
			$.ajax({
				url: url,
				data: data,
				context: container
			}).done(function(resp) {
				$(this).html(resp);
				if (!/<[a-z][\s\S]*>/i.test(resp)) {
					// non-html (failure) response
				} else {
					formWindow.dialog("option", "buttons", window.matrixView.allButtons());
					formWindow.dialog("option", "width", "auto");
					var table = $(formWindow).find(".file-content-table");
					var dataTable = window.matrixView.initTable(table);
				}
			});
		},

		initTable: function(table) {
			return table.dataTable({
				"sScrollY": 400,
				"sScrollX": "100%",
				"bInfo": false,
				"bPaginate": false,
				"bFilter": false,
				"bDestroy": true,
			});
		},

		// get details of a parameter, that is connected to the current component input connection
		getOutputParamDetails: function(dialog) {
			var inParam = dialog.find("input[value=INPUT_CONNECTION]");
			var srcRefField = inParam.closest("div").find("input[id$=source_ref]");
			var oParamField = window.experimentForm.getOutputParam(srcRefField);
			if (oParamField) {
				return {
					dataset_url: oParamField.val()
				}
			}
			return {}
		},

		doubleClick: function(componentType, formWindow) {
			if (componentType == 'MATRIX VIEW') {
				formWindow.dialog("option", "width", 614);
				formWindow.dialog("open");
				this.update(formWindow);
			}
		}
	}
})();

<|endoftext|>


<commit_before>// For University Theme Color
function getColorByUnivName(univ) {
  if (univ == "AU" || univ.includes("Adelphi")) return "#FDB813";
  if (univ == "UCB" || univ.toLowerCase().replace(/\s+/g, '').includes("berkeley")) return "#fdb515";
  if (univ == "UW" || univ.includes("Waterloo")) return "#FFD54F";
  if (univ == "KYU" || univ.includes("가야대")) return "#114fa1";
  if (univ == "GCHU" || univ.includes("가천대")) return "#00458c";
  if (univ == "CUK" || univ.includes("가톨릭대")) return "#003594";
  if (univ == "CKU" || univ.includes("가톨릭관동대")) return "#006276";
  if (univ == "MTU" || univ.includes("감리교신학대")) return "#800080";
  if (univ == "KANGNAM" || univ.includes("강남대")) return "#0091FF";
  if (univ == "GWNU" || univ.includes("강릉원주대")) return "#a90056";
  if (univ == "KNU" || univ.includes("강원대")) return "#1851a5";
  if (univ == "KU" || univ.includes("건국대") || univ == "건대") return "#036b3f";
  if (univ == "KONYANG" || univ.includes("건양대")) return "#006940";
  if (univ == "KGU" || univ.includes("경기대")) return "#004889";
  if (univ == "GNTECH" || univ.includes("경남과학기술대")) return "#2956a6";
  if (univ == "KYUNGNAM" || univ.includes("경남대")) return "#003A56";
  if (univ == "KDU" || univ.includes("경동대")) return "#0C4DA2";
  if (univ == "KPNU" || univ.includes("경북대")) return "#da2127";
  if (univ == "GNU" || univ.includes("경상대")) return "#242b90";
  if (univ == "KS" || univ.includes("경성대")) return "#0057b8";
  if (univ == "IKW" || univ.includes("경운대")) return "#23438e";
  if (univ == "KIU" || univ.includes("경일대")) return "#98012e";
  if (univ == "GJU" || univ.includes("경주대")) return "#df0013";
  if (univ == "KHU" || univ.includes("경희대")) return "#9d2235";
  if (univ == "KEIMYUNG" || univ.includes("계명대")) return "#024da0";
  if (univ == "KMCU" || univ.includes("계명문화대")) return "#eb2d2f";
  if (univ == "KRU" || univ.includes("고려대") || univ == "고대") return "#862633";
  if (univ == "KOSIN" || univ.includes("고신대")) return "#003f91";
  if (univ == "KJNU" || univ.includes("공주대")) return "#01499a";
  if (univ == "KSU" || univ.includes("광신대")) return "#1d2881";
  if (univ == "KWU" || univ.includes("광운대")) return "#8a1601";
  if (univ == "GWJCU" || univ.includes("광주가톨릭대")) return "#ed1c24";
  if (univ == "GWJU" || univ.includes("광주대")) return "#144112";
  if (univ == "GWJWU" || univ.includes("광주여자대")) return "#008b9c";
  if (univ == "KMU" || univ.includes("국민대")) return "#2864ae";
  if (univ == "KSNU" || univ.includes("군산대")) return "#437fc1";
  if (univ == "FEU" || univ.includes("극동대")) return "#221f1f";
  if (univ == "GGU" || univ.includes("금강대")) return "#005aab";
  if (univ == "KIT" || univ.includes("금오공과대") || univ == "금오공대") return "#1e90ff";
  if (univ == "GCU" || univ.includes("김천대")) return "#57444e";
  if (univ == "KKOT" || univ.includes("꽃동네대")) return "#cf171f";

  if (univ == "NAZARENE" || univ.includes("나사렛대")) return "#b32f20";
  if (univ == "NBU" || univ.includes("남부대")) return "#13007d";
  if (univ == "NSU" || univ.includes("남서울대")) return "#1f519b";

  if (univ == "DKU" || univ.includes("단국대")) return "#245ca1";
  if (univ == "CU" || univ.includes("대구가톨릭대")) return "#0742a4";
  if (univ == "DAEGU" || univ.includes("대구대")) return "#00806e";
  if (univ == "DGAU" || univ.includes("대구예술대")) return "#df569e";
  if (univ == "DHU" || univ.includes("대구한의대")) return "#50ad95";
  if (univ == "DSU" || univ.includes("대신대")) return "#3680bd";
  if (univ == "DCU" || univ.includes("대전가톨릭대")) return "#7a42a0";
  if (univ == "DJU" || univ.includes("대전대")) return "#347c4d";
  if (univ == "DTU" || univ.includes("대전신학대")) return "#2d70b5";
  if (univ == "DJNU" || univ.includes("대진대")) return "#184490";
  if (univ == "DSWU" || univ.includes("덕성여자대") || univ.includes("덕성여대")) return "#ac145a";
  if (univ == "DGU" || univ.includes("동국대")) return "#cb6015";
  if (univ == "DDWU" || univ.includes("동덕여자대") || univ.includes("동덕여대")) return "#8b2842";
  if (univ == "TU" || univ.includes("동명대")) return "#53aa48";
  if (univ == "DSU" || univ.includes("동서대")) return "#d43645";
  if (univ == "DSNU" || univ.includes("동신대")) return "#255ea9";
  if (univ == "DAU" || univ.includes("동아대")) return "#29166f";
  if (univ == "DYU" || univ.includes("동양대")) return "#143b82";
  if (univ == "DEU" || univ.includes("동의대")) return "#0b3d91";

  if (univ == "LTU" || univ.includes("루터대")) return "#2457a6";

  if (univ == "MJU" || univ.includes("명지대")) return "#10336c";
  if (univ == "MWU" || univ.includes("목원대")) return "#8b0000";
  if (univ == "MCU" || univ.includes("목포가톨릭대")) return "#353a97";
  if (univ == "MPNU" || univ.includes("목포대")) return "#20b2aa";
  if (univ == "MPNMU" || univ.includes("목포해양대")) return "#1f5a92";

  if (univ == "PCU" || univ.includes("배재대")) return "#071d8e";
  if (univ == "BU" || univ.includes("백석대")) return "#12319b";
  if (univ == "PKNU" || univ.includes("부경대")) return "#13007c";
  if (univ == "CUP" || univ.includes("부산가톨릭대")) return "#9a2183";
  if (univ == "PNU" || univ.includes("부산대") || univ == "부대") return "#005baa";
  if (univ == "BUFS" || univ.includes("부산외국어대") || univ == "부산외대") return "#ffd000";
  if (univ == "BPU" || univ.includes("부산장신대")) return "#2d6fa8";

  if (univ == "SYU" || univ.includes("삼육대")) return "#5389c6";
  if (univ == "SMU" || univ.includes("상명대")) return "#1f519b";
  if (univ == "SGU" || univ.includes("서강대")) return "#B0232A";
  if (univ == "SKU" || univ.includes("서경대")) return "#71bf44";
  if (univ == "SNU" || univ.includes("서울대")) return "#20408e";
  if (univ == "SeoulTech" || univ.includes("서울과학기술대") || univ == "서울과기대") return "#00205b";
  if (univ == "UOS" || univ.includes("서울시립대")) return "#151f6d";
  if (univ == "SMU" || univ.includes("선문대")) return "#006a74";
  if (univ == "SKHU" || univ.includes("성공회대")) return "#006BB1";
  if (univ == "SKKU" || univ.includes("성균관대")) return "#8DC63F";
  if (univ == "SJU" || univ.includes("세종대")) return "#ba0c2f";
  if (univ == "SSU" || univ.includes("숭실대")) return "#4badcd";
  if (univ == "SWC" || univ.includes("숭의여대")) return "#062d8f";

  if (univ == "AJU" || univ.includes("아주대")) return "#0072ce";
  if (univ == "YSU" || univ.includes("연세대")) return "#16407d";
  if (univ == "YU" || univ.includes("영남대")) return "#003e7d";
  if (univ == "INHA" || univ.includes("인하대")) return "#026769";

  if (univ == "JNU" || univ.includes("전남대")) return "#00913F";
  if (univ == "JBNU" || univ.includes("전북대")) return "#56296f";
  if (univ == "JJU" || univ.includes("전주대")) return "#006ba6";
  if (univ == "CAU" || univ.includes("중앙대")) return "#004c97";

  if (univ == "CNU" || univ.includes("충남대")) return "#003f98";
  if (univ == "CBNU" ||univ.includes("충북대")) return "#9B1F4E";

  if (univ == "KAIST" || univ.includes("카이스트")) return "#004191";

  if (univ == "PTU" || univ.includes("평택대")) return "#003e15";

  if (univ == "HUFS" || univ.includes("한국외국어대")) return "#00677F";
  if (univ == "KAU" || univ.includes("한국항공대")) return "#302475";
  if (univ == "HGU" || univ.includes("한동대")) return "#13eac9";
  if (univ == "HSU" || univ.includes("한성대")) return "#62b5e5";
  if (univ == "HYU" || univ.includes("한양대")) return "#003c71";
  if (univ == "HOSEO" || univ.includes("호서대")) return "#08449a";
  if (univ == "HIU" || univ.includes("홍익대")) return "#002c62";

  return "Not Found";
}
<commit_msg>Change color of Inha University<commit_after>// For University Theme Color
function getColorByUnivName(univ) {
  if (univ == "AU" || univ.includes("Adelphi")) return "#FDB813";
  if (univ == "UCB" || univ.toLowerCase().replace(/\s+/g, '').includes("berkeley")) return "#fdb515";
  if (univ == "UW" || univ.includes("Waterloo")) return "#FFD54F";
  if (univ == "KYU" || univ.includes("가야대")) return "#114fa1";
  if (univ == "GCHU" || univ.includes("가천대")) return "#00458c";
  if (univ == "CUK" || univ.includes("가톨릭대")) return "#003594";
  if (univ == "CKU" || univ.includes("가톨릭관동대")) return "#006276";
  if (univ == "MTU" || univ.includes("감리교신학대")) return "#800080";
  if (univ == "KANGNAM" || univ.includes("강남대")) return "#0091FF";
  if (univ == "GWNU" || univ.includes("강릉원주대")) return "#a90056";
  if (univ == "KNU" || univ.includes("강원대")) return "#1851a5";
  if (univ == "KU" || univ.includes("건국대") || univ == "건대") return "#036b3f";
  if (univ == "KONYANG" || univ.includes("건양대")) return "#006940";
  if (univ == "KGU" || univ.includes("경기대")) return "#004889";
  if (univ == "GNTECH" || univ.includes("경남과학기술대")) return "#2956a6";
  if (univ == "KYUNGNAM" || univ.includes("경남대")) return "#003A56";
  if (univ == "KDU" || univ.includes("경동대")) return "#0C4DA2";
  if (univ == "KPNU" || univ.includes("경북대")) return "#da2127";
  if (univ == "GNU" || univ.includes("경상대")) return "#242b90";
  if (univ == "KS" || univ.includes("경성대")) return "#0057b8";
  if (univ == "IKW" || univ.includes("경운대")) return "#23438e";
  if (univ == "KIU" || univ.includes("경일대")) return "#98012e";
  if (univ == "GJU" || univ.includes("경주대")) return "#df0013";
  if (univ == "KHU" || univ.includes("경희대")) return "#9d2235";
  if (univ == "KEIMYUNG" || univ.includes("계명대")) return "#024da0";
  if (univ == "KMCU" || univ.includes("계명문화대")) return "#eb2d2f";
  if (univ == "KRU" || univ.includes("고려대") || univ == "고대") return "#862633";
  if (univ == "KOSIN" || univ.includes("고신대")) return "#003f91";
  if (univ == "KJNU" || univ.includes("공주대")) return "#01499a";
  if (univ == "KSU" || univ.includes("광신대")) return "#1d2881";
  if (univ == "KWU" || univ.includes("광운대")) return "#8a1601";
  if (univ == "GWJCU" || univ.includes("광주가톨릭대")) return "#ed1c24";
  if (univ == "GWJU" || univ.includes("광주대")) return "#144112";
  if (univ == "GWJWU" || univ.includes("광주여자대")) return "#008b9c";
  if (univ == "KMU" || univ.includes("국민대")) return "#2864ae";
  if (univ == "KSNU" || univ.includes("군산대")) return "#437fc1";
  if (univ == "FEU" || univ.includes("극동대")) return "#221f1f";
  if (univ == "GGU" || univ.includes("금강대")) return "#005aab";
  if (univ == "KIT" || univ.includes("금오공과대") || univ == "금오공대") return "#1e90ff";
  if (univ == "GCU" || univ.includes("김천대")) return "#57444e";
  if (univ == "KKOT" || univ.includes("꽃동네대")) return "#cf171f";

  if (univ == "NAZARENE" || univ.includes("나사렛대")) return "#b32f20";
  if (univ == "NBU" || univ.includes("남부대")) return "#13007d";
  if (univ == "NSU" || univ.includes("남서울대")) return "#1f519b";

  if (univ == "DKU" || univ.includes("단국대")) return "#245ca1";
  if (univ == "CU" || univ.includes("대구가톨릭대")) return "#0742a4";
  if (univ == "DAEGU" || univ.includes("대구대")) return "#00806e";
  if (univ == "DGAU" || univ.includes("대구예술대")) return "#df569e";
  if (univ == "DHU" || univ.includes("대구한의대")) return "#50ad95";
  if (univ == "DSU" || univ.includes("대신대")) return "#3680bd";
  if (univ == "DCU" || univ.includes("대전가톨릭대")) return "#7a42a0";
  if (univ == "DJU" || univ.includes("대전대")) return "#347c4d";
  if (univ == "DTU" || univ.includes("대전신학대")) return "#2d70b5";
  if (univ == "DJNU" || univ.includes("대진대")) return "#184490";
  if (univ == "DSWU" || univ.includes("덕성여자대") || univ.includes("덕성여대")) return "#ac145a";
  if (univ == "DGU" || univ.includes("동국대")) return "#cb6015";
  if (univ == "DDWU" || univ.includes("동덕여자대") || univ.includes("동덕여대")) return "#8b2842";
  if (univ == "TU" || univ.includes("동명대")) return "#53aa48";
  if (univ == "DSU" || univ.includes("동서대")) return "#d43645";
  if (univ == "DSNU" || univ.includes("동신대")) return "#255ea9";
  if (univ == "DAU" || univ.includes("동아대")) return "#29166f";
  if (univ == "DYU" || univ.includes("동양대")) return "#143b82";
  if (univ == "DEU" || univ.includes("동의대")) return "#0b3d91";

  if (univ == "LTU" || univ.includes("루터대")) return "#2457a6";

  if (univ == "MJU" || univ.includes("명지대")) return "#10336c";
  if (univ == "MWU" || univ.includes("목원대")) return "#8b0000";
  if (univ == "MCU" || univ.includes("목포가톨릭대")) return "#353a97";
  if (univ == "MPNU" || univ.includes("목포대")) return "#20b2aa";
  if (univ == "MPNMU" || univ.includes("목포해양대")) return "#1f5a92";

  if (univ == "PCU" || univ.includes("배재대")) return "#071d8e";
  if (univ == "BU" || univ.includes("백석대")) return "#12319b";
  if (univ == "PKNU" || univ.includes("부경대")) return "#13007c";
  if (univ == "CUP" || univ.includes("부산가톨릭대")) return "#9a2183";
  if (univ == "PNU" || univ.includes("부산대") || univ == "부대") return "#005baa";
  if (univ == "BUFS" || univ.includes("부산외국어대") || univ == "부산외대") return "#ffd000";
  if (univ == "BPU" || univ.includes("부산장신대")) return "#2d6fa8";

  if (univ == "SYU" || univ.includes("삼육대")) return "#5389c6";
  if (univ == "SMU" || univ.includes("상명대")) return "#1f519b";
  if (univ == "SGU" || univ.includes("서강대")) return "#B0232A";
  if (univ == "SKU" || univ.includes("서경대")) return "#71bf44";
  if (univ == "SNU" || univ.includes("서울대")) return "#20408e";
  if (univ == "SeoulTech" || univ.includes("서울과학기술대") || univ == "서울과기대") return "#00205b";
  if (univ == "UOS" || univ.includes("서울시립대")) return "#151f6d";
  if (univ == "SMU" || univ.includes("선문대")) return "#006a74";
  if (univ == "SKHU" || univ.includes("성공회대")) return "#006BB1";
  if (univ == "SKKU" || univ.includes("성균관대")) return "#8DC63F";
  if (univ == "SJU" || univ.includes("세종대")) return "#ba0c2f";
  if (univ == "SSU" || univ.includes("숭실대")) return "#4badcd";
  if (univ == "SWC" || univ.includes("숭의여대")) return "#062d8f";

  if (univ == "AJU" || univ.includes("아주대")) return "#0072ce";
  if (univ == "YSU" || univ.includes("연세대")) return "#16407d";
  if (univ == "YU" || univ.includes("영남대")) return "#003e7d";
  if (univ == "INHA" || univ.includes("인하대")) return "#0267b9";

  if (univ == "JNU" || univ.includes("전남대")) return "#00913F";
  if (univ == "JBNU" || univ.includes("전북대")) return "#56296f";
  if (univ == "JJU" || univ.includes("전주대")) return "#006ba6";
  if (univ == "CAU" || univ.includes("중앙대")) return "#004c97";

  if (univ == "CNU" || univ.includes("충남대")) return "#003f98";
  if (univ == "CBNU" ||univ.includes("충북대")) return "#9B1F4E";

  if (univ == "KAIST" || univ.includes("카이스트")) return "#004191";

  if (univ == "PTU" || univ.includes("평택대")) return "#003e15";

  if (univ == "HUFS" || univ.includes("한국외국어대")) return "#00677F";
  if (univ == "KAU" || univ.includes("한국항공대")) return "#302475";
  if (univ == "HGU" || univ.includes("한동대")) return "#13eac9";
  if (univ == "HSU" || univ.includes("한성대")) return "#62b5e5";
  if (univ == "HYU" || univ.includes("한양대")) return "#003c71";
  if (univ == "HOSEO" || univ.includes("호서대")) return "#08449a";
  if (univ == "HIU" || univ.includes("홍익대")) return "#002c62";

  return "Not Found";
}
<|endoftext|>


<commit_before>import React, {Component} from 'react'
import {Card} from './components'

const hStyle = {
  fontFamily:'sans-serif',
  fontWeight:'normal',
  fontSize:'1.2em',
  margin:0,
  padding:0,
  marginBottom:'12px',
}

const TestSuccess = props =>

✔ {props.children}

const TestFailure = props => (

✘ {props.children}

{props.error.toString()}

)

export default class TestCard extends Component {
  constructor(props) {
    super(props)
    this.state = {results: []}
  }
  componentWillReceiveProps(nextProps) {
    //TODO
    this.runTests(nextProps.testModule)
  }
  componentDidMount() {
    //TODO
    this.runTests(this.props.testModule)
  }
  runTests(testModule) {
    console.log('running tests', Object.keys(testModule))
    const results = []
    const tests = Object.keys(testModule)
    tests.forEach(name => {
      try {
        testModule[name]()
        results.push([true, name])
      } catch(e) {
        results.push([e, name])
      }
    })
    console.log(results)
    this.setState({results})
  }
  render() {
    const {title, doc} = this.props
    return (
      <Card {...{title, doc}}>
      {this.state.results.map(([result, name], index) => (
        result === true
          ? <TestSuccess key={index}>{name}</TestSuccess>
          : <TestFailure key={index} error={result}>{name}</TestFailure>
        )
      )}
      </Card>
    )
  }
}
<commit_msg>Remove console logs<commit_after>import React, {Component} from 'react'
import {Card} from './components'

const hStyle = {
  fontFamily:'sans-serif',
  fontWeight:'normal',
  fontSize:'1.2em',
  margin:0,
  padding:0,
  marginBottom:'12px',
}

const TestSuccess = props =>

✔ {props.children}

const TestFailure = props => (

✘ {props.children}

{props.error.toString()}

)

export default class TestCard extends Component {
  constructor(props) {
    super(props)
    this.state = {results: []}
  }
  componentWillReceiveProps(nextProps) {
    //TODO
    this.runTests(nextProps.testModule)
  }
  componentDidMount() {
    //TODO
    this.runTests(this.props.testModule)
  }
  runTests(testModule) {
    const results = []
    const tests = Object.keys(testModule)
    tests.forEach(name => {
      try {
        testModule[name]()
        results.push([true, name])
      } catch(e) {
        results.push([e, name])
      }
    })
    this.setState({results})
  }
  render() {
    const {title, doc} = this.props
    return (
      <Card {...{title, doc}}>
      {this.state.results.map(([result, name], index) => (
        result === true
          ? <TestSuccess key={index}>{name}</TestSuccess>
          : <TestFailure key={index} error={result}>{name}</TestFailure>
        )
      )}
      </Card>
    )
  }
}
<|endoftext|>


<commit_before>var expect = require('expect.js');
var Mocksy = require('mocksy');
var server = new Mocksy({port: 9876});
var RequestBuilder = require('../index.js');
var host = 'http://localhost:9876';

describe('making bare requests', function () {
  var request;

  beforeEach(function (done) {
    request = new RequestBuilder();
    server.start(done);
  });

  afterEach(function (done) {
    server.stop(done);
  });

  it('makes a request with a given http method', function () {
    var apps = request.http('GET', host, 'apps');

    return apps().then(function (res) {
      expect(res.body.method).to.equal('GET');
      expect(res.body.url).to.equal('/apps');
    });
  });

  // Helpers
  RequestBuilder.httpMethods.forEach(function (method) {

    // EXAMPLE: request.get('url', 123)

    it('makes a ' + method + ' request', function () {
      var requester = request[method.toLowerCase()](host, 'requester', 123);

      return requester().then(function (res) {
        expect(res.body.method).to.equal(method);
        expect(res.body.url).to.equal('/requester/123');
      });
    });
  });

  it('defaults to a get request');
  it('passes body parameters to various methods');

});

describe('setting options', function () {
  var request;

  beforeEach(function (done) {
    request = new RequestBuilder();
    server.start(done);
  });

  afterEach(function (done) {
    server.stop(done);
  });

  it('sets the request origin', function () {
    var requester = request
      .get('test')
      .origin(host);

    return requester().then(function (res) {
      expect(res.body.url).to.equal('/test');
    });
  });

  it('aliases origin with host', function () {
    var requester = request
      .get('test')
      .host(host);

    return requester().then(function (res) {
      expect(res.body.url).to.equal('/test');
    });
  });

  it('sets the header for the request', function () {
    var requester = request
      .get('test')
      .host(host)
      .header('Authorization', 'Bearer 1234');

    return requester().then(function (res) {
      expect(res.body.headers.authorization).to.equal('Bearer 1234')
    });
  });

  it('sets an xhr options for the request', function () {
    var requester = request
      .get('test')
      .host(host)
      .xhrOption('method', 'POST')
      .xhrOption('form', {test: 'test'});

    return requester().then(function (res) {
      expect(res.body.method).to.equal('POST');
      expect(res.body.body).to.eql({test: 'test'});
    });
  });

});

// var getApps = request.get('apps')
//   .origin('https://api.divshot.com')
//   .header('Authorization', 'Session asdfwefon2o3f23uf');

// var getApps = request('GET', 'apps');

// getApps().then(function (apps) {

// });
<commit_msg>Skipping test<commit_after>var expect = require('expect.js');
var Mocksy = require('mocksy');
var server = new Mocksy({port: 9876});
var RequestBuilder = require('../index.js');
var host = 'http://localhost:9876';

describe('request instance', function () {
  var request;

  beforeEach(function (done) {
    request = new RequestBuilder();
    server.start(done);
  });

  afterEach(function (done) {
    server.stop(done);
  });

  // TODO: make this test work and pass
  it.skip('sets the origin for all http requests', function () {
    request.origin(host);

    return request.get('test')().then(function (res) {
      console.log(res.body);
    });
  });

});

describe('making bare requests', function () {
  var request;

  beforeEach(function (done) {
    request = new RequestBuilder();
    server.start(done);
  });

  afterEach(function (done) {
    server.stop(done);
  });

  it('makes a request with a given http method', function () {
    var apps = request.http('GET', host, 'apps');

    return apps().then(function (res) {
      expect(res.body.method).to.equal('GET');
      expect(res.body.url).to.equal('/apps');
    });
  });

  // Helpers
  RequestBuilder.httpMethods.forEach(function (method) {

    // EXAMPLE: request.get('url', 123)

    it('makes a ' + method + ' request', function () {
      var requester = request[method.toLowerCase()](host, 'requester', 123);

      return requester().then(function (res) {
        expect(res.body.method).to.equal(method);
        expect(res.body.url).to.equal('/requester/123');
      });
    });
  });

  it('defaults to a get request');
  it('passes body parameters to various methods');

});

describe('setting options', function () {
  var request;

  beforeEach(function (done) {
    request = new RequestBuilder();
    server.start(done);
  });

  afterEach(function (done) {
    server.stop(done);
  });

  it('sets the request origin', function () {
    var requester = request
      .get('test')
      .origin(host);

    return requester().then(function (res) {
      expect(res.body.url).to.equal('/test');
    });
  });

  it('aliases origin with host', function () {
    var requester = request
      .get('test')
      .host(host);

    return requester().then(function (res) {
      expect(res.body.url).to.equal('/test');
    });
  });

  it('sets the header for the request', function () {
    var requester = request
      .get('test')
      .host(host)
      .header('Authorization', 'Bearer 1234');

    return requester().then(function (res) {
      expect(res.body.headers.authorization).to.equal('Bearer 1234')
    });
  });

  it('sets an xhr options for the request', function () {
    var requester = request
      .get('test')
      .host(host)
      .xhrOption('method', 'POST')
      .xhrOption('form', {test: 'test'});

    return requester().then(function (res) {
      expect(res.body.method).to.equal('POST');
      expect(res.body.body).to.eql({test: 'test'});
    });
  });

});

// var getApps = request.get('apps')
//   .origin('https://api.divshot.com')
//   .header('Authorization', 'Session asdfwefon2o3f23uf');

// var getApps = request('GET', 'apps');

// getApps().then(function (apps) {

// });
<|endoftext|>


<commit_before>'use strict';

angular.module('graphs').factory('Graphite', ['$http','$q', '$log', 'Events', 'Utils',
	function($http, $q, $log, Events, Utils) {

        var Graphite = {
            getData: getData,
            addEvents: addEvents//,
            //createHighstockSeries: createHighstockSeries

        };

        return Graphite;

        function addFlagData (series, events){

            var flags  = {
                "type": "flags",
                //"onSeries": series[0],
                showInLegend: false,
                "shape": "squarepin"

            };

            var flagsData = [];

            _.each(events, function(event){
                if(event.eventDescription !== 'start' && event.eventDescription !== 'end') {
                    var epochTimestamp = new Date(event.eventTimestamp).getTime();
                    flagsData.push({x: epochTimestamp, title: '?', text: event.eventDescription});
                }
            })

            flags.data = flagsData.sort(Utils.dynamicSort('-x'));

            series.push(flags);

            return series;

        }

        function addEvents(series, from, until, productName, dashboardName){

            var deferred = $q.defer();
            var promise = deferred.promise;

            var convertedFrom = convertTime(from);
            var convertedUntil = convertTime(until);

            Events.listEventsForTestRun(productName, dashboardName, convertedFrom, convertedUntil)
                .success(function(events){
                    deferred.resolve(
                        addFlagData (series, events)
                    )
                }).error(function(msg, code) {
                    deferred.reject(msg);
                    $log.error(msg, code);
                });

            return promise;

        }

        function createChartSeries (graphiteData){

            var series = [];
            for (var j = 0; j < graphiteData.length; j++) {

                var data = [];

                for (var i = 0; i < graphiteData[j].datapoints.length; i++) {

                    if (graphiteData[j].datapoints[i][0] !== null)
                        data.push([graphiteData[j].datapoints[i][1] * 1000, graphiteData[j].datapoints[i][0]]);

                }

                series.push({
                    name: graphiteData[j].target,
                    data: data,
                    tooltip: {
                        yDecimals: 0
                    }
                });
            }

            return series;

        }

        function getData(from, until, targets, maxDataPoints) {

            var urlEncodedTargetUrl = '';

            var queryFrom = /^\d+$/.test(from) ?  Math.round(from / 1000) : from;
            var queryUntil = /^\d+$/.test(until) ?  Math.round(until / 1000) : until;

            _.each(targets, function(target){

                urlEncodedTargetUrl = urlEncodedTargetUrl + '&target=' + encodeURI(target);

            });

            var deferred = $q.defer();
            var promise = deferred.promise;

            $http.jsonp('/graphite?' + urlEncodedTargetUrl + '&from=' + queryFrom + '&until=' + queryUntil + '&maxDataPoints=' + maxDataPoints + '&callback=JSON_CALLBACK')
                .success(function(graphiteData) {
                    deferred.resolve(
                        createChartSeries(graphiteData)
                    )

                }).error(function(msg, code) {
                    deferred.reject(msg);
                    $log.error(msg, code);
                });

            return promise;
        }

    function convertTime(inputTime){

        var outputTime;
        var inputTimePattern = new RegExp(/-([0-9]+)(h|d|w|mon|min|y|2)/);
        var numberOf = (inputTimePattern.test(inputTime)) ? inputTime.match(inputTimePattern)[1] : "";
        var timeUnit = (inputTimePattern.test(inputTime)) ? inputTime.match(inputTimePattern)[2] : "";
        if (inputTime == "now"){

            outputTime = new Date().getTime();
        }else {

            switch (timeUnit) {

                case "s":

                    outputTime = new Date() - numberOf
                    break;

                case "min":

                    outputTime = new Date() - (numberOf * 60 * 1000)
                    break;

                case "h":

                    outputTime = new Date() - (numberOf * 3600 * 1000)
                    break;

                case "d":

                    outputTime = new Date() - (numberOf * 3600 * 24 * 1000)
                    break;

                case "w":

                    outputTime = new Date() - (numberOf * 3600 * 24 * 7 * 1000)
                    break;

                case "mon":

                    outputTime = new Date() - (numberOf * 3600 * 24 * 7 * 30 * 1000)
                    break;

                default:

                    outputTime = inputTime;//Math.round(inputTime / 1000);
                    break;
            }
        }

        return outputTime;

    }

    }
]);
<commit_msg>added numbers to events<commit_after>'use strict';

angular.module('graphs').factory('Graphite', ['$http','$q', '$log', 'Events', 'Utils',
	function($http, $q, $log, Events, Utils) {

        var Graphite = {
            getData: getData,
            addEvents: addEvents//,
            //createHighstockSeries: createHighstockSeries

        };

        return Graphite;

        function addFlagData (series, events){

            var flags  = {
                "type": "flags",
                //"onSeries": series[0],
                showInLegend: false,
                "shape": "squarepin"

            };

            var flagsData = [];
            var sortedEvents = events.sort(Utils.dynamicSort('eventTimestamp'));

            _.each(sortedEvents, function(event, i){
                if(event.eventDescription !== 'start' && event.eventDescription !== 'end') {
                    var epochTimestamp = new Date(event.eventTimestamp).getTime();
                    flagsData.push({x: epochTimestamp, title: i, text: event.eventDescription});
                }
            })

            flags.data = flagsData;

            series.push(flags);

            return series;

        }

        function addEvents(series, from, until, productName, dashboardName){

            var deferred = $q.defer();
            var promise = deferred.promise;

            var convertedFrom = convertTime(from);
            var convertedUntil = convertTime(until);

            Events.listEventsForTestRun(productName, dashboardName, convertedFrom, convertedUntil)
                .success(function(events){
                    deferred.resolve(
                        addFlagData (series, events)
                    )
                }).error(function(msg, code) {
                    deferred.reject(msg);
                    $log.error(msg, code);
                });

            return promise;

        }

        function createChartSeries (graphiteData){

            var series = [];
            for (var j = 0; j < graphiteData.length; j++) {

                var data = [];

                for (var i = 0; i < graphiteData[j].datapoints.length; i++) {

                    if (graphiteData[j].datapoints[i][0] !== null)
                        data.push([graphiteData[j].datapoints[i][1] * 1000, graphiteData[j].datapoints[i][0]]);

                }

                series.push({
                    name: graphiteData[j].target,
                    data: data,
                    tooltip: {
                        yDecimals: 0
                    }
                });
            }

            return series;

        }

        function getData(from, until, targets, maxDataPoints) {

            var urlEncodedTargetUrl = '';

            var queryFrom = /^\d+$/.test(from) ?  Math.round(from / 1000) : from;
            var queryUntil = /^\d+$/.test(until) ?  Math.round(until / 1000) : until;

            _.each(targets, function(target){

                urlEncodedTargetUrl = urlEncodedTargetUrl + '&target=' + encodeURI(target);

            });

            var deferred = $q.defer();
            var promise = deferred.promise;

            $http.jsonp('/graphite?' + urlEncodedTargetUrl + '&from=' + queryFrom + '&until=' + queryUntil + '&maxDataPoints=' + maxDataPoints + '&callback=JSON_CALLBACK')
                .success(function(graphiteData) {
                    deferred.resolve(
                        createChartSeries(graphiteData)
                    )

                }).error(function(msg, code) {
                    deferred.reject(msg);
                    $log.error(msg, code);
                });

            return promise;
        }

    function convertTime(inputTime){

        var outputTime;
        var inputTimePattern = new RegExp(/-([0-9]+)(h|d|w|mon|min|y|2)/);
        var numberOf = (inputTimePattern.test(inputTime)) ? inputTime.match(inputTimePattern)[1] : "";
        var timeUnit = (inputTimePattern.test(inputTime)) ? inputTime.match(inputTimePattern)[2] : "";
        if (inputTime == "now"){

            outputTime = new Date().getTime();
        }else {

            switch (timeUnit) {

                case "s":

                    outputTime = new Date() - numberOf
                    break;

                case "min":

                    outputTime = new Date() - (numberOf * 60 * 1000)
                    break;

                case "h":

                    outputTime = new Date() - (numberOf * 3600 * 1000)
                    break;

                case "d":

                    outputTime = new Date() - (numberOf * 3600 * 24 * 1000)
                    break;

                case "w":

                    outputTime = new Date() - (numberOf * 3600 * 24 * 7 * 1000)
                    break;

                case "mon":

                    outputTime = new Date() - (numberOf * 3600 * 24 * 7 * 30 * 1000)
                    break;

                default:

                    outputTime = inputTime;//Math.round(inputTime / 1000);
                    break;
            }
        }

        return outputTime;

    }

    }
]);
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import shallowEqual from './utils/shallowEqual';
import shallowEqualScalar from './utils/shallowEqualScalar';
import isPlainObject from 'lodash/lang/isPlainObject';
import invariant from 'invariant';
import checkDecoratorArguments from './utils/checkDecoratorArguments';

export default function DragLayer(collect, options = {}) {
  checkDecoratorArguments('DragLayer', 'collect[, options]', ...arguments);
  invariant(
    typeof collect === 'function',
    'Expected "collect" provided as the first argument to DragLayer ' +
    'to be a function that collects props to inject into the component. ',
    'Instead, received %s. ' +
    'Read more: http://gaearon.github.io/react-dnd/docs-drag-layer.html',
    collect
  );
  invariant(
    isPlainObject(options),
    'Expected "options" provided as the second argument to DragLayer to be ' +
    'a plain object when specified. ' +
    'Instead, received %s. ' +
    'Read more: http://gaearon.github.io/react-dnd/docs-drag-layer.html',
    options
  );

  return function decorateLayer(DecoratedComponent) {
    const { arePropsEqual = shallowEqualScalar } = options;
    const displayName =
      DecoratedComponent.displayName ||
      DecoratedComponent.name ||
      'Component';

    return class DragLayerContainer extends Component {
      static DecoratedComponent = DecoratedComponent;

      static displayName = `DragLayer(${displayName})`;

      static contextTypes = {
        dragDropManager: PropTypes.object.isRequired
      }

      getDecoratedComponentInstance() {
        return this.refs.child;
      }

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

      constructor(props, context) {
        super(props);
        this.handleChange = this.handleChange.bind(this);

        this.manager = context.dragDropManager;
        invariant(
          typeof this.manager === 'object',
          'Could not find the drag and drop manager in the context of %s. ' +
          'Make sure to wrap the top-level component of your app with DragDropContext. ' +
          'Read more: http://gaearon.github.io/react-dnd/docs-troubleshooting.html#could-not-find-the-drag-and-drop-manager-in-the-context',
          displayName,
          displayName
        );

        this.state = this.getCurrentState();
      }

      componentDidMount() {
        const monitor = this.manager.getMonitor();
        this.unsubscribe = monitor.subscribeToStateChange(this.handleChange);
      }

      componentWillUnmount() {
        this.unsubscribe;
      }

      handleChange() {
        const nextState = this.getCurrentState();
        if (!shallowEqual(nextState, this.state)) {
          this.setState(nextState);
        }
      }

      getCurrentState() {
        const monitor = this.manager.getMonitor();
        return collect(monitor);
      }

      render() {
        return (
          <DecoratedComponent {...this.props}
                              {...this.state}
                              ref='child' />
        );
      }
    };
  };
}
<commit_msg>Revert "Subscribe DragLayer only to state changes, which include offset changes"<commit_after>import React, { Component, PropTypes } from 'react';
import shallowEqual from './utils/shallowEqual';
import shallowEqualScalar from './utils/shallowEqualScalar';
import isPlainObject from 'lodash/lang/isPlainObject';
import invariant from 'invariant';
import checkDecoratorArguments from './utils/checkDecoratorArguments';

export default function DragLayer(collect, options = {}) {
  checkDecoratorArguments('DragLayer', 'collect[, options]', ...arguments);
  invariant(
    typeof collect === 'function',
    'Expected "collect" provided as the first argument to DragLayer ' +
    'to be a function that collects props to inject into the component. ',
    'Instead, received %s. ' +
    'Read more: http://gaearon.github.io/react-dnd/docs-drag-layer.html',
    collect
  );
  invariant(
    isPlainObject(options),
    'Expected "options" provided as the second argument to DragLayer to be ' +
    'a plain object when specified. ' +
    'Instead, received %s. ' +
    'Read more: http://gaearon.github.io/react-dnd/docs-drag-layer.html',
    options
  );

  return function decorateLayer(DecoratedComponent) {
    const { arePropsEqual = shallowEqualScalar } = options;
    const displayName =
      DecoratedComponent.displayName ||
      DecoratedComponent.name ||
      'Component';

    return class DragLayerContainer extends Component {
      static DecoratedComponent = DecoratedComponent;

      static displayName = `DragLayer(${displayName})`;

      static contextTypes = {
        dragDropManager: PropTypes.object.isRequired
      }

      getDecoratedComponentInstance() {
        return this.refs.child;
      }

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

      constructor(props, context) {
        super(props);
        this.handleChange = this.handleChange.bind(this);

        this.manager = context.dragDropManager;
        invariant(
          typeof this.manager === 'object',
          'Could not find the drag and drop manager in the context of %s. ' +
          'Make sure to wrap the top-level component of your app with DragDropContext. ' +
          'Read more: http://gaearon.github.io/react-dnd/docs-troubleshooting.html#could-not-find-the-drag-and-drop-manager-in-the-context',
          displayName,
          displayName
        );

        this.state = this.getCurrentState();
      }

      componentDidMount() {
        const monitor = this.manager.getMonitor();
        this.unsubscribeFromOffsetChange = monitor.subscribeToOffsetChange(this.handleChange);
        this.unsubscribeFromStateChange = monitor.subscribeToStateChange(this.handleChange);
      }

      componentWillUnmount() {
        this.unsubscribeFromOffsetChange();
        this.unsubscribeFromStateChange();
      }

      handleChange() {
        const nextState = this.getCurrentState();
        if (!shallowEqual(nextState, this.state)) {
          this.setState(nextState);
        }
      }

      getCurrentState() {
        const monitor = this.manager.getMonitor();
        return collect(monitor);
      }

      render() {
        return (
          <DecoratedComponent {...this.props}
                              {...this.state}
                              ref='child' />
        );
      }
    };
  };
}
<|endoftext|>


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

    app.directive('contenteditable', [ContentEditableDirective]);
})();
<commit_msg>removed IIFE<commit_after>angular.module('ContentEditable', [])
    .directive('contenteditable', [ContentEditableDirective]);
<|endoftext|>