<commit_before>/**
 * tab-content.js
 */

import {
  escapeMatchingChars, isObjectNotEmpty, isString, throwErr,
} from "./common.js";
import {removeTab, getTab, updateTab} from "./browser.js";
import {getSidebarTabId} from "./tab-util.js";
import {
  CLASS_TAB_CONTENT, CLASS_TAB_ICON, CLASS_TAB_TITLE, IDENTIFIED,
  TAB_CLOSE, TAB_MUTE, TAB_MUTE_UNMUTE, TABS_CLOSE, TABS_MUTE, TABS_MUTE_UNMUTE,
  URL_AUDIO_MUTED, URL_AUDIO_PLAYING, URL_FAVICON_DEFAULT, URL_LOADING_THROBBER,
} from "./constant.js";

/* api */
const {i18n} = browser;

/* favicon */
const favicon = new Map();

favicon.set("https://abs.twimg.com/favicons/favicon.ico",
            "../img/twitter-logo-blue.svg");
favicon.set("https://abs.twimg.com/icons/apple-touch-icon-192x192.png",
            "../img/twitter-logo-blue.svg");
favicon.set("chrome://browser/skin/customize.svg",
            "../img/customize-favicon.svg");
favicon.set("chrome://browser/skin/settings.svg",
            "../img/options-favicon.svg");
favicon.set("chrome://mozapps/skin/extensions/extensionGeneric-16.svg",
            "../img/addons-favicon.svg");

/**
 * tab icon fallback
 * @param {!Object} evt - event
 * @returns {boolean} - false
 */
export const tabIconFallback = evt => {
  const {target} = evt;
  if (target.hasOwnProperty("src")) {
    target.src = URL_FAVICON_DEFAULT;
  }
  return false;
};

/**
 * add tab icon error listener
 * @param {Object} elm - img element
 * @returns {void}
 */
export const addTabIconErrorListener = async elm => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE) {
    elm.addEventListener("error", tabIconFallback);
  }
};

/**
 * get favicon
 * @param {Object} elm - img element
 * @param {string} favIconUrl - favicon url
 * @returns {string} - favicon url
 */
export const getFavicon = async (elm, favIconUrl) => {
  let src;
  if (elm && elm.nodeType === Node.ELEMENT_NODE && elm.localName === "img") {
    if (isString(favIconUrl)) {
      const {protocol} = new URL(favIconUrl);
      if (/(?:f(?:tp|ile)|https?):/.test(protocol)) {
        const opt = {
          cache: "force-cache",
          credentials: "include",
          method: "GET",
          mode: "cors",
        };
        src = await fetch(favIconUrl, opt).then(res => {
          const {ok, url} = res;
          return ok && url || null;
        }).catch(() => favicon.get(favIconUrl));
        if (!src) {
          src = favicon.get(favIconUrl) || URL_FAVICON_DEFAULT;
        }
      } else {
        src = favicon.get(favIconUrl) || URL_FAVICON_DEFAULT;
      }
    } else {
      src = URL_FAVICON_DEFAULT;
    }
  }
  return src || URL_FAVICON_DEFAULT;
};

/**
 * set tab icon
 * @param {Object} elm - img element
 * @param {Object} info - tab info
 * @returns {void}
 */
export const setTabIcon = async (elm, info) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE && elm.localName === "img") {
    const {favIconUrl, status, title, url} = info;
    if (status === "loading") {
      const str = await escapeMatchingChars(title, /([/.?-])/g);
      const reg = new RegExp(`^(?:f(?:ile|tp)|https?)://(?:www\\.)?${str}$`);
      const isUrl = reg.test(url);
      if (elm.dataset.connecting && !isUrl) {
        const {stroke} = window.getComputedStyle(elm);
        elm.style.fill = stroke;
        elm.dataset.connecting = "";
      } else if (isUrl) {
        elm.dataset.connecting = url;
      }
      elm.src = URL_LOADING_THROBBER;
    } else {
      elm.dataset.connecting = "";
      if (favIconUrl) {
        const {protocol} = new URL(favIconUrl);
        if (protocol === "data:") {
          elm.src = favIconUrl;
        } else {
          elm.src = await getFavicon(elm, favIconUrl);
        }
      } else {
        elm.src = URL_FAVICON_DEFAULT;
      }
      elm.style.fill = null;
    }
  }
};

/* tab content */
/**
 * set tab content
 * @param {Object} tab - tab element
 * @param {Object} tabsTab - tabs.Tab
 * @returns {void}
 */
export const setTabContent = async (tab, tabsTab) => {
  if (tab && tab.nodeType === Node.ELEMENT_NODE && tabsTab) {
    const {favIconUrl, status, title, url} = tabsTab;
    const tabContent = tab.querySelector(`.${CLASS_TAB_CONTENT}`);
    const tabTitle = tab.querySelector(`.${CLASS_TAB_TITLE}`);
    const tabIcon = tab.querySelector(`.${CLASS_TAB_ICON}`);
    if (tabContent) {
      tabContent.title = title;
    }
    if (tabTitle) {
      tabTitle.textContent = title;
    }
    if (tabIcon) {
      await setTabIcon(tabIcon, {favIconUrl, status, title, url});
    }
    tab.dataset.tab = JSON.stringify(tabsTab);
  }
};

/* audio */
/**
 * toggle audio state
 * @param {!Object} evt - event
 * @returns {?AsyncFunction} - updateTab()
 */
export const toggleAudio = async evt => {
  const {target} = evt;
  const tabId = getSidebarTabId(target);
  let func;
  if (Number.isInteger(tabId)) {
    const tabsTab = await getTab(tabId);
    if (tabsTab) {
      const {mutedInfo: {muted}} = tabsTab;
      func = updateTab(tabId, {muted: !muted});
    }
  }
  return func || null;
};

/**
 * add tab audio click event listener
 * @param {Object} elm - element
 * @returns {void}
 */
export const addTabAudioClickListener = async elm => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE) {
    elm.addEventListener("click", evt => toggleAudio(evt).catch(throwErr));
  }
};

/**
 * set tab audio
 * @param {Object} elm - element
 * @param {Object} info - audio info
 * @returns {void}
 */
export const setTabAudio = async (elm, info) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE) {
    const {audible, muted, highlighted} = info;
    if (muted) {
      if (highlighted) {
        elm.title = i18n.getMessage(`${TABS_MUTE_UNMUTE}_tooltip`);
      } else {
        elm.title = i18n.getMessage(`${TAB_MUTE_UNMUTE}_tooltip`);
      }
    } else if (audible) {
      if (highlighted) {
        elm.title = i18n.getMessage(`${TABS_MUTE}_tooltip`);
      } else {
        elm.title = i18n.getMessage(`${TAB_MUTE}_tooltip`);
      }
    } else {
      elm.title = "";
    }
  }
};

/**
 * set tab audio icon
 * @param {Object} elm - element
 * @param {Object} info - audio info
 * @returns {void}
 */
export const setTabAudioIcon = async (elm, info) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE && elm.localName === "img") {
    const {audible, muted} = info;
    if (muted) {
      elm.alt = i18n.getMessage(`${TAB_MUTE_UNMUTE}`);
      elm.src = URL_AUDIO_MUTED;
    } else if (audible) {
      elm.alt = i18n.getMessage(`${TAB_MUTE}`);
      elm.src = URL_AUDIO_PLAYING;
    } else {
      elm.alt = "";
      elm.src = "";
    }
  }
};

/* close button */
/**
 * set close tab
 * @param {Object} elm - element
 * @param {boolean} highlighted - highlighted
 * @returns {void}
 */
export const setCloseTab = async (elm, highlighted) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE) {
    if (highlighted) {
      elm.title = i18n.getMessage(`${TABS_CLOSE}_tooltip`);
    } else {
      elm.title = i18n.getMessage(`${TAB_CLOSE}_tooltip`);
    }
  }
};

/**
 * close tab
 * @param {!Object} evt - event
 * @returns {?AsyncFunction} - removeTab()
 */
export const closeTab = async evt => {
  const {target} = evt;
  const tabId = getSidebarTabId(target);
  let func;
  if (Number.isInteger(tabId)) {
    func = removeTab(tabId);
  }
  return func || null;
};

/**
 * add tab close click listener
 * @param {Object} elm - element
 * @returns {void}
 */
export const addTabCloseClickListener = async elm => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE) {
    elm.addEventListener("click", evt => closeTab(evt).catch(throwErr));
  }
};

/* contextual identities */
/**
 * set contextual identities icon
 * @param {Object} elm - element
 * @param {Object} info - contextual identities info
 * @returns {void}
 */
export const setContextualIdentitiesIcon = async (elm, info) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE && elm.localName === "img" &&
      isObjectNotEmpty(info)) {
    const {color, icon, name} = info;
    if (color && icon && name) {
      elm.alt = name;
      elm.src = `../img/${icon}.svg#${color}`;
      elm.parentNode.classList.add(IDENTIFIED);
    }
  }
};
<commit_msg>check info is object<commit_after>/**
 * tab-content.js
 */

import {
  escapeMatchingChars, isObjectNotEmpty, isString, throwErr,
} from "./common.js";
import {removeTab, getTab, updateTab} from "./browser.js";
import {getSidebarTabId} from "./tab-util.js";
import {
  CLASS_TAB_CONTENT, CLASS_TAB_ICON, CLASS_TAB_TITLE, IDENTIFIED,
  TAB_CLOSE, TAB_MUTE, TAB_MUTE_UNMUTE, TABS_CLOSE, TABS_MUTE, TABS_MUTE_UNMUTE,
  URL_AUDIO_MUTED, URL_AUDIO_PLAYING, URL_FAVICON_DEFAULT, URL_LOADING_THROBBER,
} from "./constant.js";

/* api */
const {i18n} = browser;

/* favicon */
const favicon = new Map();

favicon.set("https://abs.twimg.com/favicons/favicon.ico",
            "../img/twitter-logo-blue.svg");
favicon.set("https://abs.twimg.com/icons/apple-touch-icon-192x192.png",
            "../img/twitter-logo-blue.svg");
favicon.set("chrome://browser/skin/customize.svg",
            "../img/customize-favicon.svg");
favicon.set("chrome://browser/skin/settings.svg",
            "../img/options-favicon.svg");
favicon.set("chrome://mozapps/skin/extensions/extensionGeneric-16.svg",
            "../img/addons-favicon.svg");

/**
 * tab icon fallback
 * @param {!Object} evt - event
 * @returns {boolean} - false
 */
export const tabIconFallback = evt => {
  const {target} = evt;
  if (target.hasOwnProperty("src")) {
    target.src = URL_FAVICON_DEFAULT;
  }
  return false;
};

/**
 * add tab icon error listener
 * @param {Object} elm - img element
 * @returns {void}
 */
export const addTabIconErrorListener = async elm => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE) {
    elm.addEventListener("error", tabIconFallback);
  }
};

/**
 * get favicon
 * @param {Object} elm - img element
 * @param {string} favIconUrl - favicon url
 * @returns {string} - favicon url
 */
export const getFavicon = async (elm, favIconUrl) => {
  let src;
  if (elm && elm.nodeType === Node.ELEMENT_NODE && elm.localName === "img") {
    if (isString(favIconUrl)) {
      const {protocol} = new URL(favIconUrl);
      if (/(?:f(?:tp|ile)|https?):/.test(protocol)) {
        const opt = {
          cache: "force-cache",
          credentials: "include",
          method: "GET",
          mode: "cors",
        };
        src = await fetch(favIconUrl, opt).then(res => {
          const {ok, url} = res;
          return ok && url || null;
        }).catch(() => favicon.get(favIconUrl));
        if (!src) {
          src = favicon.get(favIconUrl) || URL_FAVICON_DEFAULT;
        }
      } else {
        src = favicon.get(favIconUrl) || URL_FAVICON_DEFAULT;
      }
    } else {
      src = URL_FAVICON_DEFAULT;
    }
  }
  return src || URL_FAVICON_DEFAULT;
};

/**
 * set tab icon
 * @param {Object} elm - img element
 * @param {Object} info - tab info
 * @returns {void}
 */
export const setTabIcon = async (elm, info) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE && elm.localName === "img" &&
      isObjectNotEmpty(info)) {
    const {favIconUrl, status, title, url} = info;
    if (status === "loading") {
      const str = await escapeMatchingChars(title, /([/.?-])/g);
      const reg = new RegExp(`^(?:f(?:ile|tp)|https?)://(?:www\\.)?${str}$`);
      const isUrl = reg.test(url);
      if (elm.dataset.connecting && !isUrl) {
        const {stroke} = window.getComputedStyle(elm);
        elm.style.fill = stroke;
        elm.dataset.connecting = "";
      } else if (isUrl) {
        elm.dataset.connecting = url;
      }
      elm.src = URL_LOADING_THROBBER;
    } else {
      elm.dataset.connecting = "";
      if (favIconUrl) {
        const {protocol} = new URL(favIconUrl);
        if (protocol === "data:") {
          elm.src = favIconUrl;
        } else {
          elm.src = await getFavicon(elm, favIconUrl);
        }
      } else {
        elm.src = URL_FAVICON_DEFAULT;
      }
      elm.style.fill = null;
    }
  }
};

/* tab content */
/**
 * set tab content
 * @param {Object} tab - tab element
 * @param {Object} tabsTab - tabs.Tab
 * @returns {void}
 */
export const setTabContent = async (tab, tabsTab) => {
  if (tab && tab.nodeType === Node.ELEMENT_NODE && tabsTab) {
    const {favIconUrl, status, title, url} = tabsTab;
    const tabContent = tab.querySelector(`.${CLASS_TAB_CONTENT}`);
    const tabTitle = tab.querySelector(`.${CLASS_TAB_TITLE}`);
    const tabIcon = tab.querySelector(`.${CLASS_TAB_ICON}`);
    if (tabContent) {
      tabContent.title = title;
    }
    if (tabTitle) {
      tabTitle.textContent = title;
    }
    if (tabIcon) {
      await setTabIcon(tabIcon, {favIconUrl, status, title, url});
    }
    tab.dataset.tab = JSON.stringify(tabsTab);
  }
};

/* audio */
/**
 * toggle audio state
 * @param {!Object} evt - event
 * @returns {?AsyncFunction} - updateTab()
 */
export const toggleAudio = async evt => {
  const {target} = evt;
  const tabId = getSidebarTabId(target);
  let func;
  if (Number.isInteger(tabId)) {
    const tabsTab = await getTab(tabId);
    if (tabsTab) {
      const {mutedInfo: {muted}} = tabsTab;
      func = updateTab(tabId, {muted: !muted});
    }
  }
  return func || null;
};

/**
 * add tab audio click event listener
 * @param {Object} elm - element
 * @returns {void}
 */
export const addTabAudioClickListener = async elm => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE) {
    elm.addEventListener("click", evt => toggleAudio(evt).catch(throwErr));
  }
};

/**
 * set tab audio
 * @param {Object} elm - element
 * @param {Object} info - audio info
 * @returns {void}
 */
export const setTabAudio = async (elm, info) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE && isObjectNotEmpty(info)) {
    const {audible, muted, highlighted} = info;
    if (muted) {
      if (highlighted) {
        elm.title = i18n.getMessage(`${TABS_MUTE_UNMUTE}_tooltip`);
      } else {
        elm.title = i18n.getMessage(`${TAB_MUTE_UNMUTE}_tooltip`);
      }
    } else if (audible) {
      if (highlighted) {
        elm.title = i18n.getMessage(`${TABS_MUTE}_tooltip`);
      } else {
        elm.title = i18n.getMessage(`${TAB_MUTE}_tooltip`);
      }
    } else {
      elm.title = "";
    }
  }
};

/**
 * set tab audio icon
 * @param {Object} elm - element
 * @param {Object} info - audio info
 * @returns {void}
 */
export const setTabAudioIcon = async (elm, info) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE && elm.localName === "img" &&
      isObjectNotEmpty(info)) {
    const {audible, muted} = info;
    if (muted) {
      elm.alt = i18n.getMessage(`${TAB_MUTE_UNMUTE}`);
      elm.src = URL_AUDIO_MUTED;
    } else if (audible) {
      elm.alt = i18n.getMessage(`${TAB_MUTE}`);
      elm.src = URL_AUDIO_PLAYING;
    } else {
      elm.alt = "";
      elm.src = "";
    }
  }
};

/* close button */
/**
 * set close tab
 * @param {Object} elm - element
 * @param {boolean} highlighted - highlighted
 * @returns {void}
 */
export const setCloseTab = async (elm, highlighted) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE) {
    if (highlighted) {
      elm.title = i18n.getMessage(`${TABS_CLOSE}_tooltip`);
    } else {
      elm.title = i18n.getMessage(`${TAB_CLOSE}_tooltip`);
    }
  }
};

/**
 * close tab
 * @param {!Object} evt - event
 * @returns {?AsyncFunction} - removeTab()
 */
export const closeTab = async evt => {
  const {target} = evt;
  const tabId = getSidebarTabId(target);
  let func;
  if (Number.isInteger(tabId)) {
    func = removeTab(tabId);
  }
  return func || null;
};

/**
 * add tab close click listener
 * @param {Object} elm - element
 * @returns {void}
 */
export const addTabCloseClickListener = async elm => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE) {
    elm.addEventListener("click", evt => closeTab(evt).catch(throwErr));
  }
};

/* contextual identities */
/**
 * set contextual identities icon
 * @param {Object} elm - element
 * @param {Object} info - contextual identities info
 * @returns {void}
 */
export const setContextualIdentitiesIcon = async (elm, info) => {
  if (elm && elm.nodeType === Node.ELEMENT_NODE && elm.localName === "img" &&
      isObjectNotEmpty(info)) {
    const {color, icon, name} = info;
    if (color && icon && name) {
      elm.alt = name;
      elm.src = `../img/${icon}.svg#${color}`;
      elm.parentNode.classList.add(IDENTIFIED);
    }
  }
};
<|endoftext|>


<commit_before>exports.filter = (data) => {
	data.forEach( function(element) {;
		delete element.stockStyleExposure;
		delete element.stockStyleExposure;
		delete element.sectors;
		delete element.marketCapitalizations;
		delete element.regions;
	});
	return Promise.resolve(data);
}<commit_msg>Calculate metrics<commit_after>exports.filter = (data) => {
	data.forEach( function(element) {;
		delete element.stockStyleExposure;
		delete element.stockStyleExposure;
		delete element.sectors;
		delete element.marketCapitalizations;
		delete element.regions;
		element.pePb = (element.pe * element.pb).toFixed(1);
		element.forwardPePb = (element.forwardPe * element.forwardPb).toFixed(1);
	});
	return Promise.resolve(data);
}<|endoftext|>


<commit_before>import styledEngineStyled from '@mui/styled-engine';
import { getDisplayName } from '@mui/utils';
import createTheme from './createTheme';
import styleFunctionSx from './styleFunctionSx';
import propsToClassKey from './propsToClassKey';

function isEmpty(obj) {
  return Object.keys(obj).length === 0;
}

const getStyleOverrides = (name, theme) => {
  if (theme.components && theme.components[name] && theme.components[name].styleOverrides) {
    return theme.components[name].styleOverrides;
  }

  return null;
};

const getVariantStyles = (name, theme) => {
  let variants = [];
  if (theme && theme.components && theme.components[name] && theme.components[name].variants) {
    variants = theme.components[name].variants;
  }

  const variantsStyles = {};

  variants.forEach((definition) => {
    const key = propsToClassKey(definition.props);
    variantsStyles[key] = definition.style;
  });

  return variantsStyles;
};

const variantsResolver = (props, styles, theme, name) => {
  const { ownerState = {} } = props;
  const variantsStyles = [];
  const themeVariants = theme?.components?.[name]?.variants;
  if (themeVariants) {
    themeVariants.forEach((themeVariant) => {
      let isMatch = true;
      Object.keys(themeVariant.props).forEach((key) => {
        if (ownerState[key] !== themeVariant.props[key] && props[key] !== themeVariant.props[key]) {
          isMatch = false;
        }
      });
      if (isMatch) {
        variantsStyles.push(styles[propsToClassKey(themeVariant.props)]);
      }
    });
  }

  return variantsStyles;
};

export function shouldForwardProp(prop) {
  return prop !== 'ownerState' && prop !== 'theme' && prop !== 'sx' && prop !== 'as';
}

export const systemDefaultTheme = createTheme();

const lowercaseFirstLetter = (string) => {
  return string.charAt(0).toLowerCase() + string.slice(1);
};

export default function createStyled(input = {}) {
  const {
    defaultTheme = systemDefaultTheme,
    rootShouldForwardProp = shouldForwardProp,
    slotShouldForwardProp = shouldForwardProp,
  } = input;
  return (tag, inputOptions = {}) => {
    const {
      name: componentName,
      slot: componentSlot,
      skipVariantsResolver: inputSkipVariantsResolver,
      skipSx: inputSkipSx,
      overridesResolver,
      ...options
    } = inputOptions;

    // if skipVariantsResolver option is defined, take the value, otherwise, true for root and false for other slots.
    const skipVariantsResolver =
      inputSkipVariantsResolver !== undefined
        ? inputSkipVariantsResolver
        : (componentSlot && componentSlot !== 'Root') || false;

    const skipSx = inputSkipSx || false;

    let className;

    if (componentName) {
      className = `${componentName}-${lowercaseFirstLetter(componentSlot || 'Root')}`;
    }

    let shouldForwardPropOption = shouldForwardProp;

    if (componentSlot === 'Root') {
      shouldForwardPropOption = rootShouldForwardProp;
    } else if (componentSlot) {
      // any other slot specified
      shouldForwardPropOption = slotShouldForwardProp;
    }

    const defaultStyledResolver = styledEngineStyled(tag, {
      shouldForwardProp: shouldForwardPropOption,
      label: className || componentName || '',
      ...options,
    });
    const muiStyledResolver = (styleArg, ...expressions) => {
      const expressionsWithDefaultTheme = expressions
        ? expressions.map((stylesArg) => {
            return typeof stylesArg === 'function'
              ? ({ theme: themeInput, ...other }) => {
                  return stylesArg({
                    theme: isEmpty(themeInput) ? defaultTheme : themeInput,
                    ...other,
                  });
                }
              : stylesArg;
          })
        : [];

      let transformedStyleArg = styleArg;

      if (componentName && overridesResolver) {
        expressionsWithDefaultTheme.push((props) => {
          const theme = isEmpty(props.theme) ? defaultTheme : props.theme;
          const styleOverrides = getStyleOverrides(componentName, theme);

          if (styleOverrides) {
            return overridesResolver(props, styleOverrides);
          }

          return null;
        });
      }

      if (componentName && !skipVariantsResolver) {
        expressionsWithDefaultTheme.push((props) => {
          const theme = isEmpty(props.theme) ? defaultTheme : props.theme;
          return variantsResolver(
            props,
            getVariantStyles(componentName, theme),
            theme,
            componentName,
          );
        });
      }

      if (!skipSx) {
        expressionsWithDefaultTheme.push((props) => {
          const theme = isEmpty(props.theme) ? defaultTheme : props.theme;
          return styleFunctionSx({ ...props, theme });
        });
      }

      const numOfCustomFnsApplied = expressionsWithDefaultTheme.length - expressions.length;

      if (Array.isArray(styleArg) && numOfCustomFnsApplied > 0) {
        const placeholders = new Array(numOfCustomFnsApplied).fill('');
        // If the type is array, than we need to add placeholders in the template for the overrides, variants and the sx styles.
        transformedStyleArg = [...styleArg, ...placeholders];
        transformedStyleArg.raw = [...styleArg.raw, ...placeholders];
      } else if (typeof styleArg === 'function') {
        // If the type is function, we need to define the default theme.
        transformedStyleArg = ({ theme: themeInput, ...other }) =>
          styleArg({ theme: isEmpty(themeInput) ? defaultTheme : themeInput, ...other });
      }

      const Component = defaultStyledResolver(transformedStyleArg, ...expressionsWithDefaultTheme);

      if (process.env.NODE_ENV !== 'production') {
        let displayName;
        if (componentName) {
          displayName = `${componentName}${componentSlot || ''}`;
        }
        if (displayName === undefined) {
          displayName = `Styled(${getDisplayName(tag)})`;
        }
        Component.displayName = displayName;
      }

      return Component;
    };
    return muiStyledResolver;
  };
}
<commit_msg>[system] Shorten class names in production (#27932)<commit_after>import styledEngineStyled from '@mui/styled-engine';
import { getDisplayName } from '@mui/utils';
import createTheme from './createTheme';
import styleFunctionSx from './styleFunctionSx';
import propsToClassKey from './propsToClassKey';

function isEmpty(obj) {
  return Object.keys(obj).length === 0;
}

const getStyleOverrides = (name, theme) => {
  if (theme.components && theme.components[name] && theme.components[name].styleOverrides) {
    return theme.components[name].styleOverrides;
  }

  return null;
};

const getVariantStyles = (name, theme) => {
  let variants = [];
  if (theme && theme.components && theme.components[name] && theme.components[name].variants) {
    variants = theme.components[name].variants;
  }

  const variantsStyles = {};

  variants.forEach((definition) => {
    const key = propsToClassKey(definition.props);
    variantsStyles[key] = definition.style;
  });

  return variantsStyles;
};

const variantsResolver = (props, styles, theme, name) => {
  const { ownerState = {} } = props;
  const variantsStyles = [];
  const themeVariants = theme?.components?.[name]?.variants;
  if (themeVariants) {
    themeVariants.forEach((themeVariant) => {
      let isMatch = true;
      Object.keys(themeVariant.props).forEach((key) => {
        if (ownerState[key] !== themeVariant.props[key] && props[key] !== themeVariant.props[key]) {
          isMatch = false;
        }
      });
      if (isMatch) {
        variantsStyles.push(styles[propsToClassKey(themeVariant.props)]);
      }
    });
  }

  return variantsStyles;
};

export function shouldForwardProp(prop) {
  return prop !== 'ownerState' && prop !== 'theme' && prop !== 'sx' && prop !== 'as';
}

export const systemDefaultTheme = createTheme();

const lowercaseFirstLetter = (string) => {
  return string.charAt(0).toLowerCase() + string.slice(1);
};

export default function createStyled(input = {}) {
  const {
    defaultTheme = systemDefaultTheme,
    rootShouldForwardProp = shouldForwardProp,
    slotShouldForwardProp = shouldForwardProp,
  } = input;
  return (tag, inputOptions = {}) => {
    const {
      name: componentName,
      slot: componentSlot,
      skipVariantsResolver: inputSkipVariantsResolver,
      skipSx: inputSkipSx,
      overridesResolver,
      ...options
    } = inputOptions;

    // if skipVariantsResolver option is defined, take the value, otherwise, true for root and false for other slots.
    const skipVariantsResolver =
      inputSkipVariantsResolver !== undefined
        ? inputSkipVariantsResolver
        : (componentSlot && componentSlot !== 'Root') || false;

    const skipSx = inputSkipSx || false;

    let label;

    if (process.env.NODE_ENV !== 'production') {
      if (componentName) {
        label = `${componentName}-${lowercaseFirstLetter(componentSlot || 'Root')}`;
      }
    }

    let shouldForwardPropOption = shouldForwardProp;

    if (componentSlot === 'Root') {
      shouldForwardPropOption = rootShouldForwardProp;
    } else if (componentSlot) {
      // any other slot specified
      shouldForwardPropOption = slotShouldForwardProp;
    }

    const defaultStyledResolver = styledEngineStyled(tag, {
      shouldForwardProp: shouldForwardPropOption,
      label,
      ...options,
    });
    const muiStyledResolver = (styleArg, ...expressions) => {
      const expressionsWithDefaultTheme = expressions
        ? expressions.map((stylesArg) => {
            return typeof stylesArg === 'function'
              ? ({ theme: themeInput, ...other }) => {
                  return stylesArg({
                    theme: isEmpty(themeInput) ? defaultTheme : themeInput,
                    ...other,
                  });
                }
              : stylesArg;
          })
        : [];

      let transformedStyleArg = styleArg;

      if (componentName && overridesResolver) {
        expressionsWithDefaultTheme.push((props) => {
          const theme = isEmpty(props.theme) ? defaultTheme : props.theme;
          const styleOverrides = getStyleOverrides(componentName, theme);

          if (styleOverrides) {
            return overridesResolver(props, styleOverrides);
          }

          return null;
        });
      }

      if (componentName && !skipVariantsResolver) {
        expressionsWithDefaultTheme.push((props) => {
          const theme = isEmpty(props.theme) ? defaultTheme : props.theme;
          return variantsResolver(
            props,
            getVariantStyles(componentName, theme),
            theme,
            componentName,
          );
        });
      }

      if (!skipSx) {
        expressionsWithDefaultTheme.push((props) => {
          const theme = isEmpty(props.theme) ? defaultTheme : props.theme;
          return styleFunctionSx({ ...props, theme });
        });
      }

      const numOfCustomFnsApplied = expressionsWithDefaultTheme.length - expressions.length;

      if (Array.isArray(styleArg) && numOfCustomFnsApplied > 0) {
        const placeholders = new Array(numOfCustomFnsApplied).fill('');
        // If the type is array, than we need to add placeholders in the template for the overrides, variants and the sx styles.
        transformedStyleArg = [...styleArg, ...placeholders];
        transformedStyleArg.raw = [...styleArg.raw, ...placeholders];
      } else if (typeof styleArg === 'function') {
        // If the type is function, we need to define the default theme.
        transformedStyleArg = ({ theme: themeInput, ...other }) =>
          styleArg({ theme: isEmpty(themeInput) ? defaultTheme : themeInput, ...other });
      }

      const Component = defaultStyledResolver(transformedStyleArg, ...expressionsWithDefaultTheme);

      if (process.env.NODE_ENV !== 'production') {
        let displayName;
        if (componentName) {
          displayName = `${componentName}${componentSlot || ''}`;
        }
        if (displayName === undefined) {
          displayName = `Styled(${getDisplayName(tag)})`;
        }
        Component.displayName = displayName;
      }

      return Component;
    };
    return muiStyledResolver;
  };
}
<|endoftext|>


<commit_before>'use strict';

require('./globals.js');

var path = require('path');
var util = require('util');
var chalk = require('chalk');
var nconf = require('nconf');
var moment = require('moment');
var defaults = require('./defaults.json');
var pkg = require_cwd('package.json', __dirname);

nconf.argv();
nconf.env();
nconf.defaults(defaults);

var env = nconf.get('NODE_ENV');
var loading = util.format('%s - Loading configuration for %s...', moment().format(), chalk.magenta(env));

process.stdout.write(loading);

file('user');
file(env); // environment-specific configuration

nconf.set('BUILD_VERSION', pkg.version);

console.log('done');

function file (name) {
    var filename = util.format('private/%s.json', name);
    var filepath = path.join(__dirname, filename);

    nconf.file(name, filepath);
}
<commit_msg>removed chalk from envindex<commit_after>'use strict';

require('./globals.js');

var path = require('path');
var util = require('util');
var nconf = require('nconf');
var moment = require('moment');
var defaults = require('./defaults.json');
var pkg = require_cwd('package.json', __dirname);

nconf.argv();
nconf.env();
nconf.defaults(defaults);

var env = nconf.get('NODE_ENV');
var loading = util.format('%s - Loading configuration for %s...', moment().format(), env);

process.stdout.write(loading);

file('user');
file(env); // environment-specific configuration

nconf.set('BUILD_VERSION', pkg.version);

console.log('done');

function file (name) {
    var filename = util.format('private/%s.json', name);
    var filepath = path.join(__dirname, filename);

    nconf.file(name, filepath);
}
<|endoftext|>


<commit_before>var creep_miner = {

    /** @param {Creep} creep **/
    run: function(creep) {
        if (creep.ticksToLive <= creep.memory.deathWarn && creep.memory.priority != 'minerNearDeath') {
            creep.memory.priority = 'minerNearDeath';
            creep.memory.jobSpecific = creep.memory.jobSpecific + 'NearDeath';
        }

        if (Game.flags[creep.room.name + creep.memory.jobSpecific] && !creep.memory.atSpot) {
            creep.memory.ignoreTravel = true;
            if (creep.pos.x != Game.flags[creep.room.name + creep.memory.jobSpecific].pos.x || creep.pos.y != Game.flags[creep.room.name + creep.memory.jobSpecific].pos.y) {
                creep.travelTo(Game.flags[creep.room.name + creep.memory.jobSpecific]);
            } else {
                creep.memory.atSpot = true;
            }
        }
        //Creep will immediately harvest and store mined materials
        let mineTarget = Game.getObjectById(creep.memory.mineSource);
        if (mineTarget) {
            if (creep.harvest(mineTarget) == ERR_NOT_IN_RANGE && !creep.memory.ignoreTravel) {
                creep.travelTo(mineTarget, {
                    maxRooms: 1
                });
            }

            if (!creep.memory.travelDistance && creep.memory._trav && creep.memory._trav.path) {
                creep.memory.travelDistance = creep.memory._trav.path.length;
                creep.memory.deathWarn = (creep.memory.travelDistance + _.size(creep.body) * 3) + 15;
            }

            if (creep.carry.energy >= 40) {
                let storageTarget = Game.getObjectById(creep.memory.linkSource);
                if (creep.memory.jobSpecific == 'upgradeMiner') {
                    let storageTarget2 = undefined;
                    if (creep.memory.linkSource2) {
                        storageTarget2 = Game.getObjectById(creep.memory.linkSource2);
                    }
                    if (storageTarget2 && storageTarget.energy == storageTarget.energyCapacity) {
                        if (creep.transfer(storageTarget2, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE && !creep.memory.ignoreTravel) {
                            creep.travelTo(storageTarget2);
                        }
                    } else {
                        if (creep.transfer(storageTarget, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE && !creep.memory.ignoreTravel) {
                            creep.travelTo(storageTarget);
                        }
                    }
                } else {
                    if (creep.transfer(storageTarget, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE && !creep.memory.ignoreTravel) {
                        creep.travelTo(storageTarget);
                    }
                }
            }

        }
    }
};

module.exports = creep_miner;<commit_msg>Strange miner bug<commit_after>var creep_miner = {

    /** @param {Creep} creep **/
    run: function(creep) {
        if (creep.ticksToLive <= creep.memory.deathWarn && creep.memory.priority != 'minerNearDeath') {
            creep.memory.priority = 'minerNearDeath';
            creep.memory.jobSpecific = creep.memory.jobSpecific + 'NearDeath';
        }

        if (Game.flags[creep.room.name + creep.memory.jobSpecific] && !creep.memory.atSpot) {
            creep.memory.ignoreTravel = true;
            if (creep.pos.x != Game.flags[creep.room.name + creep.memory.jobSpecific].pos.x || creep.pos.y != Game.flags[creep.room.name + creep.memory.jobSpecific].pos.y) {
                creep.travelTo(Game.flags[creep.room.name + creep.memory.jobSpecific], {
                    maxRooms: 1
                });
            } else {
                creep.memory.atSpot = true;
            }
        }
        //Creep will immediately harvest and store mined materials
        let mineTarget = Game.getObjectById(creep.memory.mineSource);
        if (mineTarget) {
            if (creep.harvest(mineTarget) == ERR_NOT_IN_RANGE && !creep.memory.ignoreTravel) {
                creep.travelTo(mineTarget, {
                    maxRooms: 1
                });
            }

            if (!creep.memory.travelDistance && creep.memory._trav && creep.memory._trav.path) {
                creep.memory.travelDistance = creep.memory._trav.path.length;
                creep.memory.deathWarn = (creep.memory.travelDistance + _.size(creep.body) * 3) + 15;
            }

            if (creep.carry.energy >= 40) {
                let storageTarget = Game.getObjectById(creep.memory.linkSource);
                if (creep.memory.jobSpecific == 'upgradeMiner') {
                    let storageTarget2 = undefined;
                    if (creep.memory.linkSource2) {
                        storageTarget2 = Game.getObjectById(creep.memory.linkSource2);
                    }
                    if (storageTarget2 && storageTarget.energy == storageTarget.energyCapacity) {
                        if (creep.transfer(storageTarget2, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE && !creep.memory.ignoreTravel) {
                            creep.travelTo(storageTarget2);
                        }
                    } else {
                        if (creep.transfer(storageTarget, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE && !creep.memory.ignoreTravel) {
                            creep.travelTo(storageTarget);
                        }
                    }
                } else {
                    if (creep.transfer(storageTarget, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE && !creep.memory.ignoreTravel) {
                        creep.travelTo(storageTarget);
                    }
                }
            }

        }
    }
};

module.exports = creep_miner;<|endoftext|>


<commit_before>import { DeviceEventEmitter } from 'react-native'
import TimerMixin from 'react-timer-mixin'

const _KAM_DEFAULT_TAB_BAR_HEIGHT = 49

const KeyboardAwareMixin = {
  mixins: [TimerMixin],

  setViewIsInsideTabBar: function (viewIsInsideTabBar) {
    this.viewIsInsideTabBar = viewIsInsideTabBar
    this.setState({keyboardSpace: _KAM_DEFAULT_TAB_BAR_HEIGHT})
  },

  getInitialState: function (props) {
    this.viewIsInsideTabBar = false
    return {
      keyboardSpace: 0,
    }
  },

  // Keyboard actions
  updateKeyboardSpace: function (frames) {
    const keyboardSpace = (this.props.viewIsInsideTabBar) ? frames.endCoordinates.height - _KAM_DEFAULT_TAB_BAR_HEIGHT : frames.endCoordinates.height
    this.setState({
      keyboardSpace: keyboardSpace,
    })
  },

  resetKeyboardSpace: function () {
    const keyboardSpace = (this.props.viewIsInsideTabBar) ? _KAM_DEFAULT_TAB_BAR_HEIGHT : 0
    this.setState({
      keyboardSpace: keyboardSpace,
    })
  },

  componentDidMount: function () {
    // Keyboard events
    DeviceEventEmitter.addListener('keyboardWillShow', this.updateKeyboardSpace)
    DeviceEventEmitter.addListener('keyboardWillHide', this.resetKeyboardSpace)
  },

  componentWillUnmount: function () {
    // TODO: figure out if removeAllListeners is the right thing to do
    DeviceEventEmitter.removeAllListeners('keyboardWillShow')
    DeviceEventEmitter.removeAllListeners('keyboardWillHide')
  },

  /**
   * @param extraHeight: takes an extra height in consideration.
   */
  scrollToFocusedInput: function (event, reactNode, extraHeight = _KAM_DEFAULT_TAB_BAR_HEIGHT) {
    const scrollView = this.refs.keyboardView.getScrollResponder()
    this.setTimeout(() => {
      scrollView.scrollResponderScrollNativeHandleToKeyboard(
        reactNode, extraHeight, true
      )
    }, 220)
  },
}

export default KeyboardAwareMixin
<commit_msg>closes #7 Solved a remove listener bug that caused all listeners to be removed instead of the current scroll view<commit_after>import { DeviceEventEmitter } from 'react-native'
import TimerMixin from 'react-timer-mixin'

const _KAM_DEFAULT_TAB_BAR_HEIGHT = 49

const KeyboardAwareMixin = {
  mixins: [TimerMixin],

  setViewIsInsideTabBar: function (viewIsInsideTabBar) {
    this.viewIsInsideTabBar = viewIsInsideTabBar
    this.setState({keyboardSpace: _KAM_DEFAULT_TAB_BAR_HEIGHT})
  },

  getInitialState: function (props) {
    this.viewIsInsideTabBar = false
    this.keyboardWillShowEvent = undefined
    this.keyboardWillHideEvent = undefined
    return {
      keyboardSpace: 0,
    }
  },

  // Keyboard actions
  updateKeyboardSpace: function (frames) {
    const keyboardSpace = (this.props.viewIsInsideTabBar) ? frames.endCoordinates.height - _KAM_DEFAULT_TAB_BAR_HEIGHT : frames.endCoordinates.height
    this.setState({
      keyboardSpace: keyboardSpace,
    })
  },

  resetKeyboardSpace: function () {
    const keyboardSpace = (this.props.viewIsInsideTabBar) ? _KAM_DEFAULT_TAB_BAR_HEIGHT : 0
    this.setState({
      keyboardSpace: keyboardSpace,
    })
  },

  componentDidMount: function () {
    // Keyboard events
    this.keyboardWillShowEvent = DeviceEventEmitter.addListener('keyboardWillShow', this.updateKeyboardSpace)
    this.keyboardWillHideEvent = DeviceEventEmitter.addListener('keyboardWillHide', this.resetKeyboardSpace)
  },

  componentWillUnmount: function () {
    this.keyboardWillShowEvent.remove()
    this.keyboardWillHideEvent.remove()
  },

  /**
   * @param extraHeight: takes an extra height in consideration.
   */
  scrollToFocusedInput: function (event, reactNode, extraHeight = _KAM_DEFAULT_TAB_BAR_HEIGHT) {
    const scrollView = this.refs.keyboardView.getScrollResponder()
    this.setTimeout(() => {
      scrollView.scrollResponderScrollNativeHandleToKeyboard(
        reactNode, extraHeight, true
      )
    }, 220)
  },
}

export default KeyboardAwareMixin
<|endoftext|>


<commit_before>/**
 * @module Math
 * @for Calculation
 * @requires core
 */
define(function (require) {

  'use strict';

  var p5 = require('core');

  /**
   * Calculates the absolute value (magnitude) of a number. The absolute value of a number is always positive.
   *
   * @method abs
   * @param {Number} n number to compute
   * @return {Number} val absolute value of given number
   */
  p5.prototype.abs = Math.abs;

  /**
   * Calculates the closest int value that is greater than or equal to the value of the parameter. For example, ceil(9.03) returns the value 10.
   *
   * @method ceil
   * @param {Number} n number to round up
   * @return {Number} val rounded up number
   */
  p5.prototype.ceil = Math.ceil;

  /**
   * Constrains a value to not exceed a maximum and minimum value.
   *
   * @method constrain
   * @param {Number} amt number to constrain
   * @param {Number} low minimum limit
   * @param {Number} high maximum limit
   * @return {Number} val constrained number
   */
  p5.prototype.constrain = function(amt, low, high) {
    return this.max(this.min(amt, high), low);
  };

  p5.prototype.dist = function(x1, y1, x2, y2) {
    var xs = x2-x1;
    var ys = y2-y1;
    return Math.sqrt( xs*xs + ys*ys );
  };

  p5.prototype.exp = Math.exp;

  p5.prototype.floor = Math.floor;

  p5.prototype.lerp = function(start, stop, amt) {
    return amt*(stop-start)+start;
  };

  p5.prototype.log = Math.log;

  p5.prototype.mag = function(x, y) {
    return Math.sqrt(x*x+y*y);
  };

  p5.prototype.map = function(n, start1, stop1, start2, stop2) {
    return ((n-start1)/(stop1-start1))*(stop2-start2)+start2;
  };

  p5.prototype.max = function() {
    if (arguments[0] instanceof Array) {
      return Math.max.apply(null,arguments[0]);
    } else {
      return Math.max.apply(null,arguments);
    }
  };

  p5.prototype.min = function() {
    if (arguments[0] instanceof Array) {
      return Math.min.apply(null,arguments[0]);
    } else {
      return Math.min.apply(null,arguments);
    }
  };

  p5.prototype.norm = function(n, start, stop) { return this.map(n, start, stop, 0, 1); };

  p5.prototype.pow = Math.pow;

  p5.prototype.round = Math.round;

  p5.prototype.sq = function(n) { return n*n; };

  p5.prototype.sqrt = Math.sqrt;

  return p5;

});
<commit_msg>adding calc docs<commit_after>/**
 * @module Math
 * @for Calculation
 * @requires core
 */
define(function (require) {

  'use strict';

  var p5 = require('core');

  /**
   * Calculates the absolute value (magnitude) of a number. Maps to Math.abs(). The absolute value of a number is always positive.
   *
   * @method abs()
   * @param {Number} n number to compute
   * @return {Number} val absolute value of given number
   */
  p5.prototype.abs = Math.abs;

  /**
   * Calculates the closest int value that is greater than or equal to the value of the parameter. Maps to Math.ceil(). For example, ceil(9.03) returns the value 10.
   *
   * @method ceil()
   * @param {Number} n number to round up
   * @return {Number} val rounded up number
   */
  p5.prototype.ceil = Math.ceil;

  /**
   * Constrains a value to not exceed a maximum and minimum value.
   *
   * @method constrain()
   * @param {Number} amt number to constrain
   * @param {Number} low minimum limit
   * @param {Number} high maximum limit
   * @return {Number} val constrained number
   */
  p5.prototype.constrain = function(amt, low, high) {
    return this.max(this.min(amt, high), low);
  };

  /**
   * Calculates the distance between two points.
   *
   * @method dist()
   * @param {Number} x1 x-coordinate of the first point
   * @param {Number} y1 y-coordinate of the first point
   * @param {Number} x2 x-coordinate of the second point
   * @param {Number} y2 y-coordinate of the second point
   * @return {Number} distance distance between the two points
   */
  p5.prototype.dist = function(x1, y1, x2, y2) {
    var xs = x2-x1;
    var ys = y2-y1;
    return Math.sqrt( xs*xs + ys*ys );
  };

  /**
   * Returns Euler's number e (2.71828...) raised to the power of the n parameter. Maps to Math.exp().
   *
   * @method exp()
   * @param {Number} n exponent to raise
   * @return {Number} val e^n
   */
  p5.prototype.exp = Math.exp;

  /**
   * Calculates the closest int value that is less than or equal to the value of the parameter. Maps to Math.floor().
   *
   * @method floor()
   * @param {Number} n number to round down
   * @return {Number} val rounded down number
   */
  p5.prototype.floor = Math.floor;

  /**
   * Calculates a number between two numbers at a specific increment. The amt parameter is the amount to interpolate between the two values where 0.0 equal to the first point, 0.1 is very near the first point, 0.5 is half-way in between, etc. The lerp function is convenient for creating motion along a straight path and for drawing dotted lines.
   *
   * @method lerp()
   * @param {Number} start first value
   * @param {Number} stop second value
   * @param {Number} amt number between 0.0 and 1.0
   * @return {Number} val lerped value
   */
  p5.prototype.lerp = function(start, stop, amt) {
    return amt*(stop-start)+start;
  };

  /**
   * Calculates the natural logarithm (the base-e logarithm) of a number. This function expects the n parameter to be a value greater than 0.0. Maps to Math.log().
   *
   * @method log()
   * @param {Number} n number greater than 0
   * @return {Number} val natural logarithm of n
   */
  p5.prototype.log = Math.log;

  /**
   * Calculates the magnitude (or length) of a vector. A vector is a direction in space commonly used in computer graphics and linear algebra. Because it has no "start" position, the magnitude of a vector can be thought of as the distance from the coordinate 0,0 to its x,y value. Therefore, mag() is a shortcut for writing dist(0, 0, x, y).
   *
   * @method mag()
   * @param {Number} a first value
   * @param {Number} b second value
   * @return {Number} val magnitude of vector from (0,0) to (a,b)
   */
  p5.prototype.mag = function(x, y) {
    return Math.sqrt(x*x+y*y);
  };

  /**
   * Re-maps a number from one range to another.
   * In the first example above, the number 25 is converted from a value in the range of 0 to 100 into a value that ranges from the left edge of the window (0) to the right edge (width).
   *
   * @method map()
   * @param {Number} value the incoming value to be converted
   * @param {Number} start1 lower bound of the value's current range
   * @param {Number} stop1 upper bound of the value's current range
   * @param {Number} start2 lower bound of the value's target range
   * @param {Number} stop upper bound of the value's target range
   * @return {Number} val remapped number
   * @example

createCanvas(200, 200);
var value = 25;
var m = map(value, 0, 100, 0, width);
ellipse(m, 200, 10, 10);

function setup() {
  createCanvs(200, 200);
  noStroke();
}
function draw() {
  background(204);
  var x1 = map(mouseX, 0, width, 50, 150);
  ellipse(x1, 75, 50, 50);
  var x2 = map(mouseX, 0, width, 0, 200);
  ellipse(x2, 125, 50, 50);
}

   */
  p5.prototype.map = function(n, start1, stop1, start2, stop2) {
    return ((n-start1)/(stop1-start1))*(stop2-start2)+start2;
  };

  /**
   * Determines the largest value in a sequence of numbers, and then returns that value. max() accepts any number of Number parameters, or an Array of any length.
   *
   * @method max()
   * @param {Number|Array} n0 Numbers to compare
   * @return {Number} val maximum Number
   */
  p5.prototype.max = function() {
    if (arguments[0] instanceof Array) {
      return Math.max.apply(null,arguments[0]);
    } else {
      return Math.max.apply(null,arguments);
    }
  };

  /**
   * Determines the smallest value in a sequence of numbers, and then returns that value. min() accepts any number of Number parameters, or an Array of any length.
   *
   * @method min()
   * @param {Number|Array} n0 Numbers to compare
   * @return {Number} val minimum Number
   */
  p5.prototype.min = function() {
    if (arguments[0] instanceof Array) {
      return Math.min.apply(null,arguments[0]);
    } else {
      return Math.min.apply(null,arguments);
    }
  };

  /**
   * Normalizes a number from another range into a value between 0 and 1. Identical to map(value, low, high, 0, 1).
   * Numbers outside of the range are not clamped to 0 and 1, because out-of-range values are often intentional and useful. (See the second example above.)
   *
   * @method norm()
   * @param {Number} value incoming value to be normalized
   * @param {Number} start lower bound of the value's current range
   * @param {Number} stop upper bound of the value's current range
   * @return {Number} result normalized number
   */
  p5.prototype.norm = function(n, start, stop) { return this.map(n, start, stop, 0, 1); };

  /**
   * Facilitates exponential expressions. The pow() function is an efficient way of multiplying numbers by themselves (or their reciprocals) in large quantities. For example, pow(3, 5) is equivalent to the expression 3*3*3*3*3 and pow(3, -5) is equivalent to 1 / 3*3*3*3*3. Maps to Math.pow().
   *
   * @method pow()
   * @param {Number} n base of the exponential expression
   * @param {Number} e power by which to raise the base
   * @return {Number} value n^e
   */
  p5.prototype.pow = Math.pow;

  /**
   * Calculates the integer closest to the n parameter. For example, round(133.8) returns the value 134. Maps to Math.round().
   * @method constrain()
   * @param {Number} n number to round
   * @return {Number} val rounded number
   */
  p5.prototype.round = Math.round;

  /**
   * Squares a number (multiplies a number by itself). The result is always a positive number, as multiplying two negative numbers always yields a positive result. For example, -1 * -1 = 1.
   *
   * @method sq()
   * @param {Number} n number to square
   * @return {Number} val squared number
   */
  p5.prototype.sq = function(n) { return n*n; };

  /**
   * Calculates the square root of a number. The square root of a number is always positive, even though there may be a valid negative root. The square root s of number a is such that s*s = a. It is the opposite of squaring. Maps to Math.sqrt().
   *
   * @method sqrt()
   * @param {Number} n non-negative number to square root
   * @return {Number} val square root of number
   */
  p5.prototype.sqrt = Math.sqrt;

  return p5;

});
<|endoftext|>


<commit_before>'use strict';

const chalk = require('chalk');
const port = (process.env.PORT || 4545);

let requireApp = new Promise(function(resolve, reject) {
	let app = require('./app');
	resolve(app);
});

// Start the server
requireApp
	.then(function(app) {
		app.listen(port, function() {
			console.log('The server is listening on port', chalk.green.bold(port), 'and loves you very much.');
			console.log('Make sure you are running ' + chalk.white.bgBlack(' gulp ') + ' in another tab!');
		});
	})
	.catch(function(err) {
		console.log('Problem starting up!', chalk.red(err.message));
		console.log('I\'m out!');
		process.kill(1);
	});<commit_msg>Update nodb version.<commit_after>'use strict';

const chalk = require('chalk');
const port = (process.env.PORT || 4545);

let requireApp = new Promise(function(resolve, reject) {
	let app = require('./app');
	resolve(app);
});

// Start the server
requireApp
	.then(function(app) {
		app.listen(port, function() {
			console.log('The server is listening on port', chalk.green.bold(port), 'and loves you very much.');
			console.log('Make sure you are running ' + chalk.white.bgBlack(' npm run watch ') + ' in another tab!');
		});
	})
	.catch(function(err) {
		console.log('Problem starting up!', chalk.red(err.message));
		console.log('I\'m out!');
		process.kill(1);
	});<|endoftext|>


<commit_before>"use strict";

// Local tweet test override.
var canTweetFromLocal = false;

// Load libraries.
var _ = require('underscore');
var wordfilter = require('wordfilter');
var SC = require('node-soundcloud');
var Twit = require('twit');

// Are we on production? Check if an important environment variable exists.
function isProduction () {
  return (typeof(process.env.TWITTER_CONSUMER_KEY) !== 'undefined');
}

// Use environment variables if we're on production, config files if we're local.
if (isProduction()) {
  var yandexKey = process.env.YANDEX_KEY;

  var twitter = new Twit({
    consumer_key: process.env.TWITTER_CONSUMER_KEY,
    consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
    access_token: process.env.TWITTER_ACCESS_TOKEN,
    access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET
  });

  SC.init({
    id:     process.env.SOUNDCLOUD_CLIENT_ID,
    secret: process.env.SOUNDCLOUD_SECRET
  });
}
else {
  var yandexConfig = require('./config/yandex-config.js'),
      yandexKey    = yandexConfig.key;

  var twitter = new Twit(require('./config/twitter-config.js'));

  SC.init(require('./config/soundcloud-config.js'));
}

// Load Yandex Translation API library.
var translate = require('yandex-translate')(yandexKey);

// Execute once upon initialization.
makeAndPostTweet();

// The main process. Get a useable comment and tweet it or try again.
function makeAndPostTweet () {

  getComment()
    .then(function (results) {
      postTweet(results);
    })
    .catch(function (error) {
      console.log('ERROR:', error);
      makeAndPostTweet();
    });

}

// Get a random comment and see if it's usable.
function getComment () {

  return new Promise (function (resolve, reject) {

    console.log('\n---\n');

    // Pick a random comment. The API doesn't provide for this, but SoundCloud
    // comment IDs are sequential! There are a lot of missing comments (deleted
    // spam, etc.), but this has about a 40-50% success rate at finding an
    // actual comment, which is pretty good!
    var randomCommentID = String(_.random(100000000, 300000000));

    // Query the SoundCloud API and filter the results.
    SC.get('/comments/' + randomCommentID, function(error, comment) {

      // console.log('\n\nFULL API RESPONSE:\n\n', comment)

      console.log('LOOKING FOR A COMMENT AT ID #' + randomCommentID + '…');

      if (typeof(error) !== 'undefined') {
        reject('Comment does not exist at this ID anymore.');
      }
      else {
        var comment = comment.body.trim();

        console.log('FOUND A COMMENT:', comment);

        console.log('ANALYZING: Checking if too short…');

        if (comment.length < 1) {
          reject('Comment is too short.');
          return;
        }

        console.log('\tOK!');

        console.log('ANALYZING: Checking if too long…');

        if (comment.length > 141) {
          reject('Comment is too long');
          return;
        }

        console.log('\tOK!');

        console.log('ANALYZING: Checking for bad words…');

        if (wordfilter.blacklisted(comment)) {
          reject('Comment is a reply, contains a bad word, or looks like spam.');
          return;
        }

        console.log('\tOK!');

        console.log('ANALYZING: Checking if is English…');

        translate.detect(comment, function (error, result) {
          if (result.lang === 'en') {
            console.log('\tOK!');

            console.log('SUCCESS: All checks passed! Comment is useable!');

            resolve(comment);
          }
          else if (typeof(error) !== 'undefined') {
            reject(error);
          }
          else {
            reject('Comment is not in English.')
          }
        })

      }

    });
  });
}

function postTweet (tweet) {

  if (typeof(tweet) !== 'undefined') {
    console.log('NOW TWEETING:', tweet);

    if (isProduction() || canTweetFromLocal) {
      twitter.post('statuses/update', { status: tweet }, function (error) {
        if (error) {
          console.log('ERROR POSTING TWEET:', error);
        }
      });
    }
  }
  else {
    console.log('ERROR: No comment was fetched!');
  }

}

// Tweet on a regular schedule. 8 times a day means every 3 hours. Note that
// Because Heroku cycles dynos once per day, the bot's schedule will not be
// regular: https://devcenter.heroku.com/articles/how-heroku-works#dyno-manager
if (isProduction()) {
  var timesToTweetPerDay = 8;

  setInterval(function () {
    try {
      makeAndPostTweet();
    }
    catch (error) {
      console.log('PROCESS UNSUCCESSFUL!', error);
    }
  }, (1000 * 60 * 60 * 24) / timesToTweetPerDay);
}

///

// Additional filters.
wordfilter.addWords([

  // To get a better set of comments, I'm filtering out a lot of things.
  // The lists below are used in addition to the default set:
  // https://github.com/dariusk/wordfilter/blob/master/lib/badwords.json

  // Promotion.
  'follow',
  'listen to my',
  'check out',
  'check my',
  'subscribe',
  'channel',
  'my cloud',
  'add me',
  'profile',

  'soundcloud',
  'facebook',
  'twitter',
  'youtube',
  'instagram',
  'blog',

  'free',
  'download',

  // Fake comments.
  'repost',
  'posted',
  'full support',
  'fully support',

  // Traditional spam.
  'sex',
  'cam',
  'dollars',
  'money',
  'fans',
  'plays',
  'get play',
  'get fan',

  // URLs.
  'http',
  'www',
  '.co',
  '.net',

  // Replies, SoundCloud links, tags, etc.
  'user-',
  '\@',
  '\n',
  '_',
  '#',

  // A few curses and bad words.
  'fuck',
  'rape',
  'raping',
  'gay'

]);
<commit_msg>Add spam term.<commit_after>"use strict";

// Local tweet test override.
var canTweetFromLocal = false;

// Load libraries.
var _ = require('underscore');
var wordfilter = require('wordfilter');
var SC = require('node-soundcloud');
var Twit = require('twit');

// Are we on production? Check if an important environment variable exists.
function isProduction () {
  return (typeof(process.env.TWITTER_CONSUMER_KEY) !== 'undefined');
}

// Use environment variables if we're on production, config files if we're local.
if (isProduction()) {
  var yandexKey = process.env.YANDEX_KEY;

  var twitter = new Twit({
    consumer_key: process.env.TWITTER_CONSUMER_KEY,
    consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
    access_token: process.env.TWITTER_ACCESS_TOKEN,
    access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET
  });

  SC.init({
    id:     process.env.SOUNDCLOUD_CLIENT_ID,
    secret: process.env.SOUNDCLOUD_SECRET
  });
}
else {
  var yandexConfig = require('./config/yandex-config.js'),
      yandexKey    = yandexConfig.key;

  var twitter = new Twit(require('./config/twitter-config.js'));

  SC.init(require('./config/soundcloud-config.js'));
}

// Load Yandex Translation API library.
var translate = require('yandex-translate')(yandexKey);

// Execute once upon initialization.
makeAndPostTweet();

// The main process. Get a useable comment and tweet it or try again.
function makeAndPostTweet () {

  getComment()
    .then(function (results) {
      postTweet(results);
    })
    .catch(function (error) {
      console.log('ERROR:', error);
      makeAndPostTweet();
    });

}

// Get a random comment and see if it's usable.
function getComment () {

  return new Promise (function (resolve, reject) {

    console.log('\n---\n');

    // Pick a random comment. The API doesn't provide for this, but SoundCloud
    // comment IDs are sequential! There are a lot of missing comments (deleted
    // spam, etc.), but this has about a 40-50% success rate at finding an
    // actual comment, which is pretty good!
    var randomCommentID = String(_.random(100000000, 300000000));

    // Query the SoundCloud API and filter the results.
    SC.get('/comments/' + randomCommentID, function(error, comment) {

      // console.log('\n\nFULL API RESPONSE:\n\n', comment)

      console.log('LOOKING FOR A COMMENT AT ID #' + randomCommentID + '…');

      if (typeof(error) !== 'undefined') {
        reject('Comment does not exist at this ID anymore.');
      }
      else {
        var comment = comment.body.trim();

        console.log('FOUND A COMMENT:', comment);

        console.log('ANALYZING: Checking if too short…');

        if (comment.length < 1) {
          reject('Comment is too short.');
          return;
        }

        console.log('\tOK!');

        console.log('ANALYZING: Checking if too long…');

        if (comment.length > 141) {
          reject('Comment is too long');
          return;
        }

        console.log('\tOK!');

        console.log('ANALYZING: Checking for bad words…');

        if (wordfilter.blacklisted(comment)) {
          reject('Comment is a reply, contains a bad word, or looks like spam.');
          return;
        }

        console.log('\tOK!');

        console.log('ANALYZING: Checking if is English…');

        translate.detect(comment, function (error, result) {
          if (result.lang === 'en') {
            console.log('\tOK!');

            console.log('SUCCESS: All checks passed! Comment is useable!');

            resolve(comment);
          }
          else if (typeof(error) !== 'undefined') {
            reject(error);
          }
          else {
            reject('Comment is not in English.')
          }
        })

      }

    });
  });
}

function postTweet (tweet) {

  if (typeof(tweet) !== 'undefined') {
    console.log('NOW TWEETING:', tweet);

    if (isProduction() || canTweetFromLocal) {
      twitter.post('statuses/update', { status: tweet }, function (error) {
        if (error) {
          console.log('ERROR POSTING TWEET:', error);
        }
      });
    }
  }
  else {
    console.log('ERROR: No comment was fetched!');
  }

}

// Tweet on a regular schedule. 8 times a day means every 3 hours. Note that
// Because Heroku cycles dynos once per day, the bot's schedule will not be
// regular: https://devcenter.heroku.com/articles/how-heroku-works#dyno-manager
if (isProduction()) {
  var timesToTweetPerDay = 8;

  setInterval(function () {
    try {
      makeAndPostTweet();
    }
    catch (error) {
      console.log('PROCESS UNSUCCESSFUL!', error);
    }
  }, (1000 * 60 * 60 * 24) / timesToTweetPerDay);
}

///

// Additional filters.
wordfilter.addWords([

  // To get a better set of comments, I'm filtering out a lot of things.
  // The lists below are used in addition to the default set:
  // https://github.com/dariusk/wordfilter/blob/master/lib/badwords.json

  // Promotion.
  'follow',
  'listen to my',
  'check out',
  'check my',
  'subscribe',
  'channel',
  'my cloud',
  'add me',
  'profile',
  'premiere',

  'soundcloud',
  'facebook',
  'twitter',
  'youtube',
  'instagram',
  'blog',

  'free',
  'download',

  // Fake comments.
  'repost',
  'posted',
  'full support',
  'fully support',

  // Traditional spam.
  'sex',
  'cam',
  'dollars',
  'money',
  'fans',
  'plays',
  'get play',
  'get fan',

  // URLs.
  'http',
  'www',
  '.co',
  '.net',

  // Replies, SoundCloud links, tags, etc.
  'user-',
  '\@',
  '\n',
  '_',
  '#',

  // A few curses and bad words.
  'fuck',
  'rape',
  'raping',
  'gay'

]);
<|endoftext|>


<commit_before>/*
 * grunt-require
 * https://github.com/asciidisco/grunt-requirejs
 *
 * Copyright (c) 2012 asciidisco
 * Licensed under the MIT license.
 */

exports.init = function(grunt) {
  'use strict';

  var fs = require('fs');
  var exports = {};

  // privates
  var isDefaultVersion = true;
  var requirejs = null;

  // Returns a requirejs instance
  exports.getRequirejs = function(config) {
    var defaultRequire = require('requirejs');

    // check if we should load a custom requirejs version
    if (config.rjs) {
      var rjsPathname = config.rjs + '/bin/r.js';

      // check if the custom version is available, then load & return the
      // custom version, else default to the standard bundled requirejs
      if (fs.existsSync(rjsPathname)) {
        requirejs = require(rjsPathname);
        isDefaultVersion = false;
        return requirejs;
      }

    }

    isDefaultVersion = true;
    requirejs = defaultRequire;
    return requirejs;
  };

  // Returns the version number of the currently used requirejs library
  exports.getRequirejsVersionInfo = function() {
    return requirejs.version;
  };

  // Returns a boolean flag that determines if we´re using
  // the default bundled version or a user defined custom requirejs version
  exports.isCustomLibrary = function() {
    return !isDefaultVersion;
  };

  return exports;
};
<commit_msg>Allow to use custom r.js with relative path<commit_after>/*
 * grunt-require
 * https://github.com/asciidisco/grunt-requirejs
 *
 * Copyright (c) 2012 asciidisco
 * Licensed under the MIT license.
 */

exports.init = function(grunt) {
  'use strict';

  var fs = require('fs');
  var exports = {};

  // privates
  var isDefaultVersion = true;
  var requirejs = null;

  // Returns a requirejs instance
  exports.getRequirejs = function(config) {
    var defaultRequire = require('requirejs');

    // check if we should load a custom requirejs version
    if (config.rjs) {
      var rjsPathname = config.rjs + '/bin/r.js';

      // if the custom version is available, then load & return the
      // custom version, else default to the standard bundled requirejs
      try {
        requirejs = require(rjsPathname);
        isDefaultVersion = false;
        return requirejs;
      } catch (e) {}

    }

    isDefaultVersion = true;
    requirejs = defaultRequire;
    return requirejs;
  };

  // Returns the version number of the currently used requirejs library
  exports.getRequirejsVersionInfo = function() {
    return requirejs.version;
  };

  // Returns a boolean flag that determines if we´re using
  // the default bundled version or a user defined custom requirejs version
  exports.isCustomLibrary = function() {
    return !isDefaultVersion;
  };

  return exports;
};
<|endoftext|>


<commit_before>/*jslint vars: true*/
/*global describe, it, expect, waits, waitsFor, runs, afterEach, spyOn, $*/

describe('Autocomplete', function () {
    'use strict';

    afterEach(function () {
        $('.autocomplete-suggestions').hide();
    });

    it('Should initialize autocomplete options', function () {
        var input = document.createElement('input'),
            options = { serviceUrl: '/autocomplete/service/url' },
            autocomplete = new $.Autocomplete(input, options);

        expect(autocomplete.options.serviceUrl).toEqual(options.serviceUrl);
        expect(autocomplete.suggestionsContainer).not.toBeNull();
    });

    it('Should set autocomplete attribute to "off"', function () {
        var input = document.createElement('input'),
            autocomplete = new $.Autocomplete(input, {});

        expect(autocomplete).not.toBeNull();
        expect(input.getAttribute('autocomplete')).toEqual('off');
    });

    it('Should get current value', function () {
        var input = document.createElement('input'),
            autocomplete = new $.Autocomplete(input, {
                lookup: [{ value: 'Jamaica', data: 'B' }]
            });

        input.value = 'Jam';
        autocomplete.onValueChange();

        expect(autocomplete.visible).toBe(true);
        expect(autocomplete.currentValue).toEqual('Jam');
    });

    it('Should call formatResult three times', function () {
        var input = document.createElement('input'),
            counter = 0,
            suggestion,
            currentValue,
            autocomplete = new $.Autocomplete(input, {
                lookup: ['Jamaica', 'Jamaica', 'Jamaica'],
                formatResult: function (s, v) {
                    suggestion = s;
                    currentValue = v;
                    counter += 1;
                }
            });

        input.value = 'Jam';
        autocomplete.onValueChange();

        expect(suggestion.value).toBe('Jamaica');
        expect(suggestion.data).toBe(null);
        expect(currentValue).toEqual('Jam');
        expect(counter).toEqual(3);
    });

    it('Verify onSelect callback', function () {
        var input = document.createElement('input'),
            context,
            value,
            data,
            autocomplete = new $.Autocomplete(input, {
                lookup: [{ value: 'A', data: 'B' }],
                onSelect: function (suggestion) {
                    context = this;
                    value = suggestion.value;
                    data = suggestion.data;
                }
            });

        input.value = 'A';
        autocomplete.onValueChange();
        autocomplete.select(0);

        expect(context).toEqual(input);
        expect(value).toEqual('A');
        expect(data).toEqual('B');
    });

    it('Should convert suggestions format', function () {
        var input = document.createElement('input'),
            autocomplete = new $.Autocomplete(input, {
                lookup: ['A', 'B']
            });

        expect(autocomplete.options.lookup[0].value).toBe('A');
        expect(autocomplete.options.lookup[1].value).toBe('B');
    });

    it('Should execute onSearchStart', function () {
        var input = document.createElement('input'),
            startQuery,
            ajaxExecuted = false,
            autocomplete = new $.Autocomplete(input, {
                serviceUrl: '/test',
                onSearchStart: function (params) {
                    startQuery = params.query;
                }
            });

        $.mockjax({
            url: '/test',
            responseTime: 50,
            response: function (settings) {
                ajaxExecuted = true;
                var query = settings.data.query,
                    response = {
                        query: query,
                        suggestions: []
                    };
                this.responseText = JSON.stringify(response);
            }
        });

        input.value = 'A';
        autocomplete.onValueChange();

        waitsFor(function () {
            return ajaxExecuted;
        }, 'Ajax call never completed.', 100);

        runs(function () {
            expect(ajaxExecuted).toBe(true);
            expect(startQuery).toBe('A');
        });
    });

    it('Should execute onSearchComplete', function () {
        var input = document.createElement('input'),
            completeQuery,
            ajaxExecuted = false,
            url = '/test-completed',
            autocomplete = new $.Autocomplete(input, {
                serviceUrl: url,
                onSearchComplete: function (query) {
                    completeQuery = query;
                }
            });

        $.mockjax({
            url: url,
            responseTime: 50,
            response: function (settings) {
                ajaxExecuted = true;
                var query = settings.data.query,
                    response = {
                        query: query,
                        suggestions: []
                    };
                this.responseText = JSON.stringify(response);
            }
        });

        input.value = 'A';
        autocomplete.onValueChange();

        waitsFor(function () {
            return ajaxExecuted;
        }, 'Ajax call never completed.', 100);

        runs(function () {
            expect(ajaxExecuted).toBe(true);
            expect(completeQuery).toBe('A');
        });
    });

    it('Should transform results', function () {
        var input = document.createElement('input'),
            ajaxExecuted = false,
            url = '/test-transform',
            autocomplete = new $.Autocomplete(input, {
                serviceUrl: url,
                transformResult: function (result, query) {
                    return {
                        query: query,
                        suggestions: $.map(result.split(','), function (item) {
                            return { value: item, data: null };
                        })
                    };
                }
            });

        $.mockjax({
            url: url,
            responseTime: 50,
            response: function () {
                ajaxExecuted = true;
                this.responseText = 'Andora,Angola,Argentina';
            }
        });

        input.value = 'A';
        autocomplete.onValueChange();

        waitsFor(function () {
            return ajaxExecuted;
        }, 'Ajax call never completed.', 100);

        runs(function () {
            expect(ajaxExecuted).toBe(true);
            expect(autocomplete.suggestions.length).toBe(3);
            expect(autocomplete.suggestions[0].value).toBe('Andora');
        });
    });

    it('Should not require orginal query value from the server', function () {
        var input = document.createElement('input'),
            ajaxExecuted = false,
            url = '/test-original-query',
            autocomplete = new $.Autocomplete(input, {
                serviceUrl: url
            });

        $.mockjax({
            url: url,
            responseTime: 50,
            response: function () {
                ajaxExecuted = true;
                var response = {
                    query: null,
                    suggestions: ['A', 'B', 'C']
                };
                this.responseText = JSON.stringify(response);
            }
        });

        input.value = 'A';
        autocomplete.onValueChange();

        waitsFor(function () {
            return ajaxExecuted;
        }, 'Ajax call never completed.', 100);

        runs(function () {
            expect(ajaxExecuted).toBe(true);
            expect(autocomplete.suggestions.length).toBe(3);
            expect(autocomplete.suggestions[0].value).toBe('A');
        });
    });

    it('Should should not preventDefault when tabDisabled is set to false', function () {
        var input = document.createElement('input'),
            autocomplete = new $.Autocomplete(input, {
                lookup: [{ value: 'Jamaica', data: 'B' }],
                tabDisabled: false,
                autoSelectFirst: true
            });
        input.value = 'Jam';
        autocomplete.onValueChange();

        var event = $.Event('keydown');
        event.keyCode = 9; // the tab keycode
        spyOn(event, 'stopImmediatePropagation');
        spyOn(event, 'preventDefault');
        spyOn(autocomplete, 'suggest');

        expect(autocomplete.visible).toBe(true);
        expect(autocomplete.disabled).toBe(undefined);
        expect(autocomplete.selectedIndex).not.toBe(-1);

        $(input).trigger(event);

        expect(event.stopImmediatePropagation).not.toHaveBeenCalled();
        expect(event.preventDefault).not.toHaveBeenCalled();
        expect(autocomplete.suggest).not.toHaveBeenCalled();
    });

    it('Should should preventDefault when tabDisabled is set to true', function () {
        var input = document.createElement('input'),
            autocomplete = new $.Autocomplete(input, {
                lookup: [{ value: 'Jamaica', data: 'B' }],
                tabDisabled: true,
                autoSelectFirst: true
            });
        input.value = 'Jam';
        autocomplete.onValueChange();

        var event = $.Event('keydown');
        event.keyCode = 9; // the tab keycode
        spyOn(event, 'stopImmediatePropagation');
        spyOn(event, 'preventDefault');
        spyOn(autocomplete, 'suggest');

        expect(autocomplete.visible).toBe(true);
        expect(autocomplete.disabled).toBe(undefined);
        expect(autocomplete.selectedIndex).not.toBe(-1);

        $(input).trigger(event);

        expect(event.stopImmediatePropagation).toHaveBeenCalled();
        expect(event.preventDefault).toHaveBeenCalled();
        expect(autocomplete.suggest).not.toHaveBeenCalled();
    });

    it('Should not autoselect first item by default', function () {
        var input = document.createElement('input'),
            autocomplete = new $.Autocomplete(input, {
                lookup: ['Jamaica', 'Jamaica', 'Jamaica']
            });

        input.value = 'Jam';
        autocomplete.onValueChange();

        expect(autocomplete.selectedIndex).toBe(-1);
    });

    it('Should autoselect first item autoSelectFirst set to true', function () {
        var input = document.createElement('input'),
            autocomplete = new $.Autocomplete(input, {
                lookup: ['Jamaica', 'Jamaica', 'Jamaica'],
                autoSelectFirst: true
            });

        input.value = 'Jam';
        autocomplete.onValueChange();

        expect(autocomplete.selectedIndex).toBe(0);
    });

    it('Should use custom query parameter name', function () {
        var input = document.createElement('input'),
            paramName = 'custom',
            paramValue = null,
            autocomplete = new $.Autocomplete(input, {
                serviceUrl: '/test-query',
                paramName: paramName
            });

        $.mockjax({
            url: '/test-query',
            responseTime: 5,
            response: function (settings) {
                paramValue = settings.data[paramName];
                var response = {
                    query: paramValue,
                    suggestions: []
                };
                this.responseText = JSON.stringify(response);
            }
        });

        input.value = 'Jam';
        autocomplete.onValueChange();

        waits(10);

        runs(function () {
            expect(paramValue).toBe('Jam');
        });
    });

    it('Should destroy autocomplete instance', function () {
        var input = $(document.createElement('input')),
            div = $(document.createElement('div'));

        input.autocomplete({
            serviceUrl: '/test-dispose',
            appendTo: div
        });

        expect(input.data('autocomplete')).toBeDefined();
        expect(div.children().length).toBeGreaterThan(0);

        input.autocomplete('dispose');

        expect(input.data('autocomplete')).toBeUndefined();
        expect(div.children().length).toBe(0);
    });

    it('Should return Autocomplete instance if called without arguments', function () {
        var input = $(document.createElement('input'));

        input.autocomplete({
            serviceUrl: '/test-dispose'
        });

        var instance = input.autocomplete();

        expect(instance instanceof $.Autocomplete).toBe(true);
    });

    it('Should construct serviceUrl via callback function.', function () {
        var input = $(document.createElement('input')),
            dynamicUrl,
            data;

        input.autocomplete({
            ignoreParams: true,
            serviceUrl: function (query) {
                return '/dynamic-url/' + encodeURIComponent(query).replace(/%20/g, "+");
            }
        });

        $.mockjax({
            url: '/dynamic-url/*',
            responseTime: 5,
            response: function (settings) {
                dynamicUrl = settings.url;
                data = settings.data;
                var response = {
                    suggestions: []
                };
                this.responseText = JSON.stringify(response);
            }
        });

        input.val('Hello World');
        input.autocomplete().onValueChange();

        waits(10);

        runs(function () {
            expect(dynamicUrl).toBe('/dynamic-url/Hello+World');
            expect(data).toBeFalsy();
        });
    });

    it('Should set width to be greater than zero', function () {
        var input = $(document.createElement('input')),
            instance,
            width;

        input.autocomplete({
            lookup: [{ value: 'Jamaica', data: 'B' }]
        });

        input.val('Jam');
        instance = input.autocomplete();
        instance.onValueChange();
        width = $(instance.suggestionsContainer).width();

        expect(width).toBeGreaterThan(0);
    });
});<commit_msg>Update keyCode to which<commit_after>/*jslint vars: true*/
/*global describe, it, expect, waits, waitsFor, runs, afterEach, spyOn, $*/

describe('Autocomplete', function () {
    'use strict';

    afterEach(function () {
        $('.autocomplete-suggestions').hide();
    });

    it('Should initialize autocomplete options', function () {
        var input = document.createElement('input'),
            options = { serviceUrl: '/autocomplete/service/url' },
            autocomplete = new $.Autocomplete(input, options);

        expect(autocomplete.options.serviceUrl).toEqual(options.serviceUrl);
        expect(autocomplete.suggestionsContainer).not.toBeNull();
    });

    it('Should set autocomplete attribute to "off"', function () {
        var input = document.createElement('input'),
            autocomplete = new $.Autocomplete(input, {});

        expect(autocomplete).not.toBeNull();
        expect(input.getAttribute('autocomplete')).toEqual('off');
    });

    it('Should get current value', function () {
        var input = document.createElement('input'),
            autocomplete = new $.Autocomplete(input, {
                lookup: [{ value: 'Jamaica', data: 'B' }]
            });

        input.value = 'Jam';
        autocomplete.onValueChange();

        expect(autocomplete.visible).toBe(true);
        expect(autocomplete.currentValue).toEqual('Jam');
    });

    it('Should call formatResult three times', function () {
        var input = document.createElement('input'),
            counter = 0,
            suggestion,
            currentValue,
            autocomplete = new $.Autocomplete(input, {
                lookup: ['Jamaica', 'Jamaica', 'Jamaica'],
                formatResult: function (s, v) {
                    suggestion = s;
                    currentValue = v;
                    counter += 1;
                }
            });

        input.value = 'Jam';
        autocomplete.onValueChange();

        expect(suggestion.value).toBe('Jamaica');
        expect(suggestion.data).toBe(null);
        expect(currentValue).toEqual('Jam');
        expect(counter).toEqual(3);
    });

    it('Verify onSelect callback', function () {
        var input = document.createElement('input'),
            context,
            value,
            data,
            autocomplete = new $.Autocomplete(input, {
                lookup: [{ value: 'A', data: 'B' }],
                onSelect: function (suggestion) {
                    context = this;
                    value = suggestion.value;
                    data = suggestion.data;
                }
            });

        input.value = 'A';
        autocomplete.onValueChange();
        autocomplete.select(0);

        expect(context).toEqual(input);
        expect(value).toEqual('A');
        expect(data).toEqual('B');
    });

    it('Should convert suggestions format', function () {
        var input = document.createElement('input'),
            autocomplete = new $.Autocomplete(input, {
                lookup: ['A', 'B']
            });

        expect(autocomplete.options.lookup[0].value).toBe('A');
        expect(autocomplete.options.lookup[1].value).toBe('B');
    });

    it('Should execute onSearchStart', function () {
        var input = document.createElement('input'),
            startQuery,
            ajaxExecuted = false,
            autocomplete = new $.Autocomplete(input, {
                serviceUrl: '/test',
                onSearchStart: function (params) {
                    startQuery = params.query;
                }
            });

        $.mockjax({
            url: '/test',
            responseTime: 50,
            response: function (settings) {
                ajaxExecuted = true;
                var query = settings.data.query,
                    response = {
                        query: query,
                        suggestions: []
                    };
                this.responseText = JSON.stringify(response);
            }
        });

        input.value = 'A';
        autocomplete.onValueChange();

        waitsFor(function () {
            return ajaxExecuted;
        }, 'Ajax call never completed.', 100);

        runs(function () {
            expect(ajaxExecuted).toBe(true);
            expect(startQuery).toBe('A');
        });
    });

    it('Should execute onSearchComplete', function () {
        var input = document.createElement('input'),
            completeQuery,
            ajaxExecuted = false,
            url = '/test-completed',
            autocomplete = new $.Autocomplete(input, {
                serviceUrl: url,
                onSearchComplete: function (query) {
                    completeQuery = query;
                }
            });

        $.mockjax({
            url: url,
            responseTime: 50,
            response: function (settings) {
                ajaxExecuted = true;
                var query = settings.data.query,
                    response = {
                        query: query,
                        suggestions: []
                    };
                this.responseText = JSON.stringify(response);
            }
        });

        input.value = 'A';
        autocomplete.onValueChange();

        waitsFor(function () {
            return ajaxExecuted;
        }, 'Ajax call never completed.', 100);

        runs(function () {
            expect(ajaxExecuted).toBe(true);
            expect(completeQuery).toBe('A');
        });
    });

    it('Should transform results', function () {
        var input = document.createElement('input'),
            ajaxExecuted = false,
            url = '/test-transform',
            autocomplete = new $.Autocomplete(input, {
                serviceUrl: url,
                transformResult: function (result, query) {
                    return {
                        query: query,
                        suggestions: $.map(result.split(','), function (item) {
                            return { value: item, data: null };
                        })
                    };
                }
            });

        $.mockjax({
            url: url,
            responseTime: 50,
            response: function () {
                ajaxExecuted = true;
                this.responseText = 'Andora,Angola,Argentina';
            }
        });

        input.value = 'A';
        autocomplete.onValueChange();

        waitsFor(function () {
            return ajaxExecuted;
        }, 'Ajax call never completed.', 100);

        runs(function () {
            expect(ajaxExecuted).toBe(true);
            expect(autocomplete.suggestions.length).toBe(3);
            expect(autocomplete.suggestions[0].value).toBe('Andora');
        });
    });

    it('Should not require orginal query value from the server', function () {
        var input = document.createElement('input'),
            ajaxExecuted = false,
            url = '/test-original-query',
            autocomplete = new $.Autocomplete(input, {
                serviceUrl: url
            });

        $.mockjax({
            url: url,
            responseTime: 50,
            response: function () {
                ajaxExecuted = true;
                var response = {
                    query: null,
                    suggestions: ['A', 'B', 'C']
                };
                this.responseText = JSON.stringify(response);
            }
        });

        input.value = 'A';
        autocomplete.onValueChange();

        waitsFor(function () {
            return ajaxExecuted;
        }, 'Ajax call never completed.', 100);

        runs(function () {
            expect(ajaxExecuted).toBe(true);
            expect(autocomplete.suggestions.length).toBe(3);
            expect(autocomplete.suggestions[0].value).toBe('A');
        });
    });

    it('Should should not preventDefault when tabDisabled is set to false', function () {
        var input = document.createElement('input'),
            autocomplete = new $.Autocomplete(input, {
                lookup: [{ value: 'Jamaica', data: 'B' }],
                tabDisabled: false,
                autoSelectFirst: true
            });
        input.value = 'Jam';
        autocomplete.onValueChange();

        var event = $.Event('keydown');
        event.which = 9; // the tab keycode
        spyOn(event, 'stopImmediatePropagation');
        spyOn(event, 'preventDefault');
        spyOn(autocomplete, 'suggest');

        expect(autocomplete.visible).toBe(true);
        expect(autocomplete.disabled).toBe(undefined);
        expect(autocomplete.selectedIndex).not.toBe(-1);

        $(input).trigger(event);

        expect(event.stopImmediatePropagation).not.toHaveBeenCalled();
        expect(event.preventDefault).not.toHaveBeenCalled();
        expect(autocomplete.suggest).not.toHaveBeenCalled();
    });

    it('Should should preventDefault when tabDisabled is set to true', function () {
        var input = document.createElement('input'),
            autocomplete = new $.Autocomplete(input, {
                lookup: [{ value: 'Jamaica', data: 'B' }],
                tabDisabled: true,
                autoSelectFirst: true
            });
        input.value = 'Jam';
        autocomplete.onValueChange();

        var event = $.Event('keydown');
        event.which = 9; // the tab keycode
        spyOn(event, 'stopImmediatePropagation');
        spyOn(event, 'preventDefault');
        spyOn(autocomplete, 'suggest');

        expect(autocomplete.visible).toBe(true);
        expect(autocomplete.disabled).toBe(undefined);
        expect(autocomplete.selectedIndex).not.toBe(-1);

        $(input).trigger(event);

        expect(event.stopImmediatePropagation).toHaveBeenCalled();
        expect(event.preventDefault).toHaveBeenCalled();
        expect(autocomplete.suggest).not.toHaveBeenCalled();
    });

    it('Should not autoselect first item by default', function () {
        var input = document.createElement('input'),
            autocomplete = new $.Autocomplete(input, {
                lookup: ['Jamaica', 'Jamaica', 'Jamaica']
            });

        input.value = 'Jam';
        autocomplete.onValueChange();

        expect(autocomplete.selectedIndex).toBe(-1);
    });

    it('Should autoselect first item autoSelectFirst set to true', function () {
        var input = document.createElement('input'),
            autocomplete = new $.Autocomplete(input, {
                lookup: ['Jamaica', 'Jamaica', 'Jamaica'],
                autoSelectFirst: true
            });

        input.value = 'Jam';
        autocomplete.onValueChange();

        expect(autocomplete.selectedIndex).toBe(0);
    });

    it('Should use custom query parameter name', function () {
        var input = document.createElement('input'),
            paramName = 'custom',
            paramValue = null,
            autocomplete = new $.Autocomplete(input, {
                serviceUrl: '/test-query',
                paramName: paramName
            });

        $.mockjax({
            url: '/test-query',
            responseTime: 5,
            response: function (settings) {
                paramValue = settings.data[paramName];
                var response = {
                    query: paramValue,
                    suggestions: []
                };
                this.responseText = JSON.stringify(response);
            }
        });

        input.value = 'Jam';
        autocomplete.onValueChange();

        waits(10);

        runs(function () {
            expect(paramValue).toBe('Jam');
        });
    });

    it('Should destroy autocomplete instance', function () {
        var input = $(document.createElement('input')),
            div = $(document.createElement('div'));

        input.autocomplete({
            serviceUrl: '/test-dispose',
            appendTo: div
        });

        expect(input.data('autocomplete')).toBeDefined();
        expect(div.children().length).toBeGreaterThan(0);

        input.autocomplete('dispose');

        expect(input.data('autocomplete')).toBeUndefined();
        expect(div.children().length).toBe(0);
    });

    it('Should return Autocomplete instance if called without arguments', function () {
        var input = $(document.createElement('input'));

        input.autocomplete({
            serviceUrl: '/test-dispose'
        });

        var instance = input.autocomplete();

        expect(instance instanceof $.Autocomplete).toBe(true);
    });

    it('Should construct serviceUrl via callback function.', function () {
        var input = $(document.createElement('input')),
            dynamicUrl,
            data;

        input.autocomplete({
            ignoreParams: true,
            serviceUrl: function (query) {
                return '/dynamic-url/' + encodeURIComponent(query).replace(/%20/g, "+");
            }
        });

        $.mockjax({
            url: '/dynamic-url/*',
            responseTime: 5,
            response: function (settings) {
                dynamicUrl = settings.url;
                data = settings.data;
                var response = {
                    suggestions: []
                };
                this.responseText = JSON.stringify(response);
            }
        });

        input.val('Hello World');
        input.autocomplete().onValueChange();

        waits(10);

        runs(function () {
            expect(dynamicUrl).toBe('/dynamic-url/Hello+World');
            expect(data).toBeFalsy();
        });
    });

    it('Should set width to be greater than zero', function () {
        var input = $(document.createElement('input')),
            instance,
            width;

        input.autocomplete({
            lookup: [{ value: 'Jamaica', data: 'B' }]
        });

        input.val('Jam');
        instance = input.autocomplete();
        instance.onValueChange();
        width = $(instance.suggestionsContainer).width();

        expect(width).toBeGreaterThan(0);
    });
});<|endoftext|>