<commit_before>import React from 'react';
import { noop } from 'lodash';
import {
  arrayOf,
  shape,
  string,
  number,
  bool,
  func,
  objectOf,
  any,
  object,
  oneOfType
} from 'prop-types';
import { connect } from 'react-redux';
import { Player, ControlBar, BigPlayButton } from 'video-react';

import {
  BoundingPolyOverlay,
  OverlayPositioningProvider
} from 'veritone-react-common';
import VideoSource from './VideoSource';
import { getPolysForTime } from './helpers';

import styles from './styles.scss';

@connect(state => ({
  videoHeight: state.player.videoHeight,
  videoWidth: state.player.videoWidth,
  hasStarted: state.player.hasStarted,
  isActive: state.player.isActive,
  currentTime: state.player.currentTime,
  paused: state.player.paused
}))
class MediaPlayerComponent extends React.Component {
  static propTypes = {
    src: string,
    streams: arrayOf(
      shape({
        protocol: string,
        uri: string
      })
    ),
    boundingPolySeries: arrayOf(
      shape({
        startTimeMs: number.isRequired,
        stopTimeMs: number.isRequired,
        object: shape({
          id: string.isRequired,
          overlayObjectType: string,
          boundingPoly: arrayOf(
            shape({ x: number.isRequired, y: number.isRequired })
          ).isRequired
        })
      })
    ),
    onAddBoundingBox: func,
    onDeleteBoundingBox: func,
    onChangeBoundingBox: func,

    defaultBoundingBoxStyles: objectOf(any),
    stagedBoundingBoxStyles: objectOf(any),
    stylesByObjectType: objectOf(objectOf(any)),

    actionMenuItems: arrayOf(
      shape({
        label: string.isRequired,
        onClick: func.isRequired
      })
    ),
    readOnly: bool,
    addOnly: bool,
    autoCommit: bool,
    width: oneOfType([string, number]),
    height: oneOfType([string, number]),
    // fluid = 100% width by default, see video-react docs
    fluid: bool,
    videoHeight: number,
    videoWidth: number,
    hasStarted: bool,
    isActive: bool,
    paused: bool,
    currentTime: number,
    forwardedRef: objectOf(any)
  };

  static contextTypes = {
    // need to pass our app's redux store to the Player, or else it will create
    // its own internal store that we can't integrate with
    store: object
  };

  static defaultProps = {
    fluid: true,
    onAddBoundingBox: noop,
    onDeleteBoundingBox: noop,
    onChangeBoundingBox: noop
  };

  handleAddBoundingBox = newBox => {
    this.props.onAddBoundingBox(newBox, this.props.currentTime * 1000);
  };

  render() {
    const { src, streams, ...props } = this.props;

    const currentPolys = getPolysForTime(
      this.props.boundingPolySeries || [],
      this.props.currentTime * 1000
    );

    return (
      <OverlayPositioningProvider
        contentHeight={this.props.videoHeight}
        contentWidth={this.props.videoWidth}
        fixedWidth={!props.fluid}
      >
        {this.props.hasStarted && (
          <BoundingPolyOverlay
            wrapperStyles={{ zIndex: 100 }}
            onAddBoundingBox={this.handleAddBoundingBox}
            onDeleteBoundingBox={this.props.onDeleteBoundingBox}
            onChangeBoundingBox={this.props.onChangeBoundingBox}
            initialBoundingBoxPolys={
              this.props.boundingPolySeries ? currentPolys : undefined
            }
            actionMenuItems={this.props.actionMenuItems}
            addOnly={this.props.addOnly}
            readOnly={this.props.readOnly || !this.props.paused}
            autoCommit={this.props.autoCommit}
            stagedBoundingBoxStyles={props.stagedBoundingBoxStyles}
            stylesByObjectType={props.stylesByObjectType}
            defaultBoundingBoxStyles={props.defaultBoundingBoxStyles}
          />
        )}
        <Player
          className={styles.mediaPlayer}
          ref={this.props.forwardedRef}
          store={this.context.store}
          {...props}
        >
          {/* prevent video-react from adding its own control bar */}
          <ControlBar autoHide className={styles.hiddenDummyControls} />

          <VideoSource isVideoChild src={src} streams={streams} />
          <BigPlayButton position="center" className={styles.mediaPlayButton} />
        </Player>
      </OverlayPositioningProvider>
    );
  }
}

const MediaPlayer = React.forwardRef((props, ref) => {
  return <MediaPlayerComponent {...props} forwardedRef={ref} />;
});

export { MediaPlayer };
<commit_msg>pass thru autofocus flag to media player overlay<commit_after>import React from 'react';
import { noop } from 'lodash';
import {
  arrayOf,
  shape,
  string,
  number,
  bool,
  func,
  objectOf,
  any,
  object,
  oneOfType
} from 'prop-types';
import { connect } from 'react-redux';
import { Player, ControlBar, BigPlayButton } from 'video-react';

import {
  BoundingPolyOverlay,
  OverlayPositioningProvider
} from 'veritone-react-common';
import VideoSource from './VideoSource';
import { getPolysForTime } from './helpers';

import styles from './styles.scss';

@connect(state => ({
  videoHeight: state.player.videoHeight,
  videoWidth: state.player.videoWidth,
  hasStarted: state.player.hasStarted,
  isActive: state.player.isActive,
  currentTime: state.player.currentTime,
  paused: state.player.paused
}))
class MediaPlayerComponent extends React.Component {
  static propTypes = {
    src: string,
    streams: arrayOf(
      shape({
        protocol: string,
        uri: string
      })
    ),
    boundingPolySeries: arrayOf(
      shape({
        startTimeMs: number.isRequired,
        stopTimeMs: number.isRequired,
        object: shape({
          id: string.isRequired,
          overlayObjectType: string,
          boundingPoly: arrayOf(
            shape({ x: number.isRequired, y: number.isRequired })
          ).isRequired
        })
      })
    ),
    onAddBoundingBox: func,
    onDeleteBoundingBox: func,
    onChangeBoundingBox: func,

    defaultBoundingBoxStyles: objectOf(any),
    stagedBoundingBoxStyles: objectOf(any),
    stylesByObjectType: objectOf(objectOf(any)),

    actionMenuItems: arrayOf(
      shape({
        label: string.isRequired,
        onClick: func.isRequired
      })
    ),
    readOnly: bool,
    addOnly: bool,
    autoCommit: bool,
    width: oneOfType([string, number]),
    height: oneOfType([string, number]),
    // fluid = 100% width by default, see video-react docs
    fluid: bool,
    videoHeight: number,
    videoWidth: number,
    hasStarted: bool,
    isActive: bool,
    paused: bool,
    currentTime: number,
    autofocus: bool,
    forwardedRef: objectOf(any)
  };

  static contextTypes = {
    // need to pass our app's redux store to the Player, or else it will create
    // its own internal store that we can't integrate with
    store: object
  };

  static defaultProps = {
    fluid: true,
    onAddBoundingBox: noop,
    onDeleteBoundingBox: noop,
    onChangeBoundingBox: noop
  };

  handleAddBoundingBox = newBox => {
    this.props.onAddBoundingBox(newBox, this.props.currentTime * 1000);
  };

  render() {
    const { src, streams, ...props } = this.props;

    const currentPolys = getPolysForTime(
      this.props.boundingPolySeries || [],
      this.props.currentTime * 1000
    );

    return (
      <OverlayPositioningProvider
        contentHeight={this.props.videoHeight}
        contentWidth={this.props.videoWidth}
        fixedWidth={!props.fluid}
      >
        {this.props.hasStarted && (
          <BoundingPolyOverlay
            wrapperStyles={{ zIndex: 100 }}
            onAddBoundingBox={this.handleAddBoundingBox}
            onDeleteBoundingBox={this.props.onDeleteBoundingBox}
            onChangeBoundingBox={this.props.onChangeBoundingBox}
            initialBoundingBoxPolys={
              this.props.boundingPolySeries ? currentPolys : undefined
            }
            actionMenuItems={this.props.actionMenuItems}
            addOnly={this.props.addOnly}
            readOnly={this.props.readOnly || !this.props.paused}
            autoCommit={this.props.autoCommit}
            stagedBoundingBoxStyles={props.stagedBoundingBoxStyles}
            stylesByObjectType={props.stylesByObjectType}
            defaultBoundingBoxStyles={props.defaultBoundingBoxStyles}
            autofocus={props.autofocus}
          />
        )}
        <Player
          className={styles.mediaPlayer}
          ref={this.props.forwardedRef}
          store={this.context.store}
          {...props}
        >
          {/* prevent video-react from adding its own control bar */}
          <ControlBar autoHide className={styles.hiddenDummyControls} />

          <VideoSource isVideoChild src={src} streams={streams} />
          <BigPlayButton position="center" className={styles.mediaPlayButton} />
        </Player>
      </OverlayPositioningProvider>
    );
  }
}

const MediaPlayer = React.forwardRef((props, ref) => {
  return <MediaPlayerComponent {...props} forwardedRef={ref} />;
});

export { MediaPlayer };
<|endoftext|>


<commit_before>
/**
 *  Optimistic cache updates
 */
import Mingo from 'mingo';

/**
 * Safe getter
 * Must returns null if the document is absent (eg in case of validation failure)
 * TODO: use this getter
 * @param {*} mutation
 * @param {*} mutationName
 */
const getDocumentFromMutation = (mutation, mutationName) => {
    const mutationData = (mutation.result.data[mutationName] || {});
    const document = mutationData.data;
    return document;
};

// When using multi queries, we can't track all parameters, which are sadly needed
// by cache.readQuery for optimistic updates.
// This function can get a list of queries based on their name and should solve this issue
// @see https://gist.github.com/ngryman/6856c7eb8f9a15b1095032a6ba478c5c
// @see https://github.com/apollographql/react-apollo/issues/708#issuecomment-506975142
// @see https://github.com/apollographql/apollo-client/issues/3505
// @see https://github.com/apollographql/apollo-client/issues/3505#issuecomment-535388194
export const getVariablesListFromCache = (proxy, queryName) => {
    //const queryName = query.definitions[0].name.value;
    const rootQuery = proxy.data.data.ROOT_QUERY;

    // XXX: When using `optimisticResponse`, `proxy.data.data` resolves to
    // another cache that doesn't contain the root query.
    if (!rootQuery) return [];

    const matchQueryReducer = (names, name) => {
        // TODO: can be improved with a regex so "customer" matched only "customer(*)"
        // this may match too many items
        if (name.startsWith(queryName + '(')) {
            names.push(name);
        }
        return names;
    };

    const parseQueryNameToVariables = (name) =>
        JSON.parse((name.match(/{.*}/))[0]);

    return Object.keys(rootQuery)
        .reduce(matchQueryReducer, [])
        .map(parseQueryNameToVariables);
};

/*

Test if a document is already in a result set

*/
export const isInData = ({ queryResult, multiResolverName, document }) => positionInSet(queryResult[multiResolverName].results, document) === -1;

export const positionInSet = (results, document) => results.findIndex(item => item._id && (item._id === document._id));

/*

Reorder results according to a sort

*/
export const reorderSet = (results, sort, selector) => {
    const mingoQuery = new Mingo.Query(selector);
    const cursor = mingoQuery.find(results);
    const sortedResults = cursor.sort(sort).all();
    return sortedResults;
};

/**
 * Add to data
 * @param {*} queryData
 * @param {*} document
 */
export const addToData = ({ queryResult, multiResolverName, document, sort, selector }) => {
    const queryData = queryResult[multiResolverName];
    let { results, totalCount } = queryData;
    const idx = positionInSet(results, document);
    let newResults = [...results];
    if (idx !== -1) {
        // doc has already been added, eg after an optimistic response
        // update it
        newResults[idx] = document;
    } else {
        // add to list
        newResults.unshift(document);
        totalCount = totalCount + 1;
    }
    // sort if necessary
    if (sort) {
        newResults = reorderSet(newResults, sort, selector);
    }
    return {
        ...queryResult,
        [multiResolverName]: {
            ...queryData,
            // TODO: check order using mingo
            results: newResults,
            totalCount
        }
    };
};

export const removeFromData = ({ queryResult, multiResolverName, document }) => {
    const queryData = queryResult[multiResolverName];
    return {
        ...queryResult,
        [multiResolverName]: {
            ...queryData,
            results: queryData.results.filter(item => item._id !== document._id),
            totalCount: Math.max(0, queryData.totalCount - 1)
        }
    };
};

/*

Test if a document is matched by a given selector

*/
export const matchSelector = (document, selector) => {
    const mingoQuery = new Mingo.Query(selector);
    return mingoQuery.test(document);
};

/*

Add a document to a set of results

*/
// export const addToSet = (queryData, document) => {
//   const newData = {
//     ...queryData,
//     results: [...queryData.results, document],
//     totalCount: queryData.totalCount + 1,
//   };
//   return newData;
// };

/*

Update a document in a set of results

*/
// TODO: legacy, not used anymore because Apollo handles it out of the box
/* export const updateInSet = (queryData, document) => {
  const oldDocument = queryData.results.find(item => item._id === document._id);
  const newDocument = { ...oldDocument, ...document };
  const index = queryData.results.findIndex(item => item._id === document._id);
  const newData = { ...queryData, results: [...queryData.results] }; // clone
  newData.results[index] = newDocument;
  return newData;
};
*/
<commit_msg>comment in cacheUpdate.js<commit_after>
/**
 *  Optimistic cache updates
 */
import Mingo from 'mingo';

/**
 * Safe getter
 * Must returns null if the document is absent (eg in case of validation failure)
 * TODO: use this getter
 * @param {*} mutation
 * @param {*} mutationName
 */
const getDocumentFromMutation = (mutation, mutationName) => {
    const mutationData = (mutation.result.data[mutationName] || {});
    const document = mutationData.data;
    return document;
};

// When using multi queries, we can't track all parameters, which are sadly needed
// by cache.readQuery for optimistic updates.
// This function can get a list of queries based on their name and should solve this issue
// @see https://gist.github.com/ngryman/6856c7eb8f9a15b1095032a6ba478c5c
// @see https://github.com/apollographql/react-apollo/issues/708#issuecomment-506975142
// @see https://github.com/apollographql/apollo-client/issues/3505
// @see https://github.com/apollographql/apollo-client/issues/3505#issuecomment-535388194
export const getVariablesListFromCache = (proxy, queryName) => {
    //const queryName = query.definitions[0].name.value;
    const rootQuery = proxy.data.data.ROOT_QUERY;

    // XXX: When using `optimisticResponse`, `proxy.data.data` resolves to
    // another cache that doesn't contain the root query.
    if (!rootQuery) return [];

    // Customer(*) will be matched but no customer. This last one would cause an error in
    // JSON.parse. If wanted to be treated, parseQueryNameToVariables should be adapted
    const matchQueryReducer = (names, name) => {
        if (name.startsWith(queryName + '(')) {
            names.push(name);
        }
        return names;
    };

    const parseQueryNameToVariables = (name) =>
        JSON.parse((name.match(/{.*}/))[0]);

    return Object.keys(rootQuery)
        .reduce(matchQueryReducer, [])
        .map(parseQueryNameToVariables);
};

/*

Test if a document is already in a result set

*/
export const isInData = ({ queryResult, multiResolverName, document }) => positionInSet(queryResult[multiResolverName].results, document) === -1;

export const positionInSet = (results, document) => results.findIndex(item => item._id && (item._id === document._id));

/*

Reorder results according to a sort

*/
export const reorderSet = (results, sort, selector) => {
    const mingoQuery = new Mingo.Query(selector);
    const cursor = mingoQuery.find(results);
    const sortedResults = cursor.sort(sort).all();
    return sortedResults;
};

/**
 * Add to data
 * @param {*} queryData
 * @param {*} document
 */
export const addToData = ({ queryResult, multiResolverName, document, sort, selector }) => {
    const queryData = queryResult[multiResolverName];
    let { results, totalCount } = queryData;
    const idx = positionInSet(results, document);
    let newResults = [...results];
    if (idx !== -1) {
        // doc has already been added, eg after an optimistic response
        // update it
        newResults[idx] = document;
    } else {
        // add to list
        newResults.unshift(document);
        totalCount = totalCount + 1;
    }
    // sort if necessary
    if (sort) {
        newResults = reorderSet(newResults, sort, selector);
    }
    return {
        ...queryResult,
        [multiResolverName]: {
            ...queryData,
            // TODO: check order using mingo
            results: newResults,
            totalCount
        }
    };
};

export const removeFromData = ({ queryResult, multiResolverName, document }) => {
    const queryData = queryResult[multiResolverName];
    return {
        ...queryResult,
        [multiResolverName]: {
            ...queryData,
            results: queryData.results.filter(item => item._id !== document._id),
            totalCount: Math.max(0, queryData.totalCount - 1)
        }
    };
};

/*

Test if a document is matched by a given selector

*/
export const matchSelector = (document, selector) => {
    const mingoQuery = new Mingo.Query(selector);
    return mingoQuery.test(document);
};

/*

Add a document to a set of results

*/
// export const addToSet = (queryData, document) => {
//   const newData = {
//     ...queryData,
//     results: [...queryData.results, document],
//     totalCount: queryData.totalCount + 1,
//   };
//   return newData;
// };

/*

Update a document in a set of results

*/
// TODO: legacy, not used anymore because Apollo handles it out of the box
/* export const updateInSet = (queryData, document) => {
  const oldDocument = queryData.results.find(item => item._id === document._id);
  const newDocument = { ...oldDocument, ...document };
  const index = queryData.results.findIndex(item => item._id === document._id);
  const newData = { ...queryData, results: [...queryData.results] }; // clone
  newData.results[index] = newDocument;
  return newData;
};
*/
<|endoftext|>


<commit_before>
// limbus-buildgen - A "build anywhere" C/C++ makefile/project generator.
// Written in 2014-2016 by Jesper Oskarsson jesosk@gmail.com
//
// To the extent possible under law, the author(s) have dedicated all copyright
// and related and neighboring rights to this software to the public domain worldwide.
// This software is distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.

var should = require('should');
var util = require('./util.js');
var shell = require('./shell.js');
var minimal = require('../source/minimal-configuration');

describe('Architectures', function () {
    beforeEach(function () {
        return util.beforeEach();
    });

    afterEach(function () {
        return util.afterEach();
    });

    it('should compile for the correct architecture', function () {
        var builtExecutable = util.writeConfiguration(minimal.project())
        .then(util.generateWithParameters())
        .then(util.build());

        if (process.platform === 'win32') {
            return builtExecutable.then(function (executable) {
                return shell.exec('..\\utility-scripts\\setenv.bat && dumpbin /headers ' + executable, {cwd: 'temp'});
            }).then(function (output) {
                if (output.stdout.indexOf('PE32+') !== -1) {
                    util.hostArchitecture.should.equal('x64');

                } else if (output.stdout.indexOf('PE32') !== -1) {
                    util.hostArchitecture.should.equal('x86');

                } else {
                    return Promise.reject('Unknown platform:\n' + output.stdout);
                }
            });
        } else {
            return builtExecutable.then(function (executable) {
                return shell.exec('file ' + executable, {cwd: 'temp'});
            }).then(function (output) {
                if (output.stdout.indexOf('64-bit') !== -1) {
                    util.hostArchitecture.should.equal('x64');

                } else if (output.stdout.indexOf('86') !== -1) {
                    util.hostArchitecture.should.equal('x86');

                } else {
                    return Promise.reject('Unknown platform:\n' + output.stdout);
                }
            });
        }
    });
});
<commit_msg>Added /nologo to dump bin command<commit_after>
// limbus-buildgen - A "build anywhere" C/C++ makefile/project generator.
// Written in 2014-2016 by Jesper Oskarsson jesosk@gmail.com
//
// To the extent possible under law, the author(s) have dedicated all copyright
// and related and neighboring rights to this software to the public domain worldwide.
// This software is distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.

var should = require('should');
var util = require('./util.js');
var shell = require('./shell.js');
var minimal = require('../source/minimal-configuration');

describe('Architectures', function () {
    beforeEach(function () {
        return util.beforeEach();
    });

    afterEach(function () {
        return util.afterEach();
    });

    it('should compile for the correct architecture', function () {
        var builtExecutable = util.writeConfiguration(minimal.project())
        .then(util.generateWithParameters())
        .then(util.build());

        if (process.platform === 'win32') {
            return builtExecutable.then(function (executable) {
                return shell.exec('..\\utility-scripts\\setenv.bat && dumpbin /nologo /headers ' + executable, {cwd: 'temp'});
            }).then(function (output) {
                if (output.stdout.indexOf('PE32+') !== -1) {
                    util.hostArchitecture.should.equal('x64');

                } else if (output.stdout.indexOf('PE32') !== -1) {
                    util.hostArchitecture.should.equal('x86');

                } else {
                    return Promise.reject('Unknown platform:\n' + output.stdout);
                }
            });
        } else {
            return builtExecutable.then(function (executable) {
                return shell.exec('file ' + executable, {cwd: 'temp'});
            }).then(function (output) {
                if (output.stdout.indexOf('64-bit') !== -1) {
                    util.hostArchitecture.should.equal('x64');

                } else if (output.stdout.indexOf('86') !== -1) {
                    util.hostArchitecture.should.equal('x86');

                } else {
                    return Promise.reject('Unknown platform:\n' + output.stdout);
                }
            });
        }
    });
});
<|endoftext|>


<commit_before>/*
  General GridModel which generate whole slickGrid instance
  and can be extend with custom parameters.

  Using this library you avoid unnecessary work when constructing
  normal use-case slickGrid instance...
*/

var DataModel = function(options)
{
  var _defaults = {
    columnStaticFilter: columnStaticFilter,
    columnFilters: {},
    dataView: true,
    data: [],
    grid: false,
    dataUrl: false,
    images: {
      group: 'SlickGrid/images/arrow_right_peppermint.png',
    },
    dataComparer: comparer,
    getData: getData,
    useDataFlatter: true,
    useDataSorting: true,
    useDataGrouping: true,
    dataIdField: 'id',
    gridOptions: {
      enableColumnReorder: false,
      enableCellNavigation: true,
    },
    gridId: '#myGrid',
    slickPlugins: {
      groupItemMetadataProvider: {
        obj:  newGroupItemMetadataProvider
      },
      distinctMenu: {
        obj: true,
        options: {
          getDistinct: getStaticDistinct,
          doFilter: doStaticFilter,
        }
      },
      headerMenu: {
        obj: true,
        options: {}
      },
      headerButtons: {
        obj: true,
        options: {}
      }
    }
  }

  function Init(){
    options = $.extend(true, {}, _defaults, options);

    if( options.dataView === true ){
        var dataViewArgs = {}
        generateDataGroupMenus();
        if( options.useDataGrouping ){
          var groupItemMetadataProvider = options.slickPlugins.groupItemMetadataProvider.obj();
          options.slickPlugins.groupItemMetadataProvider.obj = groupItemMetadataProvider
          dataViewArgs = {
            groupItemMetadataProvider: groupItemMetadataProvider,
            inlineFilters: true
          }
        }
        options.dataView = newDataView(dataViewArgs);

    }
    //set data to dataView
    options.dataView.setItems(options.data);

    //set column filter
    options.dataView.setFilter(options.columnStaticFilter);
    //if grid is not yet created, create grid instance
    if(!options.grid)
      options.grid = new Slick.Grid(
        options.gridId,
        options.dataView,
        options.columns,
        options.gridOptions);
    // Make the grid respond to DataView change events.
    options.dataView.onRowCountChanged.subscribe(function (e, args) {
      options.grid.updateRowCount();
      options.grid.render();
    });
    options.dataView.onRowsChanged.subscribe(function (e, args) {
      options.grid.invalidateRows(args.rows);
      options.grid.render();
    });
    if( options.useDataGrouping){
      options.grid.registerPlugin(groupItemMetadataProvider);
    }
    if( options.useDataSorting ){
      options.grid.onSort.subscribe(function(e, args) {
        var comparer = function(a, b) {
          return a[args.sortCol.field] > b[args.sortCol.field];
        }
        options.dataView.sort(comparer, args.sortAsc);
      });
    }

    //add sort event handler
    options.grid.onSort.subscribe(function (e, args) {
      sortdir = args.sortAsc ? 1 : -1;
      sortcol = args.sortCol.field;
      options.dataView.sort(options.dataComparer, args.sortAsc);
    });

    //if headerMenu is purpose to use, create it
    if( options.slickPlugins.headerMenu.obj === true )
    {
      options.slickPlugins.headerMenu.obj = new Slick.Plugins.HeaderMenu(
        options.slickPlugins.headerMenu.options );
      options.grid.registerPlugin(options.slickPlugins.headerMenu.obj);
    }
    //if headerButtons is purpose to use, create it
    if( options.slickPlugins.headerButtons.obj === true )
    {
      options.slickPlugins.headerButtons.obj = new Slick.Plugins.HeaderButtons(
          options.slickPlugins.headerButtons.options);
      options.grid.registerPlugin(options.slickPlugins.headerButtons.obj);
      options.slickPlugins.headerButtons.obj.onCommand.subscribe(onCommand);
    }
    //if distinct menu is purpose to use create it
    if( options.slickPlugins.headerMenu.obj &&
        options.slickPlugins.distinctMenu.obj === true )
      // init distinctMenu
    {
      //Create distinctMenu instance
      options.slickPlugins.distinctMenu.obj = new Slick.Plugins.DistinctMenu(
       $.extend(true, {}, options.slickPlugins.distinctMenu.options, {
          headerMenu: options.slickPlugins.headerMenu.obj,
          columns: options.columns,
          }));
      //register distinctMenu
      options.grid.registerPlugin(options.slickPlugins.distinctMenu.obj);

      //and update menu items
      options.slickPlugins.distinctMenu.obj.update();

    }
    //if dataUrl is set, fetch data
    if( options.dataUrl ){
      options.getData( function(error, ok){
        //if data is fetched, update distinctMenu
        options.slickPlugins.distinctMenu.obj.update();
      });
    }
  }
  function onCommand(e, args)
  {
    if( args.command == 'group' ){
      onGroup(e, args);
      // Stop propagation so that it doesn't register as a header click event.
      e.preventDefault();
      e.stopPropagation();
    }
  }
  function onGroup(e, args){
    console.log('onGrouping..');
    var grouping = options.dataView.getGrouping();
    if( grouping.length == 0 || e.ctrlKey || e.altKey ){

      grouping.push({
        getter: args.column.id,
        formatter: function (g) {
          console.log(g);
          return args.column.name+":  " + g.value + "  (" + g.count + " items)";
        },
        collapsed: true,
        /*aggregators: [
          //new Slick.Data.Aggregators.Avg("percentComplete"),
          //new Slick.Data.Aggregators.Sum("cost")
        ],
        aggregateCollapsed: true
        */
      });
    } else {
      grouping = [];
    }
    options.dataView.setGrouping( grouping );
  }
  function generateDataGroupMenus(){
    for(var i in options.columns){
      var column = options.columns[i];
      $.extend(true, column, {header: {buttons: [
          {
            cssClass: 'slick-header-distinctbutton',
            image: options.images.group,
            command: 'group'}
          ]}});
    }
  }
  function columnStaticFilter(item) {
    for(var field in options.columnFilters)
    {
      if( item!==undefined && item[field]!== options.columnFilters[field] )
      {
        return false;
      }
    }
    return true;
  }
  function getData(callback){
    $.getJSON(options.url, null, function(data){
      if( options.useDataFlatter ){
        if( data.length > 0 ){
          var i, len=data.length;
          for(i=0;i<len;i++){
            data[i] = flatten(data[i]);
            if(options.dataIdField!='id')
              data[i].id = data[i][options.dataIdField];
          }
        }
      }
      options.dataView.beginUpdate();
      options.dataView.setItems(data);
      options.dataView.endUpdate();
      callback(null, data.length);
    })
  }
  function newGroupItemMetadataProvider(){
    return new Slick.Data.GroupItemMetadataProvider()
  }
  function newDataView(args){return new Slick.Data.DataView(args);}
  function getStaticDistinct(field, url, urlParameters, callback){
    function getDist(field){
      var i=0,list = [];
      options.data.forEach( function(row){
        if( row[field] && list.indexOf( row[field] )== -1 ){
          list.push( row[field] );
        }
      });
      return list;
    }
    callback(null,  getDist(field));
  }
  function doStaticFilter(field, condition, callback){
    console.log('doStaticFilter');
    options.columnFilters = {};
    for(var i=0;condition['$and'] && i<condition['$and'].length;i++){
      for(var key in condition['$and'][i] ){
        options.columnFilters[key] = condition['$and'][i][key];
      };
    }
    options.dataView.refresh();
    callback();
  }
  function comparer(a, b) {
    var x = a[sortcol], y = b[sortcol];
    return (x == y ? 0 : (x > y ? 1 : -1));
  }

  this.updateDistinct = function(){
    options.slickPlugins.distinctMenu.obj.update();
  }
  Init();
  return this;
}<commit_msg>Update DataModel.js<commit_after>/*
  General GridModel which generate whole slickGrid instance
  and can be extend with custom parameters.

  Using this library you avoid unnecessary work when constructing
  normal use-case slickGrid instance...
*/

var DataModel = function(options)
{
  var _defaults = {
    columnStaticFilter: columnStaticFilter,
    columnFilters: {},
    dataView: true,
    data: [],
    grid: false,
    dataUrl: false,
    images: {
      group: '/js/vendor/SlickGrid/images/arrow_right_peppermint.png',
    },
    dataComparer: comparer,
    getData: getData,
    useDataFlatter: true,
    useDataSorting: true,
    useDataGrouping: true,
    dataIdField: 'id',
    gridOptions: {
      enableColumnReorder: false,
      enableCellNavigation: true,
    },
    gridId: '#myGrid',
    slickPlugins: {
      groupItemMetadataProvider: {
        obj:  newGroupItemMetadataProvider
      },
      distinctMenu: {
        obj: true,
        options: {
          getDistinct: getStaticDistinct,
          doFilter: doStaticFilter,
        }
      },
      headerMenu: {
        obj: true,
        options: {}
      },
      headerButtons: {
        obj: true,
        options: {}
      }
    }
  }

  function Init(){
    options = $.extend(true, {}, _defaults, options);

    if( options.dataView === true ){
        var dataViewArgs = {}
        generateDataGroupMenus();
        if( options.useDataGrouping ){
          var groupItemMetadataProvider = options.slickPlugins.groupItemMetadataProvider.obj();
          options.slickPlugins.groupItemMetadataProvider.obj = groupItemMetadataProvider
          dataViewArgs = {
            groupItemMetadataProvider: groupItemMetadataProvider,
            inlineFilters: true
          }
        }
        options.dataView = newDataView(dataViewArgs);

    }
    //set data to dataView
    options.dataView.setItems(options.data);

    //set column filter
    //options.dataView.setFilter(columnStaticFilter);

    //if grid is not yet created, create grid instance
    if(!options.grid)
      options.grid = new Slick.Grid(
        options.gridId,
        options.dataView,
        options.columns,
        options.gridOptions);
    // Make the grid respond to DataView change events.
    options.dataView.onRowCountChanged.subscribe(function (e, args) {
      options.grid.updateRowCount();
      options.grid.render();
    });
    options.dataView.onRowsChanged.subscribe(function (e, args) {
      options.grid.invalidateRows(args.rows);
      options.grid.render();
    });
    if( options.useDataGrouping){
      options.grid.registerPlugin(groupItemMetadataProvider);
    }
    if( options.useDataSorting ){
      options.grid.onSort.subscribe(function(e, args) {
        var comparer = function(a, b) {
          return a[args.sortCol.field] > b[args.sortCol.field];
        }
        options.dataView.sort(comparer, args.sortAsc);
      });
    }

    //add sort event handler
    options.grid.onSort.subscribe(function (e, args) {
      sortdir = args.sortAsc ? 1 : -1;
      sortcol = args.sortCol.field;
      options.dataView.sort(options.dataComparer, args.sortAsc);
    });

    //if headerMenu is purpose to use, create it
    if( options.slickPlugins.headerMenu.obj === true )
    {
      options.slickPlugins.headerMenu.obj = new Slick.Plugins.HeaderMenu(
        options.slickPlugins.headerMenu.options );
      options.grid.registerPlugin(options.slickPlugins.headerMenu.obj);
    }
    //if headerButtons is purpose to use, create it
    if( options.slickPlugins.headerButtons.obj === true )
    {
      options.slickPlugins.headerButtons.obj = new Slick.Plugins.HeaderButtons(
          options.slickPlugins.headerButtons.options);
      options.grid.registerPlugin(options.slickPlugins.headerButtons.obj);
      options.slickPlugins.headerButtons.obj.onCommand.subscribe(onCommand);
    }
    //if distinct menu is purpose to use create it
    if( options.slickPlugins.headerMenu.obj &&
        options.slickPlugins.distinctMenu.obj === true )
      // init distinctMenu
    {
      //Create distinctMenu instance
      options.slickPlugins.distinctMenu.obj = new Slick.Plugins.DistinctMenu(
       $.extend(true, {}, options.slickPlugins.distinctMenu.options, {
          headerMenu: options.slickPlugins.headerMenu.obj,
          columns: options.columns,
          }));
      //register distinctMenu
      options.grid.registerPlugin(options.slickPlugins.distinctMenu.obj);

      //and update menu items
      options.slickPlugins.distinctMenu.obj.update();

    }
    options.getData( options.dataUrl, function(error, list){
      //if data is fetched, update distinctMenu
      if( list ){
        if( list.length > 0 ){
          var i, len=list.length;
          for(i=0;i<len;i++){
            if( options.useDataFlatter)
              list[i] = flatten(list[i]);
            if(options.dataIdField!='id')
              list[i].id = list[i][options.dataIdField];
          }
        }
      }
      data = list;
      options.dataView.beginUpdate();
      options.dataView.setItems(data);
      options.dataView.endUpdate();
      options.slickPlugins.distinctMenu.obj.update();
    });
  }

  function onCommand(e, args)
  {
    if( args.command == 'group' ){
      onGroup(e, args);
      // Stop propagation so that it doesn't register as a header click event.
      e.preventDefault();
      e.stopPropagation();
    }
  }
  function onGroup(e, args){
    console.log('onGrouping..');
    var grouping = options.dataView.getGrouping();
    if( grouping.length == 0 || e.ctrlKey || e.altKey ){

      grouping.push({
        getter: args.column.id,
        formatter: function (g, a, b, c) {
          console.log(g);
          return args.column.name+":  " + g.value + "  (" + g.count + " items)";
        },
        collapsed: true,
        /*aggregators: [
          //new Slick.Data.Aggregators.Avg("percentComplete"),
          //new Slick.Data.Aggregators.Sum("cost")
        ],
        aggregateCollapsed: true
        */
      });
    } else {
      grouping = [];
    }
    options.dataView.setGrouping( grouping );
  }
  function generateDataGroupMenus(){
    for(var i in options.columns){
      var column = options.columns[i];
      $.extend(true, column, {header: {buttons: [
          {
            cssClass: 'slick-header-distinctbutton',
            image: options.images.group,
            command: 'group'}
          ]}});
    }
  }
  function columnStaticFilter(item) {
    for(var field in options.columnFilters)
    {
      if( item!==undefined && item[field]!== options.columnFilters[field] )
      {
        return false;
      }
    }
    return true;
  }
  function getData(dataUrl, callback){
    $.getJSON(dataUrl, null, function(data){
      callback(null, data);
    })
  }
  function newGroupItemMetadataProvider(){
    return new Slick.Data.GroupItemMetadataProvider()
  }
  function newDataView(args){return new Slick.Data.DataView(args);}
  function getStaticDistinct(field, url, urlParameters, callback){
    function getDist(field){
      var i=0,list = [];
      options.data.forEach( function(row){
        if( row[field] && list.indexOf( row[field] )== -1 ){
          list.push( row[field] );
        }
      });
      return list;
    }
    callback(null,  getDist(field));
  }
  function doStaticFilter(field, condition, callback){
    console.log('doStaticFilter');
    options.columnFilters = {};
    for(var i=0;condition['$and'] && i<condition['$and'].length;i++){
      for(var key in condition['$and'][i] ){
        options.columnFilters[key] = condition['$and'][i][key];
      };
    }
    options.dataView.refresh();
    callback();
  }
  function comparer(a, b) {
    var x = a[sortcol], y = b[sortcol];
    return (x == y ? 0 : (x > y ? 1 : -1));
  }

  this.updateDistinct = function(){
    options.slickPlugins.distinctMenu.obj.update();
  }
  Init();
  return this;
}
<|endoftext|>


<commit_before>
// limbus-buildgen - A "build anywhere" C/C++ makefile/project generator.
// Written in 2014-2016 by Jesper Oskarsson jesosk@gmail.com
//
// To the extent possible under law, the author(s) have dedicated all copyright
// and related and neighboring rights to this software to the public domain worldwide.
// This software is distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.

var should = require('should');
var util = require('./util.js');
var shell = require('./shell.js');
var minimal = require('../source/minimal-configuration');

describe('Architectures', function () {
    beforeEach(function () {
        return util.beforeEach();
    });

    afterEach(function () {
        return util.afterEach();
    });

    it('should compile for the correct architecture', function () {
        var builtExecutable = util.writeConfiguration(minimal.project())
        .then(util.generateWithParameters())
        .then(util.build());

        if (process.platform === 'win32') {
            return builtExecutable.then(function (executable) {
                return shell.exec('..\\utility-scripts\\setenv.bat && dumpbin /nologo /headers ' + executable, {cwd: 'temp'});
            }).then(function (output) {
                if (output.stdout.indexOf('PE32+') !== -1) {
                    util.hostArchitecture.should.equal('x64');

                } else if (output.stdout.indexOf('PE32') !== -1) {
                    util.hostArchitecture.should.equal('x86');

                } else {
                    return Promise.reject('Unknown platform:\n' + output.stdout);
                }
            });
        } else {
            return builtExecutable.then(function (executable) {
                return shell.exec('file ' + executable, {cwd: 'temp'});
            }).then(function (output) {
                if (output.stdout.indexOf('64-bit') !== -1) {
                    util.hostArchitecture.should.equal('x64');

                } else if (output.stdout.indexOf('86') !== -1) {
                    util.hostArchitecture.should.equal('x86');

                } else {
                    return Promise.reject('Unknown platform:\n' + output.stdout);
                }
            });
        }
    });
});
<commit_msg>Added .exe extension to dumpbin command as it seems to be needed<commit_after>
// limbus-buildgen - A "build anywhere" C/C++ makefile/project generator.
// Written in 2014-2016 by Jesper Oskarsson jesosk@gmail.com
//
// To the extent possible under law, the author(s) have dedicated all copyright
// and related and neighboring rights to this software to the public domain worldwide.
// This software is distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.

var should = require('should');
var util = require('./util.js');
var shell = require('./shell.js');
var minimal = require('../source/minimal-configuration');

describe('Architectures', function () {
    beforeEach(function () {
        return util.beforeEach();
    });

    afterEach(function () {
        return util.afterEach();
    });

    it('should compile for the correct architecture', function () {
        var builtExecutable = util.writeConfiguration(minimal.project())
        .then(util.generateWithParameters())
        .then(util.build());

        if (process.platform === 'win32') {
            return builtExecutable.then(function (executable) {
                return shell.exec('..\\utility-scripts\\setenv.bat && dumpbin /nologo /headers ' + executable + '.exe', {cwd: 'temp'});
            }).then(function (output) {
                if (output.stdout.indexOf('PE32+') !== -1) {
                    util.hostArchitecture.should.equal('x64');

                } else if (output.stdout.indexOf('PE32') !== -1) {
                    util.hostArchitecture.should.equal('x86');

                } else {
                    return Promise.reject('Unknown platform:\n' + output.stdout);
                }
            });
        } else {
            return builtExecutable.then(function (executable) {
                return shell.exec('file ' + executable, {cwd: 'temp'});
            }).then(function (output) {
                if (output.stdout.indexOf('64-bit') !== -1) {
                    util.hostArchitecture.should.equal('x64');

                } else if (output.stdout.indexOf('86') !== -1) {
                    util.hostArchitecture.should.equal('x86');

                } else {
                    return Promise.reject('Unknown platform:\n' + output.stdout);
                }
            });
        }
    });
});
<|endoftext|>


<commit_before>(function() {
'use strict';

/*
 * TODO: Add support for multiple fingers on the `pointer` object (enables pinch gesture)
 */

var START_EVENTS = 'mousedown touchstart pointerdown';
var MOVE_EVENTS = 'mousemove touchmove pointermove';
var END_EVENTS = 'mouseup mouseleave touchend touchcancel pointerup pointercancel';
var HANDLERS;

document.contains || (document.contains = function(node) {
  return document.body.contains(node);
});

document.addEventListener('click', function(ev) {
  // Space/enter on a button, and submit events, can send clicks
  var isKeyClick = ev.clientX === 0 && ev.clientY === 0 &&
    ev.x === 0 && ev.y === 0;
  if (isKeyClick || ev.$material) return;

  // Prevent clicks unless they're sent by material
  ev.preventDefault();
  ev.stopPropagation();
}, true);

angular.element(document)
  .on(START_EVENTS, gestureStart)
  .on(MOVE_EVENTS, gestureMove)
  .on(END_EVENTS, gestureEnd)
  // For testing
  .on('$$mdGestureReset', function() {
    lastPointer = pointer = null;
  });

// The state of the current and previous 'pointer' (user's hand)
var pointer, lastPointer;

function runHandlers(handlerEvent, event) {
  var handler;
  for (var handlerName in HANDLERS) {
    handler = HANDLERS[handlerName];
    if (handlerEvent === 'start') {
      // Run cancel to reset any handlers' state
      handler.cancel();
    }
    handler[handlerEvent](event, pointer);
  }
}

function gestureStart(ev) {
  // If we're already touched down, abort
  if (pointer) return;

  var now = +Date.now();

  // iOS & old android bug: after a touch event, a click event is sent 350 ms later.
  // If <400ms have passed, don't allow an event of a different type than the previous event
  if (lastPointer && !typesMatch(ev, lastPointer) && (now - lastPointer.endTime < 1500)) {
    return;
  }

  pointer = makeStartPointer(ev);

  runHandlers('start', ev);
}

function gestureMove(ev) {
  if (!pointer || !typesMatch(ev, pointer)) return;

  updatePointerState(ev, pointer);
  runHandlers('move', ev);
}

function gestureEnd(ev) {
  if (!pointer || !typesMatch(ev, pointer)) return;

  updatePointerState(ev, pointer);
  pointer.endTime = +Date.now();

  runHandlers('end', ev);

  lastPointer = pointer;
  pointer = null;
}

/******** Helpers *********/
function typesMatch(ev, pointer) {
  return ev && pointer && ev.type.charAt(0) === pointer.type;
}

function getEventPoint(ev) {
  ev = ev.originalEvent || ev; // support jQuery events
  return (ev.touches && ev.touches[0]) ||
    (ev.changedTouches && ev.changedTouches[0]) ||
    ev;
}

function updatePointerState(ev, pointer) {
  var point = getEventPoint(ev);
  var x = pointer.x = point.pageX;
  var y = pointer.y = point.pageY;

  pointer.distanceX = x - pointer.startX;
  pointer.distanceY = y - pointer.startY;
  pointer.distance = Math.sqrt(
    pointer.distanceX * pointer.distanceX + pointer.distanceY * pointer.distanceY
  );

  pointer.directionX = pointer.distanceX > 0 ? 'right' : pointer.distanceX < 0 ? 'left' : '';
  pointer.directionY = pointer.distanceY > 0 ? 'up' : pointer.distanceY < 0 ? 'down' : '';

  pointer.duration = +Date.now() - pointer.startTime;
  pointer.velocityX = pointer.distanceX / pointer.duration;
  pointer.velocityY = pointer.distanceY / pointer.duration;
}

function makeStartPointer(ev) {
  var point = getEventPoint(ev);
  var startPointer = {
    startTime: +Date.now(),
    target: ev.target,
    // 'p' for pointer, 'm' for mouse, 't' for touch
    type: ev.type.charAt(0)
  };
  startPointer.startX = startPointer.x = point.pageX;
  startPointer.startY = startPointer.y = point.pageY;
  return startPointer;
}

angular.module('material.core')
.run(function($mdGesture) {}) // make sure $mdGesture is always instantiated
.factory('$mdGesture', function($$MdGestureHandler, $$rAF, $timeout) {
  HANDLERS = {};

  addHandler('click', {
    options: {
      maxDistance: 6
    },
    onEnd: function(ev, pointer) {
      if (pointer.distance < this.state.options.maxDistance) {
        this.dispatchEvent(ev, 'click');
      }
    }
  });

  addHandler('press', {
    onStart: function(ev, pointer) {
      this.dispatchEvent(ev, '$md.pressdown');
    },
    onEnd: function(ev, pointer) {
      this.dispatchEvent(ev, '$md.pressup');
    }
  });

  addHandler('hold', {
    options: {
      // If the user keeps his finger within the same <maxDistance> area for
      // <delay> ms, dispatch a hold event.
      maxDistance: 6,
      delay: 500,
    },
    onCancel: function() {
      $timeout.cancel(this.state.timeout);
    },
    onStart: function(ev, pointer) {
      // For hold, require a parent to be registered with $mdGesture.register()
      // Because we prevent scroll events, this is necessary.
      if (!this.state.registeredParent) return this.cancel();

      this.state.pos = {x: pointer.x, y: pointer.y};
      this.state.timeout = $timeout(angular.bind(this, function holdDelayFn() {
        this.dispatchEvent(ev, '$md.hold');
        this.cancel(); //we're done!
      }), this.state.options.delay, false);
    },
    onMove: function(ev, pointer) {
      // Don't scroll while waiting for hold
      ev.preventDefault();
      var dx = this.state.pos.x - pointer.x;
      var dy = this.state.pos.y - pointer.y;
      if (Math.sqrt(dx*dx + dy*dy) > this.options.maxDistance) {
        this.cancel();
      }
    },
    onEnd: function(ev, pointer) {
      this.onCancel();
    },
  });

  addHandler('drag', {
    options: {
      minDistance: 6,
      horizontal: true,
    },
    onStart: function(ev) {
      // For drag, require a parent to be registered with $mdGesture.register()
      if (!this.state.registeredParent) this.cancel();
    },
    onMove: function(ev, pointer) {
      var shouldStartDrag, shouldCancel;
      // Don't allow touch events to scroll while we're dragging or
      // deciding if this touchmove is a proper drag
      ev.preventDefault();

      if (!this.state.dragPointer) {
        if (this.state.options.horizontal) {
          shouldStartDrag = Math.abs(pointer.distanceX) > this.state.options.minDistance;
          shouldCancel = Math.abs(pointer.distanceY) > this.state.options.minDistance * 1.5;
        } else {
          shouldStartDrag = Math.abs(pointer.distanceY) > this.state.options.minDistance;
          shouldCancel = Math.abs(pointer.distanceX) > this.state.options.minDistance * 1.5;
        }

        if (shouldStartDrag) {
          // Create a new pointer, starting at this point where the drag started.
          this.state.dragPointer = makeStartPointer(ev);
          updatePointerState(ev, this.state.dragPointer);
          this.dispatchEvent(ev, '$md.dragstart', this.state.dragPointer);

        } else if (shouldCancel) {
          this.cancel();
        }
      } else {
        this.dispatchDragMove(ev);
      }
    },
    // Only dispatch these every frame; any more is unnecessray
    dispatchDragMove: $$rAF.throttle(function(ev) {
      // Make sure the drag didn't stop while waiting for the next frame
      if (this.state.isRunning) {
        updatePointerState(ev, this.state.dragPointer);
        this.dispatchEvent(ev, '$md.drag', this.state.dragPointer);
      }
    }),
    onEnd: function(ev, pointer) {
      if (this.state.dragPointer) {
        updatePointerState(ev, this.state.dragPointer);
        this.dispatchEvent(ev, '$md.dragend', this.state.dragPointer);
      }
    }
  });

  addHandler('swipe', {
    options: {
      minVelocity: 0.65,
      minDistance: 10,
    },
    onEnd: function(ev, pointer) {
      if (Math.abs(pointer.velocityX) > this.state.options.minVelocity &&
          Math.abs(pointer.distanceX) > this.state.options.minDistance) {
        var eventType = pointer.directionX == 'left' ? '$md.swipeleft' : '$md.swiperight';
        this.dispatchEvent(ev, eventType);
      }
    }
  });

  var self;
  return self = {
    handler: addHandler,
    register: register
  };

  function addHandler(name, definition) {
    var handler = new $$MdGestureHandler(name);
    angular.extend(handler, definition);
    HANDLERS[name] = handler;
    return self;
  }

  function register(element, handlerName, options) {
    var handler = HANDLERS[ handlerName.replace(/^\$md./, '') ];
    if (!handler) {
      throw new Error('Failed to register element with handler ' + handlerName + '. ' +
                      'Available handlers: ' + Object.keys(HANDLERS).join(', '));
    }
    return handler.registerElement(element, options);
  }
})
.factory('$$MdGestureHandler', function($$rAF) {

  function GestureHandler(name) {
    this.name = name;
    this.state = {};
  }
  GestureHandler.prototype = {
    onStart: angular.noop,
    onMove: angular.noop,
    onEnd: angular.noop,
    onCancel: angular.noop,
    options: {},

    dispatchEvent: dispatchEvent,

    start: function(ev, pointer) {
      if (this.state.isRunning) return;
      var parentTarget = this.getNearestParent(ev.target);
      var parentTargetOptions = parentTarget && parentTarget.$mdGesture[this.name] || {};

      this.state = {
        isRunning: true,
        options: angular.extend({}, this.options, parentTargetOptions),
        registeredParent: parentTarget
      };
      this.onStart(ev, pointer);
    },
    move: function(ev, pointer) {
      if (!this.state.isRunning) return;
      this.onMove(ev, pointer);
    },
    end: function(ev, pointer) {
      if (!this.state.isRunning) return;
      this.onEnd(ev, pointer);
      this.state.isRunning = false;
    },
    cancel: function(ev, pointer) {
      this.onCancel(ev, pointer);
      this.state = {};
    },

    // Find and return the nearest parent element that has been registered via
    // $mdGesture.register(element, 'handlerName').
    getNearestParent: function(node) {
      var current = node;
      while (current) {
        if ( (current.$mdGesture || {})[this.name] ) {
          return current;
        }
        current = current.parentNode;
      }
    },

    registerElement: function(element, options) {
      var self = this;
      element[0].$mdGesture = element[0].$mdGesture || {};
      element[0].$mdGesture[this.name] = options || {};
      element.on('$destroy', onDestroy);

      return onDestroy;

      function onDestroy() {
        delete element[0].$mdGesture[self.name];
        element.off('$destroy', onDestroy);
      }
    },
  };

  var customEventOptions = {
    bubbles: true,
    cancelable: true
  };
  /*
   * NOTE: dispatchEvent is very performance sensitive.
   */
  function dispatchEvent(srcEvent, eventType, eventPointer) {
    eventPointer = eventPointer || pointer;
    var eventObj;

    if (eventType === 'click') {
      eventObj = document.createEvent('MouseEvents');
      eventObj.initMouseEvent('click', true, true, window, {},
                              eventPointer.x, eventPointer.y,
                              eventPointer.x, eventPointer.y,
                              false, false, false, false, 0, null);
    } else {
      eventObj = document.createEvent('CustomEvent');
      eventObj.initCustomEvent(eventType, true, true, {});
    }
    eventObj.$material = true;
    eventObj.pointer = eventPointer;
    eventObj.srcEvent = srcEvent;
    eventPointer.target.dispatchEvent(eventObj);
  }

  return GestureHandler;
});

})();
<commit_msg>fix(gesture): make sure clicks properly support keys<commit_after>(function() {
'use strict';

/*
 * TODO: Add support for multiple fingers on the `pointer` object (enables pinch gesture)
 */

var START_EVENTS = 'mousedown touchstart pointerdown';
var MOVE_EVENTS = 'mousemove touchmove pointermove';
var END_EVENTS = 'mouseup mouseleave touchend touchcancel pointerup pointercancel';
var HANDLERS;

document.contains || (document.contains = function(node) {
  return document.body.contains(node);
});

document.addEventListener('click', function(ev) {
  // Space/enter on a button, and submit events, can send clicks
  var isKeyClick = ev.clientX === 0 && ev.clientY === 0 &&
    ev.x === 0 && ev.y === 0;
  if (isKeyClick || ev.$material) return;

  // Prevent clicks unless they're sent by material
  ev.preventDefault();
  ev.stopPropagation();
}, true);

angular.element(document)
  .on(START_EVENTS, gestureStart)
  .on(MOVE_EVENTS, gestureMove)
  .on(END_EVENTS, gestureEnd)
  // For testing
  .on('$$mdGestureReset', function() {
    lastPointer = pointer = null;
  });

// The state of the current and previous 'pointer' (user's hand)
var pointer, lastPointer;

function runHandlers(handlerEvent, event) {
  var handler;
  for (var handlerName in HANDLERS) {
    handler = HANDLERS[handlerName];
    if (handlerEvent === 'start') {
      // Run cancel to reset any handlers' state
      handler.cancel();
    }
    handler[handlerEvent](event, pointer);
  }
}

function gestureStart(ev) {
  // If we're already touched down, abort
  if (pointer) return;

  var now = +Date.now();

  // iOS & old android bug: after a touch event, a click event is sent 350 ms later.
  // If <400ms have passed, don't allow an event of a different type than the previous event
  if (lastPointer && !typesMatch(ev, lastPointer) && (now - lastPointer.endTime < 1500)) {
    return;
  }

  pointer = makeStartPointer(ev);

  runHandlers('start', ev);
}

function gestureMove(ev) {
  if (!pointer || !typesMatch(ev, pointer)) return;

  updatePointerState(ev, pointer);
  runHandlers('move', ev);
}

function gestureEnd(ev) {
  if (!pointer || !typesMatch(ev, pointer)) return;

  updatePointerState(ev, pointer);
  pointer.endTime = +Date.now();

  runHandlers('end', ev);

  lastPointer = pointer;
  pointer = null;
}

/******** Helpers *********/
function typesMatch(ev, pointer) {
  return ev && pointer && ev.type.charAt(0) === pointer.type;
}

function getEventPoint(ev) {
  ev = ev.originalEvent || ev; // support jQuery events
  return (ev.touches && ev.touches[0]) ||
    (ev.changedTouches && ev.changedTouches[0]) ||
    ev;
}

function updatePointerState(ev, pointer) {
  var point = getEventPoint(ev);
  var x = pointer.x = point.pageX;
  var y = pointer.y = point.pageY;

  pointer.distanceX = x - pointer.startX;
  pointer.distanceY = y - pointer.startY;
  pointer.distance = Math.sqrt(
    pointer.distanceX * pointer.distanceX + pointer.distanceY * pointer.distanceY
  );

  pointer.directionX = pointer.distanceX > 0 ? 'right' : pointer.distanceX < 0 ? 'left' : '';
  pointer.directionY = pointer.distanceY > 0 ? 'up' : pointer.distanceY < 0 ? 'down' : '';

  pointer.duration = +Date.now() - pointer.startTime;
  pointer.velocityX = pointer.distanceX / pointer.duration;
  pointer.velocityY = pointer.distanceY / pointer.duration;
}

function makeStartPointer(ev) {
  var point = getEventPoint(ev);
  var startPointer = {
    startTime: +Date.now(),
    target: ev.target,
    // 'p' for pointer, 'm' for mouse, 't' for touch
    type: ev.type.charAt(0)
  };
  startPointer.startX = startPointer.x = point.pageX;
  startPointer.startY = startPointer.y = point.pageY;
  return startPointer;
}

angular.module('material.core')
.run(function($mdGesture) {}) // make sure $mdGesture is always instantiated
.factory('$mdGesture', function($$MdGestureHandler, $$rAF, $timeout) {
  HANDLERS = {};

  addHandler('click', {
    options: {
      maxDistance: 6
    },
    onEnd: function(ev, pointer) {
      if (pointer.distance < this.state.options.maxDistance) {
        this.dispatchEvent(ev, 'click', null, ev);
      }
    }
  });

  addHandler('press', {
    onStart: function(ev, pointer) {
      this.dispatchEvent(ev, '$md.pressdown');
    },
    onEnd: function(ev, pointer) {
      this.dispatchEvent(ev, '$md.pressup');
    }
  });

  addHandler('hold', {
    options: {
      // If the user keeps his finger within the same <maxDistance> area for
      // <delay> ms, dispatch a hold event.
      maxDistance: 6,
      delay: 500,
    },
    onCancel: function() {
      $timeout.cancel(this.state.timeout);
    },
    onStart: function(ev, pointer) {
      // For hold, require a parent to be registered with $mdGesture.register()
      // Because we prevent scroll events, this is necessary.
      if (!this.state.registeredParent) return this.cancel();

      this.state.pos = {x: pointer.x, y: pointer.y};
      this.state.timeout = $timeout(angular.bind(this, function holdDelayFn() {
        this.dispatchEvent(ev, '$md.hold');
        this.cancel(); //we're done!
      }), this.state.options.delay, false);
    },
    onMove: function(ev, pointer) {
      // Don't scroll while waiting for hold
      ev.preventDefault();
      var dx = this.state.pos.x - pointer.x;
      var dy = this.state.pos.y - pointer.y;
      if (Math.sqrt(dx*dx + dy*dy) > this.options.maxDistance) {
        this.cancel();
      }
    },
    onEnd: function(ev, pointer) {
      this.onCancel();
    },
  });

  addHandler('drag', {
    options: {
      minDistance: 6,
      horizontal: true,
    },
    onStart: function(ev) {
      // For drag, require a parent to be registered with $mdGesture.register()
      if (!this.state.registeredParent) this.cancel();
    },
    onMove: function(ev, pointer) {
      var shouldStartDrag, shouldCancel;
      // Don't allow touch events to scroll while we're dragging or
      // deciding if this touchmove is a proper drag
      ev.preventDefault();

      if (!this.state.dragPointer) {
        if (this.state.options.horizontal) {
          shouldStartDrag = Math.abs(pointer.distanceX) > this.state.options.minDistance;
          shouldCancel = Math.abs(pointer.distanceY) > this.state.options.minDistance * 1.5;
        } else {
          shouldStartDrag = Math.abs(pointer.distanceY) > this.state.options.minDistance;
          shouldCancel = Math.abs(pointer.distanceX) > this.state.options.minDistance * 1.5;
        }

        if (shouldStartDrag) {
          // Create a new pointer, starting at this point where the drag started.
          this.state.dragPointer = makeStartPointer(ev);
          updatePointerState(ev, this.state.dragPointer);
          this.dispatchEvent(ev, '$md.dragstart', this.state.dragPointer);

        } else if (shouldCancel) {
          this.cancel();
        }
      } else {
        this.dispatchDragMove(ev);
      }
    },
    // Only dispatch these every frame; any more is unnecessray
    dispatchDragMove: $$rAF.throttle(function(ev) {
      // Make sure the drag didn't stop while waiting for the next frame
      if (this.state.isRunning) {
        updatePointerState(ev, this.state.dragPointer);
        this.dispatchEvent(ev, '$md.drag', this.state.dragPointer);
      }
    }),
    onEnd: function(ev, pointer) {
      if (this.state.dragPointer) {
        updatePointerState(ev, this.state.dragPointer);
        this.dispatchEvent(ev, '$md.dragend', this.state.dragPointer);
      }
    }
  });

  addHandler('swipe', {
    options: {
      minVelocity: 0.65,
      minDistance: 10,
    },
    onEnd: function(ev, pointer) {
      if (Math.abs(pointer.velocityX) > this.state.options.minVelocity &&
          Math.abs(pointer.distanceX) > this.state.options.minDistance) {
        var eventType = pointer.directionX == 'left' ? '$md.swipeleft' : '$md.swiperight';
        this.dispatchEvent(ev, eventType);
      }
    }
  });

  var self;
  return self = {
    handler: addHandler,
    register: register
  };

  function addHandler(name, definition) {
    var handler = new $$MdGestureHandler(name);
    angular.extend(handler, definition);
    HANDLERS[name] = handler;
    return self;
  }

  function register(element, handlerName, options) {
    var handler = HANDLERS[ handlerName.replace(/^\$md./, '') ];
    if (!handler) {
      throw new Error('Failed to register element with handler ' + handlerName + '. ' +
                      'Available handlers: ' + Object.keys(HANDLERS).join(', '));
    }
    return handler.registerElement(element, options);
  }
})
.factory('$$MdGestureHandler', function($$rAF) {

  function GestureHandler(name) {
    this.name = name;
    this.state = {};
  }
  GestureHandler.prototype = {
    onStart: angular.noop,
    onMove: angular.noop,
    onEnd: angular.noop,
    onCancel: angular.noop,
    options: {},

    dispatchEvent: dispatchEvent,

    start: function(ev, pointer) {
      if (this.state.isRunning) return;
      var parentTarget = this.getNearestParent(ev.target);
      var parentTargetOptions = parentTarget && parentTarget.$mdGesture[this.name] || {};

      this.state = {
        isRunning: true,
        options: angular.extend({}, this.options, parentTargetOptions),
        registeredParent: parentTarget
      };
      this.onStart(ev, pointer);
    },
    move: function(ev, pointer) {
      if (!this.state.isRunning) return;
      this.onMove(ev, pointer);
    },
    end: function(ev, pointer) {
      if (!this.state.isRunning) return;
      this.onEnd(ev, pointer);
      this.state.isRunning = false;
    },
    cancel: function(ev, pointer) {
      this.onCancel(ev, pointer);
      this.state = {};
    },

    // Find and return the nearest parent element that has been registered via
    // $mdGesture.register(element, 'handlerName').
    getNearestParent: function(node) {
      var current = node;
      while (current) {
        if ( (current.$mdGesture || {})[this.name] ) {
          return current;
        }
        current = current.parentNode;
      }
    },

    registerElement: function(element, options) {
      var self = this;
      element[0].$mdGesture = element[0].$mdGesture || {};
      element[0].$mdGesture[this.name] = options || {};
      element.on('$destroy', onDestroy);

      return onDestroy;

      function onDestroy() {
        delete element[0].$mdGesture[self.name];
        element.off('$destroy', onDestroy);
      }
    },
  };

  var customEventOptions = {
    bubbles: true,
    cancelable: true
  };
  /*
   * NOTE: dispatchEvent is very performance sensitive.
   */
  function dispatchEvent(srcEvent, eventType, eventPointer, /*original DOMEvent */ev) {
    eventPointer = eventPointer || pointer;
    var eventObj;

    if (eventType === 'click') {
      eventObj = document.createEvent('MouseEvents');
      eventObj.initMouseEvent(
        'click', true, true, window, ev.detail,
        ev.screenX, ev.screenY, ev.clientX, ev.clientY,
        ev.ctrlKey, ev.altKey, ev.shiftKey, ev.metaKey,
        ev.button, ev.relatedTarget || null
      );
      angular.extend(eventObj, {
        which: ev.which,
        x: ev.x, y: ev.y,
        offsetX: ev.offsetX, offsetY: ev.offsetY,
        layerX: ev.layerX, layerY: ev.layerY
      });

    } else {
      eventObj = document.createEvent('CustomEvent');
      eventObj.initCustomEvent(eventType, true, true, {});
    }
    eventObj.$material = true;
    eventObj.pointer = eventPointer;
    eventObj.srcEvent = srcEvent;
    eventPointer.target.dispatchEvent(eventObj);
  }

  return GestureHandler;
});

})();
<|endoftext|>


<commit_before>/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';

import AlbumList from './album-list';
import RNPhotosFramework from 'react-native-photos-framework';
const TEST_ALBUM_ONE = 'RNPF-test-1';
const TEST_ALBUM_TWO = 'RNPF-test-2';
export default class Example extends Component {
  constructor(props) {
    super(props);
    this.state = {
      num: 0
    };
  }

  componentWillMount() {
    //Start with creating 2 test-albums that we can work with:
    //First Check if they already exist, if they do. clean up:
  //  RNPhotosFramework.createAlbum(TEST_ALBUM_ONE);
  //  RNPhotosFramework.createAlbum(TEST_ALBUM_TWO);

    this.testAlbumsExist().then((albums) => {
      this.removeAlbums(albums);
    });
  }

  removeAlbums(albums) {
    return RNPhotosFramework.deleteAlbums(albums);
  }

  testAlbumsExist() {
    return RNPhotosFramework.getAlbumsByTitles([TEST_ALBUM_ONE, TEST_ALBUM_TWO]).then((fetchResult) => {
      const albumsThatDoExit = [TEST_ALBUM_ONE, TEST_ALBUM_TWO].filter(testAlbumTitle => fetchResult.albums.some(album => album.title === testAlbumTitle));
      const albumsThatDontExit = [TEST_ALBUM_ONE, TEST_ALBUM_TWO].filter(testAlbumTitle => !fetchResult.albums.some(album => album.title === testAlbumTitle));
      if(albumsThatDontExit.length) {
        return RNPhotosFramework.createAlbums(albumsThatDontExit).then((newAlbums) => {
          return albumsThatDoExit.concat(newAlbums);
        });
      }
      return fetchResult.albums;
    });
  }

  render() {
    return (
      <View style={styles.container}>
        <AlbumList></AlbumList>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1
  }
});

AppRegistry.registerComponent('Example', () => Example);
<commit_msg>Updated<commit_after>/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';

import AlbumList from './album-list';
import RNPhotosFramework from 'react-native-photos-framework';
const TEST_ALBUM_ONE = 'RNPF-test-1';
const TEST_ALBUM_TWO = 'RNPF-test-2';
export default class Example extends Component {
  constructor(props) {
    super(props);
    this.state = {
      num: 0
    };
  }

  componentWillMount() {
    //Start with creating 2 test-albums that we can work with:
    //First Check if they already exist, if they do. clean up:
    //RNPhotosFramework.createAlbum(TEST_ALBUM_ONE);
    //RNPhotosFramework.createAlbum(TEST_ALBUM_TWO);

    this.testAlbumsExist().then((albums) => {
      this.removeAlbums(albums);
    });
  }

  removeAlbums(albums) {
    return RNPhotosFramework.deleteAlbums(albums);
  }

  testAlbumsExist() {
    return RNPhotosFramework.getAlbumsByTitles([TEST_ALBUM_ONE, TEST_ALBUM_TWO]).then((fetchResult) => {
      const albumsThatDoExit = [TEST_ALBUM_ONE, TEST_ALBUM_TWO].filter(testAlbumTitle => fetchResult.albums.some(album => album.title === testAlbumTitle));
      const albumsThatDontExit = [TEST_ALBUM_ONE, TEST_ALBUM_TWO].filter(testAlbumTitle => !fetchResult.albums.some(album => album.title === testAlbumTitle));
      if(albumsThatDontExit.length) {
        return RNPhotosFramework.createAlbums(albumsThatDontExit).then((newAlbums) => {
          return albumsThatDoExit.concat(newAlbums);
        });
      }
      return fetchResult.albums;
    });
  }

  render() {
    return (
      <View style={styles.container}>
        <AlbumList></AlbumList>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1
  }
});

AppRegistry.registerComponent('Example', () => Example);
<|endoftext|>


<commit_before>var timer;
var chatfiltered = false;
var vidobserver;
var obsconfig = { attributes: true, attributeOldValue: true, childList: true, characterData: true };
var waitlisttimer;
var chatobserver;

$(function(){
   timer = setTimeout(initializeInterface, 9000);

});

function initializeInterface () {
    var button = $('#pagemods');

    if ( !button.text() ) {
        clearTimeout(timer);
        // Check to see if the person really is in the waitlist.

        checkWaitListStatus();
        waitlisttimer = setTimeout(checkWaitListStatus(), 60000);

        // This doesn't work because I cannot detect the iframe change.
        // Need to talk to Gryph
        var iframe = $('div.reactplayer')[0];

        vidobserver = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation){
                console.log(mutation);
            });
        });

        vidobserver.observe(iframe, obsconfig);

        // Try to track changes in the chat box.

        chatobserver = setTimeout(convertImageLink, 1000);

        // Make the changes to the UI.

        $('span[class="beta-tag"]').text("βeta+secret cannapowers");

        $('

@

Page Mods
').insertAfter('div.nav.navbar-nav.navbar-right');

        // Set up events.

        // Region Check Click Event
        $('#regioncheck').click(
            function () {
                var vidurl = $('iframe#youtube-player-0').attr("src").match(/\/embed\/(.*?)\?/);
                window.open("https://polsy.org.uk/stuff/ytrestrict.cgi?ytid=" + vidurl[1]);
            }
        );

        // Filter Chat Click Event
        $('#filterchat').click(
            function() {
                var $username = "@" + $('#username').text();
                var regex = new RegExp( $username, 'i' );
                $('ul#chatbox li').each(
                    function (c, e) {
                        if ( chatfiltered ) {
                            $(e).show('fast');
                            $('div#chatscroll').scrollTop($('div#chatscroll')[0].scrollHeight);
                        } else {
                            $(e).hide('fast');
                            $(e).find('span').each(
                                function () {
                                    var thistext = $(this).text();

                                    if ( thistext.match(regex) ) {
                                        $(e).show('fast');
                                    }
                                }
                            );
                        }
                    }
                );
                $('div#chatscroll').scrollTop($('div#chatscroll')[0].scrollHeight);

                if ( chatfiltered ) {
                    chatfiltered = false;
                } else {
                    chatfiltered = true;
                }
            }
        );

        // Page Mods Click Event.

        $('#pagemods').click(
            function () {

                var chat = $('#chatinput').val();

                $('div.show-ousers-btn.col-lg-3').click();

                $('ul[class="users-list"] li span').each(
                    function(c, e) {
                        var thisclass = $(e).attr("class");
                        if ( thisclass.match(/mod|owner|admin/i) ) {
                            chat = chat + "@" + e.innerText + " ";
                        }
                    }
                );

                $('div.show-chat-btn.col-lg-3').click();
                $('#chatinput').val(chat);
                $('#chatinput').focus();
            }
        )
     } else {
        clearTimeout(timer);
        timer = setTimeout(initializeInterface, 5000);
    }
}

// When initializing, check to see if we're falsely in the waitlist.
// If we fall off the waitlist, make sure that we rejoin the waitlist.
var clickwait;

function checkWaitListStatus() {
    var waitliststatus = $('div.join-waitlist div.join-waitlist-pressed').text();

    if ( waitliststatus && waitliststatus != "Leave Waitlist" )
        return;

    $('div.show-waitlist-btn.col.lg-3').click();
    var inwaitlist = false;
    $('ul.waitlist-list li').each(
        function (c, e) {
            var name = $(e).find('span.waitlist-name')[0].text();
            if ( name == $('span#username').text() ) {
                inwaitlist = true;
            }
        }
    );
    if ( !inwaitlist ) {
        $('div.join-waitlist.join-waitlist-pressed').click();

        clickwait = setTimeout(letsJoinWaitlist, 2000);
    }
}

function letsJoinWaitlist() {
    clearTimeout(clickwait);
    $('div.join-waitlist').click();
}
var seenurl;

function convertImageLink() {
    chatobserver = setTimeout(convertImageLink, 2000);
    $($('ul#chatbox li').get().reverse()).each(function(c,e){
        $(e).find('span.Linkify a').each(
            function(co,el){
                if ( co > 5 ) return; // Limit to 10 for performance. And likely page bleed.
                var href = $(el).attr('href');

                if ( $(el).children().count > 0 && $(el).children().get(0).nodeName == 'img' )
                    return;

                elepos = $(e).position();
                scrolltobottom = false;
                if ( elepos.top > 0 && href.match(/^http(s|):\/\/i\.imgur|jpg$|gif$|png$|jpeg$|/i) ) {
                    scrolltobottom=true;
                    if ( href.match(/gifv|mp4|webm/i) ) {
                        newhref = href.replace(/(gifv|mp4)/i, "webm");
                        newhref = newhref.replace(/http(s|):/i,"");
                        mp4href = href.replace(/(gifv|webm)/i, "mp4");
                        mp4href = mp4href.replace(/http(s|):/i, "");

                        $(el).html('<video autoplay loop muted><source src="' + newhref + '" type="video/webm"></source><source src="'+mp4href+'" type="video/mp4"></source></video>')
                    } else {
                        $(el).html('');
                    }
                }
                if ( scrolltobottom )
                    $('div#chatscroll').scrollTop($('div#chatscroll')[0].scrollHeight);
            }
        )
    });
}<commit_msg>Fix bug where non img links were overwritten.<commit_after>var timer;
var chatfiltered = false;
var vidobserver;
var obsconfig = { attributes: true, attributeOldValue: true, childList: true, characterData: true };
var waitlisttimer;
var chatobserver;

$(function(){
   timer = setTimeout(initializeInterface, 9000);

});

function initializeInterface () {
    var button = $('#pagemods');

    if ( !button.text() ) {
        clearTimeout(timer);
        // Check to see if the person really is in the waitlist.

        checkWaitListStatus();
        waitlisttimer = setTimeout(checkWaitListStatus(), 60000);

        // This doesn't work because I cannot detect the iframe change.
        // Need to talk to Gryph
        var iframe = $('div.reactplayer')[0];

        vidobserver = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation){
                console.log(mutation);
            });
        });

        vidobserver.observe(iframe, obsconfig);

        // Try to track changes in the chat box.

        chatobserver = setTimeout(convertImageLink, 1000);

        // Make the changes to the UI.

        $('span[class="beta-tag"]').text("βeta+secret cannapowers");

        $('

@

Page Mods
').insertAfter('div.nav.navbar-nav.navbar-right');

        // Set up events.

        // Region Check Click Event
        $('#regioncheck').click(
            function () {
                var vidurl = $('iframe#youtube-player-0').attr("src").match(/\/embed\/(.*?)\?/);
                window.open("https://polsy.org.uk/stuff/ytrestrict.cgi?ytid=" + vidurl[1]);
            }
        );

        // Filter Chat Click Event
        $('#filterchat').click(
            function() {
                var $username = "@" + $('#username').text();
                var regex = new RegExp( $username, 'i' );
                $('ul#chatbox li').each(
                    function (c, e) {
                        if ( chatfiltered ) {
                            $(e).show('fast');
                            $('div#chatscroll').scrollTop($('div#chatscroll')[0].scrollHeight);
                        } else {
                            $(e).hide('fast');
                            $(e).find('span').each(
                                function () {
                                    var thistext = $(this).text();

                                    if ( thistext.match(regex) ) {
                                        $(e).show('fast');
                                    }
                                }
                            );
                        }
                    }
                );
                $('div#chatscroll').scrollTop($('div#chatscroll')[0].scrollHeight);

                if ( chatfiltered ) {
                    chatfiltered = false;
                } else {
                    chatfiltered = true;
                }
            }
        );

        // Page Mods Click Event.

        $('#pagemods').click(
            function () {

                var chat = $('#chatinput').val();

                $('div.show-ousers-btn.col-lg-3').click();

                $('ul[class="users-list"] li span').each(
                    function(c, e) {
                        var thisclass = $(e).attr("class");
                        if ( thisclass.match(/mod|owner|admin/i) ) {
                            chat = chat + "@" + e.innerText + " ";
                        }
                    }
                );

                $('div.show-chat-btn.col-lg-3').click();
                $('#chatinput').val(chat);
                $('#chatinput').focus();
            }
        )
     } else {
        clearTimeout(timer);
        timer = setTimeout(initializeInterface, 5000);
    }
}

// When initializing, check to see if we're falsely in the waitlist.
// If we fall off the waitlist, make sure that we rejoin the waitlist.
var clickwait;

function checkWaitListStatus() {
    var waitliststatus = $('div.join-waitlist div.join-waitlist-pressed').text();

    if ( waitliststatus && waitliststatus != "Leave Waitlist" )
        return;

    $('div.show-waitlist-btn.col.lg-3').click();
    var inwaitlist = false;
    $('ul.waitlist-list li').each(
        function (c, e) {
            var name = $(e).find('span.waitlist-name')[0].text();
            if ( name == $('span#username').text() ) {
                inwaitlist = true;
            }
        }
    );
    if ( !inwaitlist ) {
        $('div.join-waitlist.join-waitlist-pressed').click();

        clickwait = setTimeout(letsJoinWaitlist, 2000);
    }
}

function letsJoinWaitlist() {
    clearTimeout(clickwait);
    $('div.join-waitlist').click();
}
var seenurl;

function convertImageLink() {
    chatobserver = setTimeout(convertImageLink, 2000);
    $($('ul#chatbox li').get().reverse()).each(function(c,e){
        $(e).find('span.Linkify a').each(
            function(co,el){
                if ( co > 5 ) return; // Limit to 10 for performance. And likely page bleed.
                var href = $(el).attr('href');

                if ( $(el).children().count > 0 && $(el).children().get(0).nodeName == 'img' )
                    return;

                elepos = $(e).position();
                scrolltobottom = false;
                if ( elepos.top > 0 && href.match(/^http(s|):\/\/i\.imgur|jpg$|gif$|png$|jpeg$/i) ) {
                    scrolltobottom=true;
                    if ( href.match(/gifv|mp4|webm/i) ) {
                        newhref = href.replace(/(gifv|mp4)/i, "webm");
                        newhref = newhref.replace(/http(s|):/i,"");
                        mp4href = href.replace(/(gifv|webm)/i, "mp4");
                        mp4href = mp4href.replace(/http(s|):/i, "");

                        $(el).html('<video autoplay loop muted><source src="' + newhref + '" type="video/webm"></source><source src="'+mp4href+'" type="video/mp4"></source></video>')
                    } else {
                        $(el).html('');
                    }
                }
                if ( scrolltobottom )
                    $('div#chatscroll').scrollTop($('div#chatscroll')[0].scrollHeight);
            }
        )
    });
}<|endoftext|>


<commit_before>/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

(function() {
    // special patch to correctly work on Ripple emulator (CB-9760)
    if (window.parent && !!window.parent.ripple) { // https://gist.github.com/triceam/4658021
        module.exports = window.open.bind(window); // fallback to default window.open behaviour
        return;
    }

    var exec = require('cordova/exec');
    var channel = require('cordova/channel');
    var modulemapper = require('cordova/modulemapper');
    var urlutil = require('cordova/urlutil');

    var inAppBrowserInstance = null;
    var lastUrl = '';
    var lastWindowName = '';
    var lasrWindowFeatures = '';

    var InAppBrowser = function() {

        var me = this,
            lastPollIntervalToRestore = null,
            lastPollFunctionToRestore = null;

        function clearPolling () {
            lastPollIntervalToRestore = null;
            lastPollFunctionToRestore = null;
        }

        function clearRestoring(){
            clearPolling();
        }

        this.channels = {
            'loadstart': channel.create('loadstart'),
            'loadstop' : channel.create('loadstop'),
            'loaderror' : channel.create('loaderror'),
            'hidden' : channel.create('hidden'),
            'unhidden' : channel.create('unhidden'),
            'pollresult' : channel.create('pollresult'),
            'exit' : channel.create('exit')
        }

        this._eventHandler = function(event) {
            if (event && (event.type in this.channels)) {
                console.log(this.channels);
                this.channels[event.type].fire(event);
            }
        }

        this.close = function(eventname) {
           exec(null, null, "InAppBrowser", "close", []);
           this.stopPoll();
        }

        this.show = function(eventname) {
            exec(null, null, "InAppBrowser", "show", []);
        }

        this.startPoll = function(pollFunction, pollInterval){
           lastPollInterval = pollInterval;
           lastPollFunction = pollFunction;
           exec(null, null, "InAppBrowser", "startPoll", [pollFunction, pollInterval])
        }

        this.stopPoll = function() {
           clearPolling();
           exec(null, null, "InAppBrowser", "stopPoll", []);
        }

        this.hide = function(releaseResources){

            //TODO: suspend exit

            //TODO: Polling
            //TODO: If release remove listeners
            console.log(this.channels);
            var exitHandlersToRestore = {},
                exitChannel = this.channels['exit'],
                exitRestoreCallBack = function(){
                    console.log('TODO');
                    //TODO: re-establish exit
                };

            for(var exitCallbackObserverId in exitChannel.handlers) {
                var eventHandler = exitChannel.handlers[exitCallbackObserverId];
                exitHandlersToRestore[exitCallbackObserverId] = exitChannel.handlers[exitCallbackObserverId];
                this.removeEventListener('exit', eventHandler);
            }

            if(exitHandlersToRestore){
                console.log('Had functions to restore');
                //TODO add the restore callback to exit.
            }

            console.log(exitHandlersToRestore);
            console.log(this.channels);

            // Release resources has no effect in native iOS - the IAB
            // Is fully closed & the JS pretends it isn't
            exec(null,null,"InAppBrowser", "hide", [releaseResources]);
        }

        this.unHide = function(strUrl, eventname){
            lastUrl = strUrl || lastUrl;

            //TODO: Polling

            var cb = function(eventname) {
               me._eventHandler(eventname);
            };
            exec(cb, cb, "InAppBrowser", "unHide", [lastUrl, lastWindowName, lasrWindowFeatures]);
        }

        this.addEventListener = function (eventname,f) {
            if (eventname in this.channels) {
                me.channels[eventname].subscribe(f);
            }
        }

        this.removeEventListener = function (eventname, f) {
            if (eventname in this.channels) {
                this.channels[eventname].unsubscribe(f);
            }
        }

        this.executeScript = function (injectDetails, cb) {
            if (injectDetails.code) {
                exec(cb, null, "InAppBrowser", "injectScriptCode", [injectDetails.code, !!cb]);
            } else if (injectDetails.file) {
                exec(cb, null, "InAppBrowser", "injectScriptFile", [injectDetails.file, !!cb]);
            } else {
                throw new Error('executeScript requires exactly one of code or file to be specified');
            }
        }

        this.insertCSS = function (injectDetails, cb) {
            if (injectDetails.code) {
                exec(cb, null, "InAppBrowser", "injectStyleCode", [injectDetails.code, !!cb]);
            } else if (injectDetails.file) {
                exec(cb, null, "InAppBrowser", "injectStyleFile", [injectDetails.file, !!cb]);
            } else {
                throw new Error('insertCSS requires exactly one of code or file to be specified');
            }
        }
    }

    module.exports = function(strUrl, strWindowName, strWindowFeatures, callbacks) {
        // Don't catch calls that write to existing frames (e.g. named iframes).
        if (window.frames && window.frames[strWindowName]) {
            var origOpenFunc = modulemapper.getOriginalSymbol(window, 'open');
            return origOpenFunc.apply(window, arguments);
        }

        strUrl = urlutil.makeAbsolute(strUrl);
        inAppBrowserInstance = new InAppBrowser();

        callbacks = callbacks || {};
        for (var callbackName in callbacks) {
            inAppBrowserInstance.addEventListener(callbackName, callbacks[callbackName]);
        }

        var cb = function(eventname) {
           inAppBrowserInstance._eventHandler(eventname);
        };

        strWindowFeatures = strWindowFeatures || "";

        lastUrl = strUrl;
        lastWindowName = strWindowName;
        lastWindowFeatures = strWindowFeatures;
        exec(cb, cb, "InAppBrowser", "open", [strUrl, strWindowName, strWindowFeatures]);
        return inAppBrowserInstance;
    };
})();
<commit_msg>Trying to suspend the exit callback - improving check to see whether restore callback should be called<commit_after>/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

(function() {
    // special patch to correctly work on Ripple emulator (CB-9760)
    if (window.parent && !!window.parent.ripple) { // https://gist.github.com/triceam/4658021
        module.exports = window.open.bind(window); // fallback to default window.open behaviour
        return;
    }

    var exec = require('cordova/exec');
    var channel = require('cordova/channel');
    var modulemapper = require('cordova/modulemapper');
    var urlutil = require('cordova/urlutil');

    var inAppBrowserInstance = null;
    var lastUrl = '';
    var lastWindowName = '';
    var lasrWindowFeatures = '';

    var InAppBrowser = function() {

        var me = this,
            lastPollIntervalToRestore = null,
            lastPollFunctionToRestore = null;

        function clearPolling () {
            lastPollIntervalToRestore = null;
            lastPollFunctionToRestore = null;
        }

        function clearRestoring(){
            clearPolling();
        }

        this.channels = {
            'loadstart': channel.create('loadstart'),
            'loadstop' : channel.create('loadstop'),
            'loaderror' : channel.create('loaderror'),
            'hidden' : channel.create('hidden'),
            'unhidden' : channel.create('unhidden'),
            'pollresult' : channel.create('pollresult'),
            'exit' : channel.create('exit')
        }

        this._eventHandler = function(event) {
            if (event && (event.type in this.channels)) {
                console.log(this.channels);
                this.channels[event.type].fire(event);
            }
        }

        this.close = function(eventname) {
           exec(null, null, "InAppBrowser", "close", []);
           this.stopPoll();
        }

        this.show = function(eventname) {
            exec(null, null, "InAppBrowser", "show", []);
        }

        this.startPoll = function(pollFunction, pollInterval){
           lastPollInterval = pollInterval;
           lastPollFunction = pollFunction;
           exec(null, null, "InAppBrowser", "startPoll", [pollFunction, pollInterval])
        }

        this.stopPoll = function() {
           clearPolling();
           exec(null, null, "InAppBrowser", "stopPoll", []);
        }

        this.hide = function(releaseResources){

            //TODO: suspend exit

            //TODO: Polling
            //TODO: If release remove listeners
            console.log(this.channels);
            var exitHandlersToRestore = {},
                exitChannel = this.channels['exit'],
                exitRestoreCallBack = function(){
                    console.log('TODO');
                    //TODO: re-establish exit
                };

            for(var exitCallbackObserverId in exitChannel.handlers) {
                var eventHandler = exitChannel.handlers[exitCallbackObserverId];
                exitHandlersToRestore[exitCallbackObserverId] = exitChannel.handlers[exitCallbackObserverId];
                this.removeEventListener('exit', eventHandler);
            }

            if(exitHandlersToRestore !== {} ){
                console.log('Had functions to restore');
                this.addEventListener('exit', exitRestoreCallBack);
                //TODO add the restore callback to exit.
            }

            console.log(exitHandlersToRestore);
            console.log(this.channels);

            // Release resources has no effect in native iOS - the IAB
            // Is fully closed & the JS pretends it isn't
            exec(null,null,"InAppBrowser", "hide", [releaseResources]);
        }

        this.unHide = function(strUrl, eventname){
            lastUrl = strUrl || lastUrl;

            //TODO: Polling

            var cb = function(eventname) {
               me._eventHandler(eventname);
            };
            exec(cb, cb, "InAppBrowser", "unHide", [lastUrl, lastWindowName, lasrWindowFeatures]);
        }

        this.addEventListener = function (eventname,f) {
            if (eventname in this.channels) {
                me.channels[eventname].subscribe(f);
            }
        }

        this.removeEventListener = function (eventname, f) {
            if (eventname in this.channels) {
                this.channels[eventname].unsubscribe(f);
            }
        }

        this.executeScript = function (injectDetails, cb) {
            if (injectDetails.code) {
                exec(cb, null, "InAppBrowser", "injectScriptCode", [injectDetails.code, !!cb]);
            } else if (injectDetails.file) {
                exec(cb, null, "InAppBrowser", "injectScriptFile", [injectDetails.file, !!cb]);
            } else {
                throw new Error('executeScript requires exactly one of code or file to be specified');
            }
        }

        this.insertCSS = function (injectDetails, cb) {
            if (injectDetails.code) {
                exec(cb, null, "InAppBrowser", "injectStyleCode", [injectDetails.code, !!cb]);
            } else if (injectDetails.file) {
                exec(cb, null, "InAppBrowser", "injectStyleFile", [injectDetails.file, !!cb]);
            } else {
                throw new Error('insertCSS requires exactly one of code or file to be specified');
            }
        }
    }

    module.exports = function(strUrl, strWindowName, strWindowFeatures, callbacks) {
        // Don't catch calls that write to existing frames (e.g. named iframes).
        if (window.frames && window.frames[strWindowName]) {
            var origOpenFunc = modulemapper.getOriginalSymbol(window, 'open');
            return origOpenFunc.apply(window, arguments);
        }

        strUrl = urlutil.makeAbsolute(strUrl);
        inAppBrowserInstance = new InAppBrowser();

        callbacks = callbacks || {};
        for (var callbackName in callbacks) {
            inAppBrowserInstance.addEventListener(callbackName, callbacks[callbackName]);
        }

        var cb = function(eventname) {
           inAppBrowserInstance._eventHandler(eventname);
        };

        strWindowFeatures = strWindowFeatures || "";

        lastUrl = strUrl;
        lastWindowName = strWindowName;
        lastWindowFeatures = strWindowFeatures;
        exec(cb, cb, "InAppBrowser", "open", [strUrl, strWindowName, strWindowFeatures]);
        return inAppBrowserInstance;
    };
})();
<|endoftext|>