<commit_before>// @flow
import type { Dispatch } from 'redux';

import { getFeatureFlag, TILE_VIEW_ENABLED } from '../base/flags';
import {
    getPinnedParticipant,
    getParticipantCount,
    pinParticipant
} from '../base/participants';
import { isStageFilmstripAvailable } from '../filmstrip/functions';
import { isVideoPlaying } from '../shared-video/functions';
import { VIDEO_QUALITY_LEVELS } from '../video-quality/constants';

import { LAYOUTS } from './constants';

declare var interfaceConfig: Object;

/**
 * A selector for retrieving the current automatic pinning setting.
 *
 * @private
 * @returns {string|undefined} The string "remote-only" is returned if only
 * remote screen sharing should be automatically pinned, any other truthy value
 * means automatically pin all screen shares. Falsy means do not automatically
 * pin any screen shares.
 */
export function getAutoPinSetting() {
    return typeof interfaceConfig === 'object'
        ? interfaceConfig.AUTO_PIN_LATEST_SCREEN_SHARE
        : 'remote-only';
}

/**
 * Returns the {@code LAYOUTS} constant associated with the layout
 * the application should currently be in.
 *
 * @param {Object} state - The redux state.
 * @returns {string}
 */
export function getCurrentLayout(state: Object) {
    if (shouldDisplayTileView(state)) {
        return LAYOUTS.TILE_VIEW;
    } else if (interfaceConfig.VERTICAL_FILMSTRIP) {
        if (isStageFilmstripAvailable(state, 2)) {
            return LAYOUTS.STAGE_FILMSTRIP_VIEW;
        }

        return LAYOUTS.VERTICAL_FILMSTRIP_VIEW;
    }

    return LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW;
}

/**
 * Selector for determining if the UI layout should be in tile view. Tile view
 * is determined by more than just having the tile view setting enabled, as
 * one-on-one calls should not be in tile view, as well as etherpad editing.
 *
 * @param {Object} state - The redux state.
 * @returns {boolean} True if tile view should be displayed.
 */
export function shouldDisplayTileView(state: Object = {}) {
    const participantCount = getParticipantCount(state);

    const tileViewEnabledFeatureFlag = getFeatureFlag(state, TILE_VIEW_ENABLED, true);
    const { disableTileView } = state['features/base/config'];

    if (disableTileView || !tileViewEnabledFeatureFlag) {
        return false;
    }

    const { tileViewEnabled } = state['features/video-layout'];

    if (tileViewEnabled !== undefined) {
        // If the user explicitly requested a view mode, we
        // do that.
        return tileViewEnabled;
    }

    const { iAmRecorder } = state['features/base/config'];

    // None tile view mode is easier to calculate (no need for many negations), so we do
    // that and negate it only once.
    const shouldDisplayNormalMode = Boolean(

        // Reasons for normal mode:

        // Editing etherpad
        state['features/etherpad']?.editing

        // We pinned a participant
        || getPinnedParticipant(state)

        // It's a 1-on-1 meeting
        || participantCount < 3

        // There is a shared YouTube video in the meeting
        || isVideoPlaying(state)

        // We want jibri to use stage view by default
        || iAmRecorder
    );

    return !shouldDisplayNormalMode;
}

/**
 * Private helper to automatically pin the latest screen share stream or unpin
 * if there are no more screen share streams.
 *
 * @param {Array<string>} screenShares - Array containing the list of all the screen sharing endpoints
 * before the update was triggered (including the ones that have been removed from redux because of the update).
 * @param {Store} store - The redux store.
 * @returns {void}
 */
export function updateAutoPinnedParticipant(
        screenShares: Array<string>, { dispatch, getState }: { dispatch: Dispatch<any>, getState: Function }) {
    const state = getState();
    const remoteScreenShares = state['features/video-layout'].remoteScreenShares;
    const pinned = getPinnedParticipant(getState);

    // if the pinned participant is shared video or some other fake participant we want to skip auto-pinning
    if (pinned?.isFakeParticipant) {
        return;
    }

    // Unpin the screen share when the screen sharing participant leaves. Switch to tile view if no other
    // participant was pinned before screen share was auto-pinned, pin the previously pinned participant otherwise.
    if (!remoteScreenShares?.length) {
        let participantId = null;

        if (pinned && !screenShares.find(share => share === pinned.id)) {
            participantId = pinned.id;
        }
        dispatch(pinParticipant(participantId));

        return;
    }

    const latestScreenShareParticipantId = remoteScreenShares[remoteScreenShares.length - 1];

    if (latestScreenShareParticipantId) {
        dispatch(pinParticipant(latestScreenShareParticipantId));
    }
}

/**
 * Selector for whether we are currently in tile view.
 *
 * @param {Object} state - The redux state.
 * @returns {boolean}
 */
export function isLayoutTileView(state: Object) {
    return getCurrentLayout(state) === LAYOUTS.TILE_VIEW;
}

/**
 * Gets the video quality for the given height.
 *
 * @param {number|undefined} height - Height of the video container.
 * @returns {number}
 */
function getVideoQualityForHeight(height: number) {
    if (!height) {
        return VIDEO_QUALITY_LEVELS.LOW;
    }
    const levels = Object.values(VIDEO_QUALITY_LEVELS)
        .map(Number)
        .sort((a, b) => a - b);

    for (const level of levels) {
        if (height <= level) {
            return level;
        }
    }

    return VIDEO_QUALITY_LEVELS.ULTRA;
}

/**
 * Gets the video quality level for the resizable filmstrip thumbnail height.
 *
 * @param {Object} state - Redux state.
 * @returns {number}
 */
export function getVideoQualityForResizableFilmstripThumbnails(state) {
    const height = state['features/filmstrip'].verticalViewDimensions?.gridView?.thumbnailSize?.height;

    return getVideoQualityForHeight(height);
}

/**
 * Gets the video quality for the large video.
 *
 * @returns {number}
 */
export function getVideoQualityForLargeVideo() {
    const wrapper = document.querySelector('#largeVideoWrapper');

    return getVideoQualityForHeight(wrapper.clientHeight);
}

/**
 * Gets the video quality level for the thumbnails in the stage filmstrip.
 *
 * @param {Object} state - Redux state.
 * @returns {number}
 */
export function getVideoQualityForStageThumbnails(state) {
    const height = state['features/filmstrip'].stageFilmstripDimensions?.thumbnailSize?.height;

    return getVideoQualityForHeight(height);
}
<commit_msg>fix(video-layout) fix usage of disableTileView<commit_after>// @flow
import type { Dispatch } from 'redux';

import { getFeatureFlag, TILE_VIEW_ENABLED } from '../base/flags';
import {
    getPinnedParticipant,
    getParticipantCount,
    pinParticipant
} from '../base/participants';
import { isStageFilmstripAvailable } from '../filmstrip/functions';
import { isVideoPlaying } from '../shared-video/functions';
import { VIDEO_QUALITY_LEVELS } from '../video-quality/constants';

import { LAYOUTS } from './constants';

declare var interfaceConfig: Object;

/**
 * A selector for retrieving the current automatic pinning setting.
 *
 * @private
 * @returns {string|undefined} The string "remote-only" is returned if only
 * remote screen sharing should be automatically pinned, any other truthy value
 * means automatically pin all screen shares. Falsy means do not automatically
 * pin any screen shares.
 */
export function getAutoPinSetting() {
    return typeof interfaceConfig === 'object'
        ? interfaceConfig.AUTO_PIN_LATEST_SCREEN_SHARE
        : 'remote-only';
}

/**
 * Returns the {@code LAYOUTS} constant associated with the layout
 * the application should currently be in.
 *
 * @param {Object} state - The redux state.
 * @returns {string}
 */
export function getCurrentLayout(state: Object) {
    if (shouldDisplayTileView(state)) {
        return LAYOUTS.TILE_VIEW;
    } else if (interfaceConfig.VERTICAL_FILMSTRIP) {
        if (isStageFilmstripAvailable(state, 2)) {
            return LAYOUTS.STAGE_FILMSTRIP_VIEW;
        }

        return LAYOUTS.VERTICAL_FILMSTRIP_VIEW;
    }

    return LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW;
}

/**
 * Selector for determining if the UI layout should be in tile view. Tile view
 * is determined by more than just having the tile view setting enabled, as
 * one-on-one calls should not be in tile view, as well as etherpad editing.
 *
 * @param {Object} state - The redux state.
 * @returns {boolean} True if tile view should be displayed.
 */
export function shouldDisplayTileView(state: Object = {}) {
    const { tileViewEnabled } = state['features/video-layout'];

    if (tileViewEnabled !== undefined) {
        // If the user explicitly requested a view mode, we
        // do that.
        return tileViewEnabled;
    }

    const tileViewEnabledFeatureFlag = getFeatureFlag(state, TILE_VIEW_ENABLED, true);
    const { disableTileView } = state['features/base/config'];

    if (disableTileView || !tileViewEnabledFeatureFlag) {
        return false;
    }

    const participantCount = getParticipantCount(state);
    const { iAmRecorder } = state['features/base/config'];

    // None tile view mode is easier to calculate (no need for many negations), so we do
    // that and negate it only once.
    const shouldDisplayNormalMode = Boolean(

        // Reasons for normal mode:

        // Editing etherpad
        state['features/etherpad']?.editing

        // We pinned a participant
        || getPinnedParticipant(state)

        // It's a 1-on-1 meeting
        || participantCount < 3

        // There is a shared YouTube video in the meeting
        || isVideoPlaying(state)

        // We want jibri to use stage view by default
        || iAmRecorder
    );

    return !shouldDisplayNormalMode;
}

/**
 * Private helper to automatically pin the latest screen share stream or unpin
 * if there are no more screen share streams.
 *
 * @param {Array<string>} screenShares - Array containing the list of all the screen sharing endpoints
 * before the update was triggered (including the ones that have been removed from redux because of the update).
 * @param {Store} store - The redux store.
 * @returns {void}
 */
export function updateAutoPinnedParticipant(
        screenShares: Array<string>, { dispatch, getState }: { dispatch: Dispatch<any>, getState: Function }) {
    const state = getState();
    const remoteScreenShares = state['features/video-layout'].remoteScreenShares;
    const pinned = getPinnedParticipant(getState);

    // if the pinned participant is shared video or some other fake participant we want to skip auto-pinning
    if (pinned?.isFakeParticipant) {
        return;
    }

    // Unpin the screen share when the screen sharing participant leaves. Switch to tile view if no other
    // participant was pinned before screen share was auto-pinned, pin the previously pinned participant otherwise.
    if (!remoteScreenShares?.length) {
        let participantId = null;

        if (pinned && !screenShares.find(share => share === pinned.id)) {
            participantId = pinned.id;
        }
        dispatch(pinParticipant(participantId));

        return;
    }

    const latestScreenShareParticipantId = remoteScreenShares[remoteScreenShares.length - 1];

    if (latestScreenShareParticipantId) {
        dispatch(pinParticipant(latestScreenShareParticipantId));
    }
}

/**
 * Selector for whether we are currently in tile view.
 *
 * @param {Object} state - The redux state.
 * @returns {boolean}
 */
export function isLayoutTileView(state: Object) {
    return getCurrentLayout(state) === LAYOUTS.TILE_VIEW;
}

/**
 * Gets the video quality for the given height.
 *
 * @param {number|undefined} height - Height of the video container.
 * @returns {number}
 */
function getVideoQualityForHeight(height: number) {
    if (!height) {
        return VIDEO_QUALITY_LEVELS.LOW;
    }
    const levels = Object.values(VIDEO_QUALITY_LEVELS)
        .map(Number)
        .sort((a, b) => a - b);

    for (const level of levels) {
        if (height <= level) {
            return level;
        }
    }

    return VIDEO_QUALITY_LEVELS.ULTRA;
}

/**
 * Gets the video quality level for the resizable filmstrip thumbnail height.
 *
 * @param {Object} state - Redux state.
 * @returns {number}
 */
export function getVideoQualityForResizableFilmstripThumbnails(state) {
    const height = state['features/filmstrip'].verticalViewDimensions?.gridView?.thumbnailSize?.height;

    return getVideoQualityForHeight(height);
}

/**
 * Gets the video quality for the large video.
 *
 * @returns {number}
 */
export function getVideoQualityForLargeVideo() {
    const wrapper = document.querySelector('#largeVideoWrapper');

    return getVideoQualityForHeight(wrapper.clientHeight);
}

/**
 * Gets the video quality level for the thumbnails in the stage filmstrip.
 *
 * @param {Object} state - Redux state.
 * @returns {number}
 */
export function getVideoQualityForStageThumbnails(state) {
    const height = state['features/filmstrip'].stageFilmstripDimensions?.thumbnailSize?.height;

    return getVideoQualityForHeight(height);
}
<|endoftext|>


<commit_before>export const typeOf = x => {
  const t = x == null ? 'Null' : (x.__typeName || x.constructor.name);

  if (t == 'Number') {
    return Number.isSafeInteger(x) ? 'Integer' : 'Float';
  }
  else if (t == 'Array') {
    const isMatrix = x.length > 0 && x[0].constructor.name == 'Array';
    return isMatrix ? 'Matrix' : 'Vector';
  }
  else
    return t;
};

const call = (dispatch, op, ops) => (...args) => {
  let next = dispatch;
  for (let i = 0; next && i < args.length; ++i)
    next = next[typeOf(args[i])];

  const method = next || dispatch['__default__'];

  if (method)
    return method(...args, ops);
  else
    throw new Error(`Operator '${op}' not defined on [${args.map(typeOf)}]`);
};

const _isObject = o => o != null && o.constructor == Object;

const mergeDeep = (obj, mods) => {
  const out = Object.assign({}, obj);

  for (const k in mods) {
    if (_isObject(out[k]) && _isObject(mods[k]))
      out[k] = mergeDeep(out[k], mods[k]);
    else
      out[k] = mods[k];
  }

  return out;
};

const gcd = (a, b, ops) => {
  a = ops.abs(a);
  b = ops.abs(b);

  while (ops.sgn(b) > 0)
    [a, b] = [b, ops.mod(a, b)];

  return a;
};

const gcdex = (m, n, ops) => {
  let f  = ops.abs(m);
  let fm = ops.lt(m, 0) ? -1 : 1;
  let g  = ops.abs(n);
  let gm = 0;

  while (ops.ne(g, 0)) {
    const q  = ops.idiv(f, g);
    const t  = g;
    const tm = gm;
    g  = ops.minus(f, ops.times(q, g));
    gm = ops.minus(fm, ops.times(q, gm));
    f  = t;
    fm = tm;
  }

  if (ops.eq(n, 0))
    return [ f, fm, 0, gm, 1 ];
  else
    return [
      f,
      fm, ops.idiv(ops.minus(f, ops.times(fm, m)), n),
      gm, ops.idiv(ops.minus(0, ops.times(gm, m)), n) ];
};

const mod = (x, y, ops) => ops.minus(x, ops.times(ops.idiv(x, y), y));

const fromRepr = (obj, ops) => {
  const keys = Object.keys(obj);
  if (keys.length != 1)
    throw new Error('must have exactly one key');

  return ops[`__${keys[0]}__`](obj);
};

const defaults = {
  isInteger    : { __default__: x => false },
  isRational   : { __default__: x => false },
  isReal       : { __default__: x => false },

  eq: { __default__: (a, b, ops) => ops.cmp(a, b) == 0 },
  ne: { __default__: (a, b, ops) => ops.cmp(a, b) != 0 },
  lt: { __default__: (a, b, ops) => ops.cmp(a, b) <  0 },
  gt: { __default__: (a, b, ops) => ops.cmp(a, b) >  0 },
  le: { __default__: (a, b, ops) => ops.cmp(a, b) <= 0 },
  ge: { __default__: (a, b, ops) => ops.cmp(a, b) >= 0 },

  mod: { __default__: mod },
  gcd: { __default__: gcd },
  gcdex: { __default__: gcdex },

  typeOf     : { __default__: x => typeOf(x) },
  repr       : { __default__: (x, ops) => ({ [typeOf(x)]: ops.__repr__(x) }) },
  fromRepr   : { Object: fromRepr },
  serialize  : { __default__: (x, ops) => JSON.stringify(ops.repr(x)) },
  deserialize: { String: (x, ops) => fromRepr(JSON.parse(x), ops) },

  __repr__: { __default__: x => x }
};

export const arithmetic = (registry = mergeDeep({}, defaults)) => {
  const result = {
    register(specs) {
      return arithmetic(mergeDeep(registry, specs));
    }
  };
  for (const op in registry)
    result[op] = call(registry[op], op, result);

  return result;
};

if (require.main == module) {
  const ops = arithmetic()
    .register({
      add: {
        Integer: {
          Integer: (a, b) => a + b,
          String : (n, s) => `${n}+"${s}"`
        },
        __default__: (x, y) => `${x} plus ${y}`
      },
      test: {
        __default__: (x, y, ops) => `<${ops.add(x, y)}>`
      }
    });

  console.log(`add(3, 4) = ${ops.add(3, 4)}`);
  console.log(`add(5, "Olaf") = ${ops.add(5, "Olaf")}`);
  console.log(`add("Olaf", "Delgado") = ${ops.add("Olaf", "Delgado")}`);
  console.log(`test(5, "Olaf") = ${ops.test(5, "Olaf")}`);
}
<commit_msg>shorten gcdex code<commit_after>export const typeOf = x => {
  const t = x == null ? 'Null' : (x.__typeName || x.constructor.name);

  if (t == 'Number') {
    return Number.isSafeInteger(x) ? 'Integer' : 'Float';
  }
  else if (t == 'Array') {
    const isMatrix = x.length > 0 && x[0].constructor.name == 'Array';
    return isMatrix ? 'Matrix' : 'Vector';
  }
  else
    return t;
};

const call = (dispatch, op, ops) => (...args) => {
  let next = dispatch;
  for (let i = 0; next && i < args.length; ++i)
    next = next[typeOf(args[i])];

  const method = next || dispatch['__default__'];

  if (method)
    return method(...args, ops);
  else
    throw new Error(`Operator '${op}' not defined on [${args.map(typeOf)}]`);
};

const _isObject = o => o != null && o.constructor == Object;

const mergeDeep = (obj, mods) => {
  const out = Object.assign({}, obj);

  for (const k in mods) {
    if (_isObject(out[k]) && _isObject(mods[k]))
      out[k] = mergeDeep(out[k], mods[k]);
    else
      out[k] = mods[k];
  }

  return out;
};

const gcd = (a, b, ops) => {
  a = ops.abs(a);
  b = ops.abs(b);

  while (ops.sgn(b) > 0)
    [a, b] = [b, ops.mod(a, b)];

  return a;
};

const gcdex = (m, n, ops) => {
  let [f, g] = [ops.abs(m), ops.abs(n)];
  let [fm, gm] = [ops.lt(m, 0) ? -1 : 1, 0];

  while (ops.ne(g, 0)) {
    const q  = ops.idiv(f, g);
    [f, g] = [g, ops.minus(f, ops.times(q, g))];
    [fm, gm] = [gm, ops.minus(fm, ops.times(q, gm))];
  }

  if (ops.eq(n, 0))
    return [ f, fm, 0, gm, 1 ];
  else
    return [
      f,
      fm, ops.idiv(ops.minus(f, ops.times(fm, m)), n),
      gm, ops.idiv(ops.minus(0, ops.times(gm, m)), n) ];
};

const mod = (x, y, ops) => ops.minus(x, ops.times(ops.idiv(x, y), y));

const fromRepr = (obj, ops) => {
  const keys = Object.keys(obj);
  if (keys.length != 1)
    throw new Error('must have exactly one key');

  return ops[`__${keys[0]}__`](obj);
};

const defaults = {
  isInteger    : { __default__: x => false },
  isRational   : { __default__: x => false },
  isReal       : { __default__: x => false },

  eq: { __default__: (a, b, ops) => ops.cmp(a, b) == 0 },
  ne: { __default__: (a, b, ops) => ops.cmp(a, b) != 0 },
  lt: { __default__: (a, b, ops) => ops.cmp(a, b) <  0 },
  gt: { __default__: (a, b, ops) => ops.cmp(a, b) >  0 },
  le: { __default__: (a, b, ops) => ops.cmp(a, b) <= 0 },
  ge: { __default__: (a, b, ops) => ops.cmp(a, b) >= 0 },

  mod: { __default__: mod },
  gcd: { __default__: gcd },
  gcdex: { __default__: gcdex },

  typeOf     : { __default__: x => typeOf(x) },
  repr       : { __default__: (x, ops) => ({ [typeOf(x)]: ops.__repr__(x) }) },
  fromRepr   : { Object: fromRepr },
  serialize  : { __default__: (x, ops) => JSON.stringify(ops.repr(x)) },
  deserialize: { String: (x, ops) => fromRepr(JSON.parse(x), ops) },

  __repr__: { __default__: x => x }
};

export const arithmetic = (registry = mergeDeep({}, defaults)) => {
  const result = {
    register(specs) {
      return arithmetic(mergeDeep(registry, specs));
    }
  };
  for (const op in registry)
    result[op] = call(registry[op], op, result);

  return result;
};

if (require.main == module) {
  const ops = arithmetic()
    .register({
      add: {
        Integer: {
          Integer: (a, b) => a + b,
          String : (n, s) => `${n}+"${s}"`
        },
        __default__: (x, y) => `${x} plus ${y}`
      },
      test: {
        __default__: (x, y, ops) => `<${ops.add(x, y)}>`
      }
    });

  console.log(`add(3, 4) = ${ops.add(3, 4)}`);
  console.log(`add(5, "Olaf") = ${ops.add(5, "Olaf")}`);
  console.log(`add("Olaf", "Delgado") = ${ops.add("Olaf", "Delgado")}`);
  console.log(`test(5, "Olaf") = ${ops.test(5, "Olaf")}`);
}
<|endoftext|>


<commit_before>import moment from 'moment'
import _ from 'lodash'
import { handleActions } from 'redux-actions'

const data = {
  start_date: moment().format('YYYY-MM-DD'),
  end_date: moment().format('YYYY-MM-DD'),
  data_type: 'campaign', // or date
  location_depth: 0,
  selected_campaign: null,
  selected_locations: [],
  selected_indicators: [],
  selected_indicator_tag: null,
  indicator_filter: { id: 0, value: 0, title: 'All Districts', type: 'LPD Status' },
  datapoints: {meta: null, raw: null, flattened: null},
  dataParamsChanged: false
}

const data_entry = handleActions({
  SET_DATA_ENTRY_START_DATE: (state, action) => {
    return Object.assign({}, state, {
      start_date: action.payload,
      dataParamsChanged: true
    })
  },
  SET_DATA_ENTRY_END_DATE: (state, action) => {
    return Object.assign({}, state, {
      end_date: action.payload,
      dataParamsChanged: true
    })
  },
  TOGGLE_DATA_ENTRY_TYPE: (state, action) => {
    return Object.assign({}, data, {
      data_type: state.data_type === 'campaign' ? 'date' : 'campaign'
    })
  },
  GET_INITIAL_DATA_SUCCESS: (state, action) => {
    return Object.assign({}, state, {
      selected_campaign: action.payload.data.objects[0].campaigns[0]
    })
  },
  CLEAR_DATAPOINTS: (state, action) => {
    return Object.assign({}, state, {
      datapoints: {meta: null, raw: null, flattened: null},
      dataParamsChanged: false
    })
  },
  GET_DATAPOINTS_SUCCESS: (state, action) => {
    return Object.assign({}, state, {
      datapoints: {
        meta: action.payload.data.meta,
        raw: action.payload.data.objects,
        flattened: action.payload.data.objects
      },
      dataParamsChanged: false
    })
  },
  UPDATE_DATAPOINT_FAILURE: (state, action) => {
    return Object.assign({}, state, {
      dataParamsChanged: true
    })
  },
  SELECT_GLOBAL_CAMPAIGN: (state, action) => {
    return Object.assign({}, state, {
      selected_campaign: action.payload,
      dataParamsChanged: true
    })
  },
  SELECT_GLOBAL_LOCATION: (state, action) => {
    return Object.assign({}, state, {
      selected_locations: [...state.selected_locations, action.payload],
      dataParamsChanged: true
    })
  },
  SELECT_GLOBAL_LOCATION_DEPTH: (state, action) => {
    return Object.assign({}, state, {
      location_depth: action.payload
    })
  },
  SET_GLOBAL_LOCATIONS: (state, action) => {
    return Object.assign({}, state, {
      selected_locations: _.isArray(action.payload) ? action.payload : [action.payload],
      dataParamsChanged: true
    })
  },
  SET_GLOBAL_INDICATORS: (state, action) => {
    return Object.assign({}, state, {
      selected_indicators: _.isArray(action.payload) ? action.payload : [action.payload],
      dataParamsChanged: true
    })
  },
  SET_GLOBAL_INDICATOR_TAG: (state, action) => {
    return Object.assign({}, state, {
      selected_indicator_tag: action.payload
    })
  },
  SET_GLOBAL_INDICATOR_FILTER: (state, action) => {
    return Object.assign({}, state, {
      indicator_filter: action.payload,
      dataParamsChanged: true
    })
  }
}, data)

export default data_entry
<commit_msg>Update default lpd status<commit_after>import moment from 'moment'
import _ from 'lodash'
import { handleActions } from 'redux-actions'

const data = {
  start_date: moment().format('YYYY-MM-DD'),
  end_date: moment().format('YYYY-MM-DD'),
  data_type: 'campaign', // or date
  location_depth: 0,
  selected_campaign: null,
  selected_locations: [],
  selected_indicators: [],
  selected_indicator_tag: null,
  indicator_filter: { id: 1, value: 1, title: 'LPD 1', type: 'LPD Status' },
  datapoints: {meta: null, raw: null, flattened: null},
  dataParamsChanged: false
}

const data_entry = handleActions({
  SET_DATA_ENTRY_START_DATE: (state, action) => {
    return Object.assign({}, state, {
      start_date: action.payload,
      dataParamsChanged: true
    })
  },
  SET_DATA_ENTRY_END_DATE: (state, action) => {
    return Object.assign({}, state, {
      end_date: action.payload,
      dataParamsChanged: true
    })
  },
  TOGGLE_DATA_ENTRY_TYPE: (state, action) => {
    return Object.assign({}, data, {
      data_type: state.data_type === 'campaign' ? 'date' : 'campaign'
    })
  },
  GET_INITIAL_DATA_SUCCESS: (state, action) => {
    return Object.assign({}, state, {
      selected_campaign: action.payload.data.objects[0].campaigns[0]
    })
  },
  CLEAR_DATAPOINTS: (state, action) => {
    return Object.assign({}, state, {
      datapoints: {meta: null, raw: null, flattened: null},
      dataParamsChanged: false
    })
  },
  GET_DATAPOINTS_SUCCESS: (state, action) => {
    return Object.assign({}, state, {
      datapoints: {
        meta: action.payload.data.meta,
        raw: action.payload.data.objects,
        flattened: action.payload.data.objects
      },
      dataParamsChanged: false
    })
  },
  UPDATE_DATAPOINT_FAILURE: (state, action) => {
    return Object.assign({}, state, {
      dataParamsChanged: true
    })
  },
  SELECT_GLOBAL_CAMPAIGN: (state, action) => {
    return Object.assign({}, state, {
      selected_campaign: action.payload,
      dataParamsChanged: true
    })
  },
  SELECT_GLOBAL_LOCATION: (state, action) => {
    return Object.assign({}, state, {
      selected_locations: [...state.selected_locations, action.payload],
      dataParamsChanged: true
    })
  },
  SELECT_GLOBAL_LOCATION_DEPTH: (state, action) => {
    return Object.assign({}, state, {
      location_depth: action.payload
    })
  },
  SET_GLOBAL_LOCATIONS: (state, action) => {
    return Object.assign({}, state, {
      selected_locations: _.isArray(action.payload) ? action.payload : [action.payload],
      dataParamsChanged: true
    })
  },
  SET_GLOBAL_INDICATORS: (state, action) => {
    return Object.assign({}, state, {
      selected_indicators: _.isArray(action.payload) ? action.payload : [action.payload],
      dataParamsChanged: true
    })
  },
  SET_GLOBAL_INDICATOR_TAG: (state, action) => {
    return Object.assign({}, state, {
      selected_indicator_tag: action.payload
    })
  },
  SET_GLOBAL_INDICATOR_FILTER: (state, action) => {
    return Object.assign({}, state, {
      indicator_filter: action.payload,
      dataParamsChanged: true
    })
  }
}, data)

export default data_entry
<|endoftext|>


<commit_before>var gulp = require('gulp');
var babel = require('gulp-babel');
var watch = require('gulp-watch');
var concat     = require('gulp-concat');
var uglify = require('gulp-uglify');
var notify = require('gulp-notify');
var gulpUtil = require('gulp-util');
var ignore = require('gulp-ignore');

gulp.task('scripts', function() {
  return gulp.src([
    	'../src/app.js'
    ])
	  .pipe(concat('main.js'))
	  .pipe(babel())
	  .pipe(notify({message: 'Scripts task complete'}))
    .pipe(ignore.exclude([ "**/*.map" ]))
    .pipe(uglify())
    .pipe(gulp.dest('../dist'));
});

gulp.task('watch', function() {
  gulp.watch([
    '../src/app.js'
    ],['scripts']);
});

gulp.task('default', ['scripts', 'watch'], function () {
  // gulp do stuff...
});<commit_msg>Update gulpfile.js<commit_after>var gulp = require('gulp');
var babel = require('gulp-babel');
var watch = require('gulp-watch');
var concat     = require('gulp-concat');
var uglify = require('gulp-uglify');
var notify = require('gulp-notify');
var gulpUtil = require('gulp-util');
var ignore = require('gulp-ignore');

gulp.task('scripts', function() {
  return gulp.src([
    	'../src/app.js'
    ])
    .pipe(concat('main.js'))
    .pipe(babel())
    .pipe(notify({message: 'Scripts task complete'}))
    .pipe(ignore.exclude([ "**/*.map" ]))
    .pipe(uglify())
    .pipe(gulp.dest('../dist'));
});

gulp.task('watch', function() {
  gulp.watch([
    '../src/app.js'
    ],['scripts']);
});

gulp.task('default', ['scripts', 'watch'], function () {
  // gulp do stuff...
});
<|endoftext|>


<commit_before>import React, { Component } from 'react';
if (process.env.WEBPACK) { var fabric = require('fabric');}
if (process.env.WEBPACK) require('./css/Image.scss');
import ControlContainer from './ControlsContainer';
import { connect } from 'react-redux';
import {setConfig, setFrame} from '../actions/image';

@connect((state) => {
  const {image} = state;
  return {image};
}, {setConfig, setFrame})
export default class Image extends Component {
  componentDidMount() {
    process.env.WEBPACK && this.initFabric();
    process.env.WEBPACK && this.getConfigs();
  }

  state = {
    color: '#fff',
    config: {}
  };

  canvasObj = {};

  getConfigs() {
    fetch('/image_builder_config.json')
      .then((response) => response.json())
      .then((data) => {
        this.setState({config: data});
        this.addBackground();
      });
  }

  addBackground = () => {
    const fjs = fabric.fabric;
    const imgUrl = this.state.config.background;
    const canvas = this.canvasObj;

    fjs.Image.fromURL(imgUrl, function(oImg) {
      oImg.setWidth(canvas.width);
      oImg.setHeight(canvas.height);
      canvas.setBackgroundImage(oImg, canvas.renderAll.bind(canvas), {
        originX: 'left',
        originY: 'top',
        left: 0,
        top: 0
      });
    });
  };

  initFabric() {
    const fjs = fabric.fabric;
    const canvas = this.canvasObj = new fjs.Canvas('canvas');
    var out_frame = new fjs.Rect({
      width: 160,
      height: 240,
      fill: 'rgba(0, 0, 0, 0)',
      selectable: false,
      stroke: 'rgba(0,255,0,1)',
      strokeWidth: 1,
      evented: false,
      left: 70,
      top: 40
    });

    canvas.add(out_frame);
    this.props.setFrame(out_frame);

    canvas.on('object:added', function(e) {
      out_frame.bringToFront();
    });
    canvas.on('object:moving', (e) => {
      const obj = e.target;
      let angleLeft = 0;
      let realLeft = obj.left;
      let diagonal = Math.sqrt(Math.pow(e.target.width * e.target.scaleX, 2) + Math.pow(e.target.height * e.target.scaleY, 2));
      console.log(e.target, 'angle=',  e.target.angle, 'top=', obj.top, 'left=', obj.left, 'width=', e.target.width, 'height=', e.target.height);

      if (e.target.angle < 46 && e.target.angle !== 0) {
        angleLeft = (diagonal * (e.target.angle / 0.45 / 100)) / 2;
      }
      realLeft = realLeft - angleLeft;
      console.log('realLeft=', realLeft, 'angleLeft=', angleLeft, 'obj.left=', obj.left, 'diagonal=', diagonal);

      if (realLeft < 0) {
        obj.setLeft(angleLeft);
      }

      if (obj.top < 0) {
        obj.setTop(0);
      }

      if (obj.height * obj.scaleY + obj.top > e.target.canvas.height) {
        const top = e.target.canvas.height - obj.height * obj.scaleY;
        console.log('top', top);
        top > 0 && obj.setTop(top);
      }

      if (obj.width * obj.scaleX + obj.left > e.target.canvas.width) {
        const left = e.target.canvas.width - obj.width * obj.scaleX;
        console.log('left', left);
        left > 0 && obj.setLeft(left);
      }
    });
  }

  render() {
    const {config} = this.state;
    return (

{config.title}

        <canvas id="canvas" width="300" height="300"></canvas>
        {process.env.WEBPACK && <ControlContainer config={config} fabric={fabric.fabric} canvas={this.canvasObj}/>}

);
  }
}
<commit_msg>removed unnecessary code<commit_after>import React, { Component } from 'react';
if (process.env.WEBPACK) { var fabric = require('fabric');}
if (process.env.WEBPACK) require('./css/Image.scss');
import ControlContainer from './ControlsContainer';
import { connect } from 'react-redux';
import {setConfig, setFrame} from '../actions/image';

@connect((state) => {
  const {image} = state;
  return {image};
}, {setConfig, setFrame})
export default class Image extends Component {
  componentDidMount() {
    process.env.WEBPACK && this.initFabric();
    process.env.WEBPACK && this.getConfigs();
  }

  state = {
    color: '#fff',
    config: {}
  };

  canvasObj = {};

  getConfigs() {
    fetch('/image_builder_config.json')
      .then((response) => response.json())
      .then((data) => {
        this.setState({config: data});
        this.addBackground();
      });
  }

  addBackground = () => {
    const fjs = fabric.fabric;
    const imgUrl = this.state.config.background;
    const canvas = this.canvasObj;

    fjs.Image.fromURL(imgUrl, function(oImg) {
      oImg.setWidth(canvas.width);
      oImg.setHeight(canvas.height);
      canvas.setBackgroundImage(oImg, canvas.renderAll.bind(canvas), {
        originX: 'left',
        originY: 'top',
        left: 0,
        top: 0
      });
    });
  };

  initFabric() {
    const fjs = fabric.fabric;
    const canvas = this.canvasObj = new fjs.Canvas('canvas');
    var out_frame = new fjs.Rect({
      width: 160,
      height: 240,
      fill: 'rgba(0, 0, 0, 0)',
      selectable: false,
      stroke: 'rgba(0,255,0,1)',
      strokeWidth: 1,
      evented: false,
      left: 70,
      top: 40
    });

    canvas.add(out_frame);
    this.props.setFrame(out_frame);
  }

  render() {
    const {config} = this.state;
    return (

{config.title}

        <canvas id="canvas" width="300" height="300"></canvas>
        {process.env.WEBPACK && <ControlContainer config={config} fabric={fabric.fabric} canvas={this.canvasObj}/>}

);
  }
}
<|endoftext|>


<commit_before>if (typeof jQuery === "undefined") {
    throw new Error("jQuery plugins need to be before this file");
}

$.AdminBSB = {};
$.AdminBSB.options = {
    colors: {
        red: '#F44336',
        pink: '#E91E63',
        purple: '#9C27B0',
        deepPurple: '#673AB7',
        indigo: '#3F51B5',
        blue: '#2196F3',
        lightBlue: '#03A9F4',
        cyan: '#00BCD4',
        teal: '#009688',
        green: '#4CAF50',
        lightGreen: '#8BC34A',
        lime: '#CDDC39',
        yellow: '#ffe821',
        amber: '#FFC107',
        orange: '#FF9800',
        deepOrange: '#FF5722',
        brown: '#795548',
        grey: '#9E9E9E',
        blueGrey: '#607D8B',
        black: '#000000',
        white: '#ffffff'
    },
    leftSideBar: {
        scrollColor: 'rgba(0,0,0,0.5)',
        scrollWidth: '4px',
        scrollAlwaysVisible: false,
        scrollBorderRadius: '0',
        scrollRailBorderRadius: '0',
        scrollActiveItemWhenPageLoad: true,
        breakpointWidth: 1170
    },
    dropdownMenu: {
        effectIn: 'fadeIn',
        effectOut: 'fadeOut'
    }
}

/* Left Sidebar - Function =================================================================================================
*  You can manage the left sidebar menu options
*
*/
$.AdminBSB.leftSideBar = {
    activate: function () {
        var _this = this;
        var $body = $('body');
        var $overlay = $('.overlay');

        //Close sidebar
        $(window).click(function (e) {
            var $target = $(e.target);
            if (e.target.nodeName.toLowerCase() === 'i') { $target = $(e.target).parent(); }

            if (!$target.hasClass('bars') && _this.isOpen() && $target.parents('#leftsidebar').length === 0) {
                if (!$target.hasClass('js-right-sidebar')) $overlay.fadeOut();
                $body.removeClass('overlay-open');
            }
        });

        $.each($('.menu-toggle.toggled'), function (i, val) {
            $(val).next().slideToggle(0);
        });

        //When page load
        $.each($('.menu .list li.active'), function (i, val) {
            var $activeAnchors = $(val).find('a:eq(0)');

            $activeAnchors.addClass('toggled');
            $activeAnchors.next().show();
        });

        //Collapse or Expand Menu
        $('.menu-toggle').on('click', function (e) {
            var $this = $(this);
            var $content = $this.next();

            if ($($this.parents('ul')[0]).hasClass('list')) {
                var $not = $(e.target).hasClass('menu-toggle') ? e.target : $(e.target).parents('.menu-toggle');

                $.each($('.menu-toggle.toggled').not($not).next(), function (i, val) {
                    if ($(val).is(':visible')) {
                        $(val).prev().toggleClass('toggled');
                        $(val).slideUp();
                    }
                });
            }

            $this.toggleClass('toggled');
            $content.slideToggle(320);
        });

        //Set menu height
        _this.setMenuHeight();
        _this.checkStatuForResize(true);
        $(window).resize(function () {
            _this.setMenuHeight();
            _this.checkStatuForResize(false);
        });

        //Set Waves
        Waves.attach('.menu .list a', ['waves-block']);
        Waves.init();
    },
    setMenuHeight: function (isFirstTime) {
        if (typeof $.fn.slimScroll != 'undefined') {
            var configs = $.AdminBSB.options.leftSideBar;
            var height = ($(window).height() - ($('.legal').outerHeight() + $('.user-info').outerHeight() + $('.navbar').innerHeight()));
            var $el = $('.list');

            $el.slimscroll({
                height: height + "px",
                color: configs.scrollColor,
                size: configs.scrollWidth,
                alwaysVisible: configs.scrollAlwaysVisible,
                borderRadius: configs.scrollBorderRadius,
                railBorderRadius: configs.scrollRailBorderRadius
            });

            //Scroll active menu item when page load, if option set = true
            if ($.AdminBSB.options.leftSideBar.scrollActiveItemWhenPageLoad) {
                var activeItemOffsetTop = $('.menu .list li.active')[0].offsetTop
                if (activeItemOffsetTop > 150) $el.slimscroll({ scrollTo: activeItemOffsetTop + 'px' });
            }
        }
    },
    checkStatuForResize: function (firstTime) {
        var $body = $('body');
        var $openCloseBar = $('.navbar .navbar-header .bars');
        var width = $body.width();

        if (firstTime) {
            $body.find('.content, .sidebar').addClass('no-animate').delay(1000).queue(function () {
                $(this).removeClass('no-animate').dequeue();
            });
        }

        if (width < $.AdminBSB.options.leftSideBar.breakpointWidth) {
            $body.addClass('ls-closed');
            $openCloseBar.fadeIn();
        }
        else {
            $body.removeClass('ls-closed');
            $openCloseBar.fadeOut();
        }
    },
    isOpen: function () {
        return $('body').hasClass('overlay-open');
    }
};
//==========================================================================================================================

/* Right Sidebar - Function ================================================================================================
*  You can manage the right sidebar menu options
*
*/
$.AdminBSB.rightSideBar = {
    activate: function () {
        var _this = this;
        var $sidebar = $('#rightsidebar');
        var $overlay = $('.overlay');

        //Close sidebar
        $(window).click(function (e) {
            var $target = $(e.target);
            if (e.target.nodeName.toLowerCase() === 'i') { $target = $(e.target).parent(); }

            if (!$target.hasClass('js-right-sidebar') && _this.isOpen() && $target.parents('#rightsidebar').length === 0) {
                if (!$target.hasClass('bars')) $overlay.fadeOut();
                $sidebar.removeClass('open');
            }
        });

        $('.js-right-sidebar').on('click', function () {
            $sidebar.toggleClass('open');
            if (_this.isOpen()) { $overlay.fadeIn(); } else { $overlay.fadeOut(); }
        });
    },
    isOpen: function () {
        return $('.right-sidebar').hasClass('open');
    }
}
//==========================================================================================================================

/* Searchbar - Function ================================================================================================
*  You can manage the search bar
*
*/
var $searchBar = $('.search-bar');
$.AdminBSB.search = {
    activate: function () {
        var _this = this;

        //Search button click event
        $('.js-search').on('click', function () {
            _this.showSearchBar();
        });

        //Close search click event
        $searchBar.find('.close-search').on('click', function () {
            _this.hideSearchBar();
        });

        //ESC key on pressed
        $searchBar.find('input[type="text"]').on('keyup', function (e) {
            if (e.keyCode == 27) {
                _this.hideSearchBar();
            }
        });
    },
    showSearchBar: function () {
        $searchBar.addClass('open');
        $searchBar.find('input[type="text"]').focus();
    },
    hideSearchBar: function () {
        $searchBar.removeClass('open');
        $searchBar.find('input[type="text"]').val('');
    }
}
//==========================================================================================================================

/* Navbar - Function =======================================================================================================
*  You can manage the navbar
*
*/
$.AdminBSB.navbar = {
    activate: function () {
        var $body = $('body');
        var $overlay = $('.overlay');

        //Open left sidebar panel
        $('.bars').on('click', function () {
            $body.toggleClass('overlay-open');
            if ($body.hasClass('overlay-open')) { $overlay.fadeIn(); } else { $overlay.fadeOut(); }
        });

        //Close collapse bar on click event
        $('.nav [data-close="true"]').on('click', function () {
            var isVisible = $('.navbar-toggle').is(':visible');
            var $navbarCollapse = $('.navbar-collapse');

            if (isVisible) {
                $navbarCollapse.slideUp(function () {
                    $navbarCollapse.removeClass('in').removeAttr('style');
                });
            }
        });
    }
}
//==========================================================================================================================

/* Input - Function ========================================================================================================
*  You can manage the inputs(also textareas) with name of class 'form-control'
*
*/
$.AdminBSB.input = {
    activate: function () {
        //On focus event
        $('.form-control').focus(function () {
            $(this).parent().addClass('focused');
        });

        //On focusout event
        $('.form-control').focusout(function () {
            var $this = $(this);
            if ($this.parents('.form-group').hasClass('form-float')) {
                if ($this.val() == '') { $this.parents('.form-line').removeClass('focused'); }
            }
            else {
                $this.parents('.form-line').removeClass('focused');
            }
        });

        //On label click
        $('body').on('click', '.form-float .form-line .form-label', function () {
            $(this).parent().find('input').focus();
        });

        //Not blank form
        $('.form-control').each(function () {
            if ($(this).val() !== '') {
                $(this).parents('.form-line').addClass('focused');
            }
        });
    }
}
//==========================================================================================================================

/* Form - Select - Function ================================================================================================
*  You can manage the 'select' of form elements
*
*/
$.AdminBSB.select = {
    activate: function () {
        if ($.fn.selectpicker) { $('select:not(.ms)').selectpicker(); }
    }
}
//==========================================================================================================================

/* DropdownMenu - Function =================================================================================================
*  You can manage the dropdown menu
*
*/

$.AdminBSB.dropdownMenu = {
    activate: function () {
        var _this = this;

        $('.dropdown, .dropup, .btn-group').on({
            "show.bs.dropdown": function () {
                var dropdown = _this.dropdownEffect(this);
                _this.dropdownEffectStart(dropdown, dropdown.effectIn);
            },
            "shown.bs.dropdown": function () {
                var dropdown = _this.dropdownEffect(this);
                if (dropdown.effectIn && dropdown.effectOut) {
                    _this.dropdownEffectEnd(dropdown, function () { });
                }
            },
            "hide.bs.dropdown": function (e) {
                var dropdown = _this.dropdownEffect(this);
                if (dropdown.effectOut) {
                    e.preventDefault();
                    _this.dropdownEffectStart(dropdown, dropdown.effectOut);
                    _this.dropdownEffectEnd(dropdown, function () {
                        dropdown.dropdown.removeClass('open');
                    });
                }
            }
        });

        //Set Waves
        Waves.attach('.dropdown-menu li a', ['waves-block']);
        Waves.init();
    },
    dropdownEffect: function (target) {
        var effectIn = $.AdminBSB.options.dropdownMenu.effectIn, effectOut = $.AdminBSB.options.dropdownMenu.effectOut;
        var dropdown = $(target), dropdownMenu = $('.dropdown-menu', target);

        if (dropdown.length > 0) {
            var udEffectIn = dropdown.data('effect-in');
            var udEffectOut = dropdown.data('effect-out');
            if (udEffectIn !== undefined) { effectIn = udEffectIn; }
            if (udEffectOut !== undefined) { effectOut = udEffectOut; }
        }

        return {
            target: target,
            dropdown: dropdown,
            dropdownMenu: dropdownMenu,
            effectIn: effectIn,
            effectOut: effectOut
        };
    },
    dropdownEffectStart: function (data, effectToStart) {
        if (effectToStart) {
            data.dropdown.addClass('dropdown-animating');
            data.dropdownMenu.addClass('animated dropdown-animated');
            data.dropdownMenu.addClass(effectToStart);
        }
    },
    dropdownEffectEnd: function (data, callback) {
        var animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
        data.dropdown.one(animationEnd, function () {
            data.dropdown.removeClass('dropdown-animating');
            data.dropdownMenu.removeClass('animated dropdown-animated');
            data.dropdownMenu.removeClass(data.effectIn);
            data.dropdownMenu.removeClass(data.effectOut);

            if (typeof callback == 'function') {
                callback();
            }
        });
    }
}
//==========================================================================================================================

/* Browser - Function ======================================================================================================
*  You can manage browser
*
*/
var edge = 'Microsoft Edge';
var ie10 = 'Internet Explorer 10';
var ie11 = 'Internet Explorer 11';
var opera = 'Opera';
var firefox = 'Mozilla Firefox';
var chrome = 'Google Chrome';
var safari = 'Safari';

$.AdminBSB.browser = {
    activate: function () {
        var _this = this;
        var className = _this.getClassName();

        if (className !== '') $('html').addClass(_this.getClassName());
    },
    getBrowser: function () {
        var userAgent = navigator.userAgent.toLowerCase();

        if (/edge/i.test(userAgent)) {
            return edge;
        } else if (/rv:11/i.test(userAgent)) {
            return ie11;
        } else if (/msie 10/i.test(userAgent)) {
            return ie10;
        } else if (/opr/i.test(userAgent)) {
            return opera;
        } else if (/chrome/i.test(userAgent)) {
            return chrome;
        } else if (/firefox/i.test(userAgent)) {
            return firefox;
        } else if (!!navigator.userAgent.match(/Version\/[\d\.]+.*Safari/)) {
            return safari;
        }

        return undefined;
    },
    getClassName: function () {
        var browser = this.getBrowser();

        if (browser === edge) {
            return 'edge';
        } else if (browser === ie11) {
            return 'ie11';
        } else if (browser === ie10) {
            return 'ie10';
        } else if (browser === opera) {
            return 'opera';
        } else if (browser === chrome) {
            return 'chrome';
        } else if (browser === firefox) {
            return 'firefox';
        } else if (browser === safari) {
            return 'safari';
        } else {
            return '';
        }
    }
}
//==========================================================================================================================

$(function () {
    $.AdminBSB.browser.activate();
    $.AdminBSB.leftSideBar.activate();
    $.AdminBSB.rightSideBar.activate();
    $.AdminBSB.navbar.activate();
    $.AdminBSB.dropdownMenu.activate();
    $.AdminBSB.input.activate();
    $.AdminBSB.select.activate();
    $.AdminBSB.search.activate();

    setTimeout(function () { $('.page-loader-wrapper').fadeOut(); }, 50);
});<commit_msg>set menu breakpointWidth<commit_after>if (typeof jQuery === "undefined") {
    throw new Error("jQuery plugins need to be before this file");
}

$.AdminBSB = {};
$.AdminBSB.options = {
    colors: {
        red: '#F44336',
        pink: '#E91E63',
        purple: '#9C27B0',
        deepPurple: '#673AB7',
        indigo: '#3F51B5',
        blue: '#2196F3',
        lightBlue: '#03A9F4',
        cyan: '#00BCD4',
        teal: '#009688',
        green: '#4CAF50',
        lightGreen: '#8BC34A',
        lime: '#CDDC39',
        yellow: '#ffe821',
        amber: '#FFC107',
        orange: '#FF9800',
        deepOrange: '#FF5722',
        brown: '#795548',
        grey: '#9E9E9E',
        blueGrey: '#607D8B',
        black: '#000000',
        white: '#ffffff'
    },
    leftSideBar: {
        scrollColor: 'rgba(0,0,0,0.5)',
        scrollWidth: '4px',
        scrollAlwaysVisible: false,
        scrollBorderRadius: '0',
        scrollRailBorderRadius: '0',
        scrollActiveItemWhenPageLoad: true,
        breakpointWidth: 1770
    },
    dropdownMenu: {
        effectIn: 'fadeIn',
        effectOut: 'fadeOut'
    }
}

/* Left Sidebar - Function =================================================================================================
*  You can manage the left sidebar menu options
*
*/
$.AdminBSB.leftSideBar = {
    activate: function () {
        var _this = this;
        var $body = $('body');
        var $overlay = $('.overlay');

        //Close sidebar
        $(window).click(function (e) {
            var $target = $(e.target);
            if (e.target.nodeName.toLowerCase() === 'i') { $target = $(e.target).parent(); }

            if (!$target.hasClass('bars') && _this.isOpen() && $target.parents('#leftsidebar').length === 0) {
                if (!$target.hasClass('js-right-sidebar')) $overlay.fadeOut();
                $body.removeClass('overlay-open');
            }
        });

        $.each($('.menu-toggle.toggled'), function (i, val) {
            $(val).next().slideToggle(0);
        });

        //When page load
        $.each($('.menu .list li.active'), function (i, val) {
            var $activeAnchors = $(val).find('a:eq(0)');

            $activeAnchors.addClass('toggled');
            $activeAnchors.next().show();
        });

        //Collapse or Expand Menu
        $('.menu-toggle').on('click', function (e) {
            var $this = $(this);
            var $content = $this.next();

            if ($($this.parents('ul')[0]).hasClass('list')) {
                var $not = $(e.target).hasClass('menu-toggle') ? e.target : $(e.target).parents('.menu-toggle');

                $.each($('.menu-toggle.toggled').not($not).next(), function (i, val) {
                    if ($(val).is(':visible')) {
                        $(val).prev().toggleClass('toggled');
                        $(val).slideUp();
                    }
                });
            }

            $this.toggleClass('toggled');
            $content.slideToggle(320);
        });

        //Set menu height
        _this.setMenuHeight();
        _this.checkStatuForResize(true);
        $(window).resize(function () {
            _this.setMenuHeight();
            _this.checkStatuForResize(false);
        });

        //Set Waves
        Waves.attach('.menu .list a', ['waves-block']);
        Waves.init();
    },
    setMenuHeight: function (isFirstTime) {
        if (typeof $.fn.slimScroll != 'undefined') {
            var configs = $.AdminBSB.options.leftSideBar;
            var height = ($(window).height() - ($('.legal').outerHeight() + $('.user-info').outerHeight() + $('.navbar').innerHeight()));
            var $el = $('.list');

            $el.slimscroll({
                height: height + "px",
                color: configs.scrollColor,
                size: configs.scrollWidth,
                alwaysVisible: configs.scrollAlwaysVisible,
                borderRadius: configs.scrollBorderRadius,
                railBorderRadius: configs.scrollRailBorderRadius
            });

            //Scroll active menu item when page load, if option set = true
            if ($.AdminBSB.options.leftSideBar.scrollActiveItemWhenPageLoad) {
                var activeItemOffsetTop = $('.menu .list li.active')[0].offsetTop
                if (activeItemOffsetTop > 150) $el.slimscroll({ scrollTo: activeItemOffsetTop + 'px' });
            }
        }
    },
    checkStatuForResize: function (firstTime) {
        var $body = $('body');
        var $openCloseBar = $('.navbar .navbar-header .bars');
        var width = $body.width();

        if (firstTime) {
            $body.find('.content, .sidebar').addClass('no-animate').delay(1000).queue(function () {
                $(this).removeClass('no-animate').dequeue();
            });
        }

        if (width < $.AdminBSB.options.leftSideBar.breakpointWidth) {
            $body.addClass('ls-closed');
            $openCloseBar.fadeIn();
        }
        else {
            $body.removeClass('ls-closed');
            $openCloseBar.fadeOut();
        }
    },
    isOpen: function () {
        return $('body').hasClass('overlay-open');
    }
};
//==========================================================================================================================

/* Right Sidebar - Function ================================================================================================
*  You can manage the right sidebar menu options
*
*/
$.AdminBSB.rightSideBar = {
    activate: function () {
        var _this = this;
        var $sidebar = $('#rightsidebar');
        var $overlay = $('.overlay');

        //Close sidebar
        $(window).click(function (e) {
            var $target = $(e.target);
            if (e.target.nodeName.toLowerCase() === 'i') { $target = $(e.target).parent(); }

            if (!$target.hasClass('js-right-sidebar') && _this.isOpen() && $target.parents('#rightsidebar').length === 0) {
                if (!$target.hasClass('bars')) $overlay.fadeOut();
                $sidebar.removeClass('open');
            }
        });

        $('.js-right-sidebar').on('click', function () {
            $sidebar.toggleClass('open');
            if (_this.isOpen()) { $overlay.fadeIn(); } else { $overlay.fadeOut(); }
        });
    },
    isOpen: function () {
        return $('.right-sidebar').hasClass('open');
    }
}
//==========================================================================================================================

/* Searchbar - Function ================================================================================================
*  You can manage the search bar
*
*/
var $searchBar = $('.search-bar');
$.AdminBSB.search = {
    activate: function () {
        var _this = this;

        //Search button click event
        $('.js-search').on('click', function () {
            _this.showSearchBar();
        });

        //Close search click event
        $searchBar.find('.close-search').on('click', function () {
            _this.hideSearchBar();
        });

        //ESC key on pressed
        $searchBar.find('input[type="text"]').on('keyup', function (e) {
            if (e.keyCode == 27) {
                _this.hideSearchBar();
            }
        });
    },
    showSearchBar: function () {
        $searchBar.addClass('open');
        $searchBar.find('input[type="text"]').focus();
    },
    hideSearchBar: function () {
        $searchBar.removeClass('open');
        $searchBar.find('input[type="text"]').val('');
    }
}
//==========================================================================================================================

/* Navbar - Function =======================================================================================================
*  You can manage the navbar
*
*/
$.AdminBSB.navbar = {
    activate: function () {
        var $body = $('body');
        var $overlay = $('.overlay');

        //Open left sidebar panel
        $('.bars').on('click', function () {
            $body.toggleClass('overlay-open');
            if ($body.hasClass('overlay-open')) { $overlay.fadeIn(); } else { $overlay.fadeOut(); }
        });

        //Close collapse bar on click event
        $('.nav [data-close="true"]').on('click', function () {
            var isVisible = $('.navbar-toggle').is(':visible');
            var $navbarCollapse = $('.navbar-collapse');

            if (isVisible) {
                $navbarCollapse.slideUp(function () {
                    $navbarCollapse.removeClass('in').removeAttr('style');
                });
            }
        });
    }
}
//==========================================================================================================================

/* Input - Function ========================================================================================================
*  You can manage the inputs(also textareas) with name of class 'form-control'
*
*/
$.AdminBSB.input = {
    activate: function () {
        //On focus event
        $('.form-control').focus(function () {
            $(this).parent().addClass('focused');
        });

        //On focusout event
        $('.form-control').focusout(function () {
            var $this = $(this);
            if ($this.parents('.form-group').hasClass('form-float')) {
                if ($this.val() == '') { $this.parents('.form-line').removeClass('focused'); }
            }
            else {
                $this.parents('.form-line').removeClass('focused');
            }
        });

        //On label click
        $('body').on('click', '.form-float .form-line .form-label', function () {
            $(this).parent().find('input').focus();
        });

        //Not blank form
        $('.form-control').each(function () {
            if ($(this).val() !== '') {
                $(this).parents('.form-line').addClass('focused');
            }
        });
    }
}
//==========================================================================================================================

/* Form - Select - Function ================================================================================================
*  You can manage the 'select' of form elements
*
*/
$.AdminBSB.select = {
    activate: function () {
        if ($.fn.selectpicker) { $('select:not(.ms)').selectpicker(); }
    }
}
//==========================================================================================================================

/* DropdownMenu - Function =================================================================================================
*  You can manage the dropdown menu
*
*/

$.AdminBSB.dropdownMenu = {
    activate: function () {
        var _this = this;

        $('.dropdown, .dropup, .btn-group').on({
            "show.bs.dropdown": function () {
                var dropdown = _this.dropdownEffect(this);
                _this.dropdownEffectStart(dropdown, dropdown.effectIn);
            },
            "shown.bs.dropdown": function () {
                var dropdown = _this.dropdownEffect(this);
                if (dropdown.effectIn && dropdown.effectOut) {
                    _this.dropdownEffectEnd(dropdown, function () { });
                }
            },
            "hide.bs.dropdown": function (e) {
                var dropdown = _this.dropdownEffect(this);
                if (dropdown.effectOut) {
                    e.preventDefault();
                    _this.dropdownEffectStart(dropdown, dropdown.effectOut);
                    _this.dropdownEffectEnd(dropdown, function () {
                        dropdown.dropdown.removeClass('open');
                    });
                }
            }
        });

        //Set Waves
        Waves.attach('.dropdown-menu li a', ['waves-block']);
        Waves.init();
    },
    dropdownEffect: function (target) {
        var effectIn = $.AdminBSB.options.dropdownMenu.effectIn, effectOut = $.AdminBSB.options.dropdownMenu.effectOut;
        var dropdown = $(target), dropdownMenu = $('.dropdown-menu', target);

        if (dropdown.length > 0) {
            var udEffectIn = dropdown.data('effect-in');
            var udEffectOut = dropdown.data('effect-out');
            if (udEffectIn !== undefined) { effectIn = udEffectIn; }
            if (udEffectOut !== undefined) { effectOut = udEffectOut; }
        }

        return {
            target: target,
            dropdown: dropdown,
            dropdownMenu: dropdownMenu,
            effectIn: effectIn,
            effectOut: effectOut
        };
    },
    dropdownEffectStart: function (data, effectToStart) {
        if (effectToStart) {
            data.dropdown.addClass('dropdown-animating');
            data.dropdownMenu.addClass('animated dropdown-animated');
            data.dropdownMenu.addClass(effectToStart);
        }
    },
    dropdownEffectEnd: function (data, callback) {
        var animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
        data.dropdown.one(animationEnd, function () {
            data.dropdown.removeClass('dropdown-animating');
            data.dropdownMenu.removeClass('animated dropdown-animated');
            data.dropdownMenu.removeClass(data.effectIn);
            data.dropdownMenu.removeClass(data.effectOut);

            if (typeof callback == 'function') {
                callback();
            }
        });
    }
}
//==========================================================================================================================

/* Browser - Function ======================================================================================================
*  You can manage browser
*
*/
var edge = 'Microsoft Edge';
var ie10 = 'Internet Explorer 10';
var ie11 = 'Internet Explorer 11';
var opera = 'Opera';
var firefox = 'Mozilla Firefox';
var chrome = 'Google Chrome';
var safari = 'Safari';

$.AdminBSB.browser = {
    activate: function () {
        var _this = this;
        var className = _this.getClassName();

        if (className !== '') $('html').addClass(_this.getClassName());
    },
    getBrowser: function () {
        var userAgent = navigator.userAgent.toLowerCase();

        if (/edge/i.test(userAgent)) {
            return edge;
        } else if (/rv:11/i.test(userAgent)) {
            return ie11;
        } else if (/msie 10/i.test(userAgent)) {
            return ie10;
        } else if (/opr/i.test(userAgent)) {
            return opera;
        } else if (/chrome/i.test(userAgent)) {
            return chrome;
        } else if (/firefox/i.test(userAgent)) {
            return firefox;
        } else if (!!navigator.userAgent.match(/Version\/[\d\.]+.*Safari/)) {
            return safari;
        }

        return undefined;
    },
    getClassName: function () {
        var browser = this.getBrowser();

        if (browser === edge) {
            return 'edge';
        } else if (browser === ie11) {
            return 'ie11';
        } else if (browser === ie10) {
            return 'ie10';
        } else if (browser === opera) {
            return 'opera';
        } else if (browser === chrome) {
            return 'chrome';
        } else if (browser === firefox) {
            return 'firefox';
        } else if (browser === safari) {
            return 'safari';
        } else {
            return '';
        }
    }
}
//==========================================================================================================================

$(function () {
    $.AdminBSB.browser.activate();
    $.AdminBSB.leftSideBar.activate();
    $.AdminBSB.rightSideBar.activate();
    $.AdminBSB.navbar.activate();
    $.AdminBSB.dropdownMenu.activate();
    $.AdminBSB.input.activate();
    $.AdminBSB.select.activate();
    $.AdminBSB.search.activate();

    setTimeout(function () { $('.page-loader-wrapper').fadeOut(); }, 50);
});<|endoftext|>


<commit_before>'use strict';

/*!
 * Jessel John - May, 04, 2014
 * MIT Licence
 */
! function(window, document, undefined) {
    angular.module('ng.resourceloader',[])
        .directive('ngLazyLoadImg', ['$window', '$timeout', function($window, $timeout) {
            var objOfOnLoadImgElems = {},
                objOfLazyImgElems = {},
                objOfLazyImgElemsInViewport = {},
                arrOfPrevDisplayedElements = [],
                loadTimeoutId,
                scrollTimeoutId,
                resizeTimeoutId,
                ngLazyLoadImg = {
                    scope: {
                        'defaultImage': '=?',
                        'unLoadOnScroll': '=?',
                        'imgsrc': '=',
                        'onWinLoad': '=?'
                    },
                    replace: true,
                    template: function(elem, attrs) {
                        return attrs.elemType == 'img' ?
                            '' :
                            '

';
                    },
                    restrict: 'E',
                    controllerAs: 'tyShow',
                    controller: ['$scope', '$element',
                        function($scope, $element) {
                            var that = this,
                                $elementOffsetTop = $element[0].getBoundingClientRect().top;

                            function populateLazyElemsFn(obj) {
                                if (obj[$elementOffsetTop] === undefined) {
                                    obj[$elementOffsetTop] = [];
                                }
                                obj[$elementOffsetTop].push({
                                    'that': that,
                                    'scope': $scope,
                                    'elem': $element
                                });
                            }

                            that.imgsrc = $scope.defaultImage;

                            if (!$scope.onWinLoad) {
                                $scope.unLoadOnScroll = $scope.unLoadOnScroll === undefined ? true : $scope.unLoadOnScroll;
                                populateLazyElemsFn(objOfLazyImgElems);
                            } else {
                                $scope.unLoadOnScroll = $scope.unLoadOnScroll === undefined ? false : $scope.unLoadOnScroll;
                                populateLazyElemsFn(objOfOnLoadImgElems);
                            }

                            $timeout.cancel(loadTimeoutId);
                            loadTimeoutId = $timeout(executeWhenAllLoaded, 300);
                        }
                    ],
                    link: function postLink(scope, element, attrs) {}
                };

            function getDocumentHeight() {
                var body = document.body,
                    html = document.documentElement,
                    height = Math.max(body.scrollHeight, body.offsetHeight,
                        html.clientHeight, html.scrollHeight, html.offsetHeight);

                return height;
            }

            function setImageIfInViewportFn(obj, forceLoad) {
                var doc = document.documentElement,
                    $windowScrollTop = ($window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0),
                    $windowHeight = window.outerHeight,
                    $documentHeight = getDocumentHeight(),
                    arrOfPrevDisplayedElementsCopy = arrOfPrevDisplayedElements;

                arrOfPrevDisplayedElements = [];
                arrOfPrevDisplayedElementsCopy.forEach(function(item, index) {
                    var eachElemClientRect = item.elem[0].getBoundingClientRect(),
                        $elementOffsetTop = eachElemClientRect.top +
                        ($windowScrollTop - $windowHeight),
                        offsetTop = (eachElemClientRect.height !== 0 ? $elementOffsetTop : $documentHeight + 10);
                    if ((offsetTop < $windowScrollTop - $windowHeight - eachElemClientRect.height) || offsetTop > $windowScrollTop) {
                        item.scope.loaded = false;
                    }
                });
                for (var a in obj) {
                    var eachBlock = obj[a];
                    for (var i = 0, len = eachBlock.length; i < len; i++) {
                        var img = document.createElement('img');
                        img.src = eachBlock[i].scope.imgsrc;
                        img.onload = function(eachElem) {
                            if (eachElem.scope.unLoadOnScroll) {
                                arrOfPrevDisplayedElements.push(eachElem);
                            }
                            return function() {
                                eachElem.that.imgsrc = eachElem.scope.imgsrc;
                                eachElem.scope.loaded = true;
                                eachElem.scope.$digest();
                            }
                        }(eachBlock[i]);

                        img.onerror = function(eachElem) {
                            return function() {
                                eachElem.scope.loaded = true;
                                eachElem.scope.$digest();
                            }
                        }(eachBlock[i]);
                    }
                }
            }

            function addValueToObjArrProp(obj, prop, value) {
                if (obj[prop] === undefined) {
                    obj[prop] = [];
                }

                obj[prop].push(value);
            }

            function recalculateOffsetFn() {
                var lazyObjCopy = objOfLazyImgElems,
                    doc = document.documentElement,
                    $windowScrollTop = ($window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0),
                    $windowHeight = window.outerHeight,
                    $documentHeight = getDocumentHeight();
                objOfLazyImgElemsInViewport = {};
                objOfLazyImgElems = {};

                for (var a in lazyObjCopy) {
                    var eachObj = lazyObjCopy[a];
                    for (var i = 0, len = eachObj.length; i < len; i++) {
                        var eachElem = eachObj[i],
                            eachElemClientRect = eachElem.elem[0].getBoundingClientRect(),
                            $elementOffsetTop = eachElemClientRect.top +
                            ($windowScrollTop - $windowHeight),
                            offsetTop = (eachElemClientRect.height !== 0 ? $elementOffsetTop : $documentHeight + 10),
                            newEachElemObj = {
                                'that': eachElem.that,
                                'scope': eachElem.scope,
                                'elem': eachElem.elem
                            };

                        addValueToObjArrProp(objOfLazyImgElems, offsetTop, newEachElemObj);

                        if ((offsetTop >= $windowScrollTop - $windowHeight - eachElemClientRect.height) && offsetTop < $windowScrollTop) {
                            addValueToObjArrProp(objOfLazyImgElemsInViewport, offsetTop, newEachElemObj);
                        }
                    }
                }
            }

            function executeWhenAllLoaded() {
                setImageIfInViewportFn(objOfOnLoadImgElems, true);
                recalculateOffsetFn();
                setImageIfInViewportFn(objOfLazyImgElemsInViewport, false);
            }

            window.addEventListener('scroll', function() {
                $timeout.cancel(scrollTimeoutId);
                scrollTimeoutId = $timeout(function() {
                    recalculateOffsetFn();
                    setImageIfInViewportFn(objOfLazyImgElemsInViewport, false);
                }, 300);
            }, false);

            window.addEventListener('resize', function() {
                $timeout.cancel(resizeTimeoutId);
                resizeTimeoutId = $timeout(function() {
                    recalculateOffsetFn();
                    setImageIfInViewportFn(objOfLazyImgElemsInViewport, false);
                }, 300);
            }, false);

            return ngLazyLoadImg;
        }]);
}(window, document);

<commit_msg>Update imageloader.js<commit_after>'use strict';

/*!
 * Jessel John - May, 04, 2014
 * MIT Licence
 */
! function(window, document, undefined) {
    angular.module('ng.resourceloader',[])
        .directive('ngLazyLoadImg', ['$window', '$rootScope', '$timeout', function($window, $rootScope, $timeout) {
            var objOfOnLoadImgElems = {},
                objOfLazyImgElems = {},
                objOfLazyImgElemsInViewport = {},
                arrOfPrevDisplayedElements = [],
                loadTimeoutId,
                scrollTimeoutId,
                resizeTimeoutId,
                ngLazyLoadImg = {
                    scope: {
                        'defaultImage': '=?',
                        'unLoadOnScroll': '=?',
                        'imgsrc': '=',
                        'onWinLoad': '=?'
                    },
                    replace: true,
                    template: function(elem, attrs) {
                        return attrs.elemType == 'img' ?
                            '' :
                            '

';
                    },
                    restrict: 'E',
                    controllerAs: 'tyShow',
                    controller: ['$scope', '$element',
                        function($scope, $element) {
                            var that = this,
                                $elementOffsetTop = $element[0].getBoundingClientRect().top;

                            function populateLazyElemsFn(obj) {
                                if (obj[$elementOffsetTop] === undefined) {
                                    obj[$elementOffsetTop] = [];
                                }
                                obj[$elementOffsetTop].push({
                                    'that': that,
                                    'scope': $scope,
                                    'elem': $element
                                });
                            }

                            that.imgsrc = $scope.defaultImage;

                            if (!$scope.onWinLoad) {
                                $scope.unLoadOnScroll = $scope.unLoadOnScroll === undefined ? true : $scope.unLoadOnScroll;
                                populateLazyElemsFn(objOfLazyImgElems);
                            } else {
                                $scope.unLoadOnScroll = $scope.unLoadOnScroll === undefined ? false : $scope.unLoadOnScroll;
                                populateLazyElemsFn(objOfOnLoadImgElems);
                            }

                            $timeout.cancel(loadTimeoutId);
                            loadTimeoutId = $timeout(executeWhenAllLoaded, 300);
                        }
                    ],
                    link: function postLink(scope, element, attrs) {}
                };

            function getDocumentHeight() {
                var body = document.body,
                    html = document.documentElement,
                    height = Math.max(body.scrollHeight, body.offsetHeight,
                        html.clientHeight, html.scrollHeight, html.offsetHeight);

                return height;
            }

            function setImageIfInViewportFn(obj, forceLoad) {
                var doc = document.documentElement,
                    $windowScrollTop = ($window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0),
                    $windowHeight = window.outerHeight,
                    $documentHeight = getDocumentHeight(),
                    arrOfPrevDisplayedElementsCopy = arrOfPrevDisplayedElements;

                arrOfPrevDisplayedElements = [];
                arrOfPrevDisplayedElementsCopy.forEach(function(item, index) {
                    var eachElemClientRect = item.elem[0].getBoundingClientRect(),
                        $elementOffsetTop = eachElemClientRect.top +
                        ($windowScrollTop - $windowHeight),
                        offsetTop = (eachElemClientRect.height !== 0 ? $elementOffsetTop : $documentHeight + 10);
                    if ((offsetTop < $windowScrollTop - $windowHeight - eachElemClientRect.height) || offsetTop > $windowScrollTop) {
                        item.scope.loaded = false;
                    }
                });
                for (var a in obj) {
                    var eachBlock = obj[a];
                    for (var i = 0, len = eachBlock.length; i < len; i++) {
                        var img = document.createElement('img');
                        img.src = eachBlock[i].scope.imgsrc;
                        img.onload = function(eachElem) {
                            if (eachElem.scope.unLoadOnScroll) {
                                arrOfPrevDisplayedElements.push(eachElem);
                            }
                            return function() {
                                eachElem.that.imgsrc = eachElem.scope.imgsrc;
                                eachElem.scope.loaded = true;
                                eachElem.scope.$digest();
                            }
                        }(eachBlock[i]);

                        img.onerror = function(eachElem) {
                            return function() {
                                eachElem.scope.loaded = true;
                                eachElem.scope.$digest();
                            }
                        }(eachBlock[i]);
                    }
                }
            }

            function addValueToObjArrProp(obj, prop, value) {
                if (obj[prop] === undefined) {
                    obj[prop] = [];
                }

                obj[prop].push(value);
            }

            function recalculateOffsetFn() {
                var lazyObjCopy = objOfLazyImgElems,
                    doc = document.documentElement,
                    $windowScrollTop = ($window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0),
                    $windowHeight = window.outerHeight,
                    $documentHeight = getDocumentHeight();
                objOfLazyImgElemsInViewport = {};
                objOfLazyImgElems = {};

                for (var a in lazyObjCopy) {
                    var eachObj = lazyObjCopy[a];
                    for (var i = 0, len = eachObj.length; i < len; i++) {
                        var eachElem = eachObj[i],
                            eachElemClientRect = eachElem.elem[0].getBoundingClientRect(),
                            $elementOffsetTop = eachElemClientRect.top +
                            ($windowScrollTop - $windowHeight),
                            offsetTop = (eachElemClientRect.height !== 0 ? $elementOffsetTop : $documentHeight + 10),
                            newEachElemObj = {
                                'that': eachElem.that,
                                'scope': eachElem.scope,
                                'elem': eachElem.elem
                            };

                        addValueToObjArrProp(objOfLazyImgElems, offsetTop, newEachElemObj);

                        if ((offsetTop >= $windowScrollTop - $windowHeight - eachElemClientRect.height) && offsetTop < $windowScrollTop) {
                            addValueToObjArrProp(objOfLazyImgElemsInViewport, offsetTop, newEachElemObj);
                        }
                    }
                }
            }

            function executeWhenAllLoaded() {
                setImageIfInViewportFn(objOfOnLoadImgElems, true);
                recalculateOffsetFn();
                setImageIfInViewportFn(objOfLazyImgElemsInViewport, false);
            }

            window.addEventListener('scroll', function() {
                $timeout.cancel(scrollTimeoutId);
                scrollTimeoutId = $timeout(function() {
                    recalculateOffsetFn();
                    setImageIfInViewportFn(objOfLazyImgElemsInViewport, false);
                }, 300);
            }, false);

            window.addEventListener('resize', function() {
                $timeout.cancel(resizeTimeoutId);
                resizeTimeoutId = $timeout(function() {
                    recalculateOffsetFn();
                    setImageIfInViewportFn(objOfLazyImgElemsInViewport, false);
                }, 300);
            }, false);

            $rootScope.$on('trigger.lazyload', function(e) {
                $timeout(function() {
                    recalculateOffsetFn();
                    setImageIfInViewportFn(objOfLazyImgElemsInViewport, false);
                }, 300);
            });

            return ngLazyLoadImg;
        }]);
}(window, document);

<|endoftext|>


<commit_before>var Board = function( attributes ){
  this.humanoid;
  this.dx = 0;
  this.dy = 0;
  this.humanoids = attributes.humanoids || [];
  this.width = attributes.width  || '600px';
  this.height = attributes.height || '400px';
}

Board.prototype = {
  isPositionEqual: function( position1, position2 ){
    return position1.x === position2.x && position1.y === position2.y
  },
  isValidDestination: function( target_position ){
    var result = true
    for(var i= 0; i < this.humanoids.length; i++ ){
      if( this.isPositionEqual( this.humanoids[i].position , target_position ) ){
        result = false
      }
    }
    return result
  },

  nearestHumanoid: function( humanoidType ){
    var similarHumanoids = this.findSimilarHumanoids( humanoidType )
    var closestPos = this.findClosestPos( similarHumanoids )
    var closestHumanoid = this.findClosestHumanoid( closestPos, similarHumanoids )
    return closestHumanoid
  },

  isAnyHumanRemaining: function(){
    var result = false
    for( var i=0; i < this.humanoids.length; i++ ){
      if(this.humanoids[i].humanType == "human") { result = true; break };
    }
    return result
  },

  nextTurn: function(){
    for( var i=0; i< this.humanoids.length; i++ ){
      this.humanoid = this.humanoids[i]
      if( this.humanoid.humanType == "infectedHuman" ){
          this.humanoid.incrementTimeSinceInfection()
          continue
      }
      if( this.humanoid.humanType == "player" ){
        var coords = ( Pathfinder.playerMove(this.humanoid.position, this.dx, this.dy, this.humanoid.speed) )
        coords.x = ( (coords.x + this.width) % this.width )
        coords.y = ( (coords.y + this.height) % this.height )
        this.humanoid.position = coords
        continue
      }
      var nearestZombie = this.nearestHumanoid( "zombie" )
      var nearestHuman = this.nearestHumanoid( "human" )
      var player = this.nearestHumanoid( 'player' )
      var destination = this.setDestination( nearestHuman, nearestZombie, player )
      destination.x = ( (destination.x + this.width) % this.width )
      destination.y = ( (destination.y + this.height) % this.height )

      if ( this.humanoid.isAbleToBite( player ) ){
        this.humanoid.bite( player )
      }

      if ( this.humanoid.isAbleToBite( nearestHuman ) ){
        this.humanoid.bite( nearestHuman )
      }

      if( this.isValidDestination( destination ) ){
        this.humanoid.position = destination
      }
    };
  },

  setDestination: function( nearestHuman, nearestZombie, player ){
    if( !nearestHuman ) { return this.humanoid.moveNearest(  nearestZombie  )}
    else if( this.humanoid.humanType == "zombie" ){ return this.setZombieDestination( nearestHuman, nearestZombie, player ) }
    else if( this.humanoid.humanType == "human" ){ return this.setHumanDestination( nearestHuman, nearestZombie ) }
    else { return this.humanoid.position }
  },

  setZombieDestination: function( nearestHuman, nearestZombie, player ){
    var playerDistance = Pathfinder.distanceTo( player.position, this.humanoid.position )
    var humanDistance = Pathfinder.distanceTo( nearestHuman.position, this.humanoid.position )
    var zombieDistance = Pathfinder.distanceTo( nearestZombie.position, this.humanoid.position ) * gameSettings.zombieSpread
    if ( playerDistance < humanDistance ){
      if ( playerDistance < zombieDistance ){
        return this.humanoid.moveNearest( player )
      } else {
        return this.humanoid.moveNearest( nearestZombie )
      }
    } else if ( humanDistance < zombieDistance ){
      return this.humanoid.moveNearest( nearestHuman )
    } else {
      return this.humanoid.moveNearest( nearestZombie )
    }
  },
  setHumanDestination: function( nearestHuman, nearestZombie ){
    if ( Pathfinder.distanceTo( nearestZombie.position, this.humanoid.position ) < gameSettings.humanFearRange ){
      return this.humanoid.moveNearest( nearestZombie )
    }
    else {
      return this.humanoid.moveNearest( nearestHuman )
    }
  },

  deleteSelfHumanoid: function(){
    var otherHumanoids = []
    for( var i=0; i < this.humanoids.length; i++){otherHumanoids.push(this.humanoids[i])}

    for( var i=0; i < this.humanoids.length; i++ ){
      if( this.isPositionEqual( this.humanoids[i].position , this.humanoid.position ) ){
        otherHumanoids.splice( i, 1 )
        break
      }
    }
    return otherHumanoids
  },
  findSimilarHumanoids: function( humanoidType ){
    var otherHumanoids = this.deleteSelfHumanoid()
    var similar = [];
    for( var i=0; i< otherHumanoids.length; i++ ){
      if( otherHumanoids[i].humanType === humanoidType ){ similar.push(otherHumanoids[i])}
    }
    return similar
  },
  findClosestPos: function( otherHumanoids ){
    var closestPos = []
    for( var i=0; i< otherHumanoids.length; i++ ){
      var dist = Pathfinder.distanceTo( otherHumanoids[i].position, this.humanoid.position )
      closestPos.push( dist );
    }
    return closestPos
  },
  findClosestHumanoid: function( closestPos, otherHumanoids ){
    var closestHumanoidValue = Math.min.apply( null, closestPos )
    for( var i=0; i < closestPos.length; i++ ){
      if( closestPos[i] == closestHumanoidValue ){ var closestHumanoid = otherHumanoids[i]}
    }
   return closestHumanoid
  }
}
<commit_msg>complete zombie movement functionality. requires refactor<commit_after>var Board = function( attributes ){
  this.humanoid;
  this.dx = 0;
  this.dy = 0;
  this.humanoids = attributes.humanoids || [];
  this.width = attributes.width  || '600px';
  this.height = attributes.height || '400px';
}

Board.prototype = {
  isPositionEqual: function( position1, position2 ){
    return position1.x === position2.x && position1.y === position2.y
  },
  isValidDestination: function( target_position ){
    var result = true
    for(var i= 0; i < this.humanoids.length; i++ ){
      if( this.isPositionEqual( this.humanoids[i].position , target_position ) ){
        result = false
      }
    }
    return result
  },

  nearestHumanoid: function( humanoidType ){
    var similarHumanoids = this.findSimilarHumanoids( humanoidType )
    var closestPos = this.findClosestPos( similarHumanoids )
    var closestHumanoid = this.findClosestHumanoid( closestPos, similarHumanoids )
    return closestHumanoid
  },

  isAnyHumanRemaining: function(){
    var result = false
    for( var i=0; i < this.humanoids.length; i++ ){
      if(this.humanoids[i].humanType == "human"  || this.humanoids[i].humanType == "player") { result = true; break };
    }
    return result
  },

  nextTurn: function(){
    for( var i=0; i< this.humanoids.length; i++ ){
      this.humanoid = this.humanoids[i]
      if( this.humanoid.humanType == "infectedHuman" ){
          this.humanoid.incrementTimeSinceInfection()
          continue
      }
      if( this.humanoid.humanType == "player" ){
        var coords = ( Pathfinder.playerMove(this.humanoid.position, this.dx, this.dy, this.humanoid.speed) )
        coords.x = ( (coords.x + this.width) % this.width )
        coords.y = ( (coords.y + this.height) % this.height )
        this.humanoid.position = coords
        continue
      }
      var nearestZombie = this.nearestHumanoid( "zombie" )
      var nearestHuman = this.nearestHumanoid( "human" )
      var player = this.nearestHumanoid( 'player' )
      var destination = this.setDestination( nearestHuman, nearestZombie, player )
      destination.x = ( (destination.x + this.width) % this.width )
      destination.y = ( (destination.y + this.height) % this.height )

      if ( this.humanoid.isAbleToBite( player ) ){
        this.humanoid.bite( player )
      }

      if ( this.humanoid.isAbleToBite( nearestHuman ) ){
        this.humanoid.bite( nearestHuman )
      }

      if( this.isValidDestination( destination ) ){
        this.humanoid.position = destination
      }
    };
  },

  setDestination: function( nearestHuman, nearestZombie, player ){
    if( !nearestHuman ) { return this.humanoid.moveNearest(  nearestZombie  )}
    else if( this.humanoid.humanType == "zombie" ){ return this.setZombieDestination( nearestHuman, nearestZombie, player ) }
    else if( this.humanoid.humanType == "human" ){ return this.setHumanDestination( nearestHuman, nearestZombie ) }
    else { return this.humanoid.position }
  },

  setZombieDestination: function( nearestHuman, nearestZombie, player ){
    var playerDistance = Number.POSITIVE_INFINITY;
    var humanDistance = Number.POSITIVE_INFINITY;
    var zombieDistance = Pathfinder.distanceTo( nearestZombie.position, this.humanoid.position ) * gameSettings.zombieSpread
    if (player){ playerDistance = Pathfinder.distanceTo( player.position, this.humanoid.position ) }
    if (nearestHuman){ humanDistance = Pathfinder.distanceTo( nearestHuman.position, this.humanoid.position ) }

    if ( playerDistance < humanDistance ){
      if ( playerDistance < zombieDistance ){
        return this.humanoid.moveNearest( player )
      } else {
        return this.humanoid.moveNearest( nearestZombie )
      }
    } else if ( humanDistance < zombieDistance ){
      return this.humanoid.moveNearest( nearestHuman )
    } else {
      return this.humanoid.moveNearest( nearestZombie )
    }
  },

  setHumanDestination: function( nearestHuman, nearestZombie ){
    if ( Pathfinder.distanceTo( nearestZombie.position, this.humanoid.position ) < gameSettings.humanFearRange ){
      return this.humanoid.moveNearest( nearestZombie )
    }
    else {
      return this.humanoid.moveNearest( nearestHuman )
    }
  },

  deleteSelfHumanoid: function(){
    var otherHumanoids = []
    for( var i=0; i < this.humanoids.length; i++){otherHumanoids.push(this.humanoids[i])}

    for( var i=0; i < this.humanoids.length; i++ ){
      if( this.isPositionEqual( this.humanoids[i].position , this.humanoid.position ) ){
        otherHumanoids.splice( i, 1 )
        break
      }
    }
    return otherHumanoids
  },
  findSimilarHumanoids: function( humanoidType ){
    var otherHumanoids = this.deleteSelfHumanoid()
    var similar = [];
    for( var i=0; i< otherHumanoids.length; i++ ){
      if( otherHumanoids[i].humanType === humanoidType ){ similar.push(otherHumanoids[i])}
    }
    return similar
  },
  findClosestPos: function( otherHumanoids ){
    var closestPos = []
    for( var i=0; i< otherHumanoids.length; i++ ){
      var dist = Pathfinder.distanceTo( otherHumanoids[i].position, this.humanoid.position )
      closestPos.push( dist );
    }
    return closestPos
  },
  findClosestHumanoid: function( closestPos, otherHumanoids ){
    var closestHumanoidValue = Math.min.apply( null, closestPos )
    for( var i=0; i < closestPos.length; i++ ){
      if( closestPos[i] == closestHumanoidValue ){ var closestHumanoid = otherHumanoids[i]}
    }
   return closestHumanoid
  }
}
<|endoftext|>