<commit_before>/**
 * AccessKeyedElement is mixed into other classes to provide an `accesskey` HTML attribute.
 * Access keys allow an user to go to a specific element by using
 * a shortcut combination of a browser specific keys + the key
 * set to the field.
 *
 *     @example
 *     // AccessKeyedElement provides an `accesskey` attribute to the
 *     // ButtonWidget class.
 *     var button = new OO.ui.ButtonWidget( {
 *         label: 'Button with access key',
 *         accessKey: 'k'
 *     } );
 *     $( document.body ).append( button.$element );
 *
 * @abstract
 * @class
 *
 * @constructor
 * @param {Object} [config] Configuration options
 * @cfg {jQuery} [$accessKeyed] The element to which the `accesskey` attribute is applied.
 *  If this config is omitted, the access key functionality is applied to $element, the
 *  element created by the class.
 * @cfg {string|Function} [accessKey] The key or a function that returns the key. If
 *  this config is omitted, no access key will be added.
 */
OO.ui.mixin.AccessKeyedElement = function OoUiMixinAccessKeyedElement( config ) {
	// Configuration initialization
	config = config || {};

	// Properties
	this.$accessKeyed = null;
	this.accessKey = null;

	// Initialization
	this.setAccessKey( config.accessKey || null );
	this.setAccessKeyedElement( config.$accessKeyed || this.$element );

	// If this is also a TitledElement and it initialized before we did, we may have
	// to update the title with the access key
	if ( this.updateTitle ) {
		this.updateTitle();
	}
};

/* Setup */

OO.initClass( OO.ui.mixin.AccessKeyedElement );

/* Static Properties */

/**
 * The access key, a function that returns a key, or `null` for no access key.
 *
 * @static
 * @inheritable
 * @property {string|Function|null}
 */
OO.ui.mixin.AccessKeyedElement.static.accessKey = null;

/* Methods */

/**
 * Set the access keyed element.
 *
 * This method is used to retarget a AccessKeyedElement mixin so that its functionality applies to
 * the specified element.
 * If an element is already set, the mixin's effect on that element is removed before the new
 * element is set up.
 *
 * @param {jQuery} $accessKeyed Element that should use the 'access keyed' functionality
 */
OO.ui.mixin.AccessKeyedElement.prototype.setAccessKeyedElement = function ( $accessKeyed ) {
	if ( this.$accessKeyed ) {
		this.$accessKeyed.removeAttr( 'accesskey' );
	}

	this.$accessKeyed = $accessKeyed;
	if ( this.accessKey ) {
		this.$accessKeyed.attr( 'accesskey', this.accessKey );
	}
};

/**
 * Set access key.
 *
 * @param {string|Function|null} accessKey Key, a function that returns a key, or `null` for no
 *  access key
 * @chainable
 * @return {OO.ui.Element} The element, for chaining
 */
OO.ui.mixin.AccessKeyedElement.prototype.setAccessKey = function ( accessKey ) {
	accessKey = typeof accessKey === 'string' ? OO.ui.resolveMsg( accessKey ) : null;

	if ( this.accessKey !== accessKey ) {
		if ( this.$accessKeyed ) {
			if ( accessKey !== null ) {
				this.$accessKeyed.attr( 'accesskey', accessKey );
			} else {
				this.$accessKeyed.removeAttr( 'accesskey' );
			}
		}
		this.accessKey = accessKey;

		// Only if this is a TitledElement
		if ( this.updateTitle ) {
			this.updateTitle();
		}
	}

	return this;
};

/**
 * Get access key.
 *
 * @return {string} accessKey string
 */
OO.ui.mixin.AccessKeyedElement.prototype.getAccessKey = function () {
	return this.accessKey;
};

/**
 * Add information about the access key to the element's tooltip label.
 * (This is only public for hacky usage in FieldLayout.)
 *
 * @param {string} title Tooltip label for `title` attribute
 * @return {string}
 */
OO.ui.mixin.AccessKeyedElement.prototype.formatTitleWithAccessKey = function ( title ) {
	var accessKey;

	if ( !this.$accessKeyed ) {
		// Not initialized yet; the constructor will call updateTitle() which will rerun this
		// function.
		return title;
	}
	// Use jquery.accessKeyLabel if available to show modifiers, otherwise just display the
	// single key.
	if ( $.fn.updateTooltipAccessKeys && $.fn.updateTooltipAccessKeys.getAccessKeyLabel ) {
		accessKey = $.fn.updateTooltipAccessKeys.getAccessKeyLabel( this.$accessKeyed[ 0 ] );
	} else {
		accessKey = this.getAccessKey();
	}
	if ( accessKey ) {
		title += ' [' + accessKey + ']';
	}
	return title;
};
<commit_msg>Fix broken resolveMsg() call in the AccessKeyedElement mixin<commit_after>/**
 * AccessKeyedElement is mixed into other classes to provide an `accesskey` HTML attribute.
 * Access keys allow an user to go to a specific element by using
 * a shortcut combination of a browser specific keys + the key
 * set to the field.
 *
 *     @example
 *     // AccessKeyedElement provides an `accesskey` attribute to the
 *     // ButtonWidget class.
 *     var button = new OO.ui.ButtonWidget( {
 *         label: 'Button with access key',
 *         accessKey: 'k'
 *     } );
 *     $( document.body ).append( button.$element );
 *
 * @abstract
 * @class
 *
 * @constructor
 * @param {Object} [config] Configuration options
 * @cfg {jQuery} [$accessKeyed] The element to which the `accesskey` attribute is applied.
 *  If this config is omitted, the access key functionality is applied to $element, the
 *  element created by the class.
 * @cfg {string|Function} [accessKey] The key or a function that returns the key. If
 *  this config is omitted, no access key will be added.
 */
OO.ui.mixin.AccessKeyedElement = function OoUiMixinAccessKeyedElement( config ) {
	// Configuration initialization
	config = config || {};

	// Properties
	this.$accessKeyed = null;
	this.accessKey = null;

	// Initialization
	this.setAccessKey( config.accessKey || null );
	this.setAccessKeyedElement( config.$accessKeyed || this.$element );

	// If this is also a TitledElement and it initialized before we did, we may have
	// to update the title with the access key
	if ( this.updateTitle ) {
		this.updateTitle();
	}
};

/* Setup */

OO.initClass( OO.ui.mixin.AccessKeyedElement );

/* Static Properties */

/**
 * The access key, a function that returns a key, or `null` for no access key.
 *
 * @static
 * @inheritable
 * @property {string|Function|null}
 */
OO.ui.mixin.AccessKeyedElement.static.accessKey = null;

/* Methods */

/**
 * Set the access keyed element.
 *
 * This method is used to retarget a AccessKeyedElement mixin so that its functionality applies to
 * the specified element.
 * If an element is already set, the mixin's effect on that element is removed before the new
 * element is set up.
 *
 * @param {jQuery} $accessKeyed Element that should use the 'access keyed' functionality
 */
OO.ui.mixin.AccessKeyedElement.prototype.setAccessKeyedElement = function ( $accessKeyed ) {
	if ( this.$accessKeyed ) {
		this.$accessKeyed.removeAttr( 'accesskey' );
	}

	this.$accessKeyed = $accessKeyed;
	if ( this.accessKey ) {
		this.$accessKeyed.attr( 'accesskey', this.accessKey );
	}
};

/**
 * Set access key.
 *
 * @param {string|Function|null} accessKey Key, a function that returns a key, or `null` for no
 *  access key
 * @chainable
 * @return {OO.ui.Element} The element, for chaining
 */
OO.ui.mixin.AccessKeyedElement.prototype.setAccessKey = function ( accessKey ) {
	accessKey = OO.ui.resolveMsg( accessKey );
	accessKey = typeof accessKey === 'string' ? accessKey : null;

	if ( this.accessKey !== accessKey ) {
		if ( this.$accessKeyed ) {
			if ( accessKey !== null ) {
				this.$accessKeyed.attr( 'accesskey', accessKey );
			} else {
				this.$accessKeyed.removeAttr( 'accesskey' );
			}
		}
		this.accessKey = accessKey;

		// Only if this is a TitledElement
		if ( this.updateTitle ) {
			this.updateTitle();
		}
	}

	return this;
};

/**
 * Get access key.
 *
 * @return {string} accessKey string
 */
OO.ui.mixin.AccessKeyedElement.prototype.getAccessKey = function () {
	return this.accessKey;
};

/**
 * Add information about the access key to the element's tooltip label.
 * (This is only public for hacky usage in FieldLayout.)
 *
 * @param {string} title Tooltip label for `title` attribute
 * @return {string}
 */
OO.ui.mixin.AccessKeyedElement.prototype.formatTitleWithAccessKey = function ( title ) {
	var accessKey;

	if ( !this.$accessKeyed ) {
		// Not initialized yet; the constructor will call updateTitle() which will rerun this
		// function.
		return title;
	}
	// Use jquery.accessKeyLabel if available to show modifiers, otherwise just display the
	// single key.
	if ( $.fn.updateTooltipAccessKeys && $.fn.updateTooltipAccessKeys.getAccessKeyLabel ) {
		accessKey = $.fn.updateTooltipAccessKeys.getAccessKeyLabel( this.$accessKeyed[ 0 ] );
	} else {
		accessKey = this.getAccessKey();
	}
	if ( accessKey ) {
		title += ' [' + accessKey + ']';
	}
	return title;
};
<|endoftext|>


<commit_before>/**
 * Package dependencies
 */
const RSA = require('node-rsa')
const crypto = require('crypto')

/**
 * Local dependencies
 */
const {buf2ab,ab2buf} = require('../encodings')
const CryptoKey = require('../CryptoKey')
const CryptoKeyPair = require('../CryptoKeyPair')
const KeyAlgorithm = require('./KeyAlgorithm')
const RsaKeyAlgorithm = require('./RsaKeyAlgorithm')
const OperationError = require('../errors/OperationError')
const InvalidAccessError = require('../errors/InvalidAccessError')

/**
 * RsaHashedKeyAlgorithm
 */
class RsaHashedKeyAlgorithm extends RsaKeyAlgorithm {

  /**
   * constructor
   *
   * @param {object} algorithm
   */
  constructor (algorithm) {
    super(algorithm)

    // validate hash
    if (!(this.hash instanceof KeyAlgorithm)) {
      throw new Error('hash of RsaHashedKeyAlgorithm must be a KeyAlgorithm')
    }
  }

  /**
   * sign
   *
   * @description
   * Create an RSA digital signature
   *
   * @param {CryptoKey} key
   * @param {BufferSource} data
   *
   * @returns {string}
   */
  sign (key, data) {
    if (key.type !== 'private') {
      throw new InvalidAccessError()
    }

    try {
      let pem = key.key
      let signer = crypto.createSign('RSA-SHA256')

      signer.update(data.toString())
      return buf2ab(signer.sign(pem))
    } catch (error) {
      throw new OperationError()
    }
  }

  /**
   * verify
   *
   * @description
   *
   * @param {CryptoKey} key
   * @param {BufferSource} signature
   * @param {BufferSource} data
   *
   * @returns {Boolean}
   */
  verify (key, signature, data) {
    if (key.type !== 'public') {
      throw new InvalidAccessError()
    }

    try {
      let pem = key.key
      let verifier = crypto.createVerify('RSA-SHA256')

      verifier.update(data)
      return verifier.verify(pem, ab2buf(signature))
    } catch (error) {
      throw new OperationError()
    }
  }

  /**
   * generateKey
   *
   * @description
   * Generate an RSA key pair
   *
   * @param {RsaHashedKeyGenParams} params
   * @returns {CryptoKeyPair}
   */
  generateKey (params, extractable, usages) {

    // validate usages
    usages.forEach(usage => {
      if (usage !== 'sign' && usage !== 'verify') {
        throw new SyntaxError()
      }
    })

    let keypair

    // Generate RSA keypair
    try {
      // TODO
      // - fallback on system OpenSSL + child_process
      // - what is this bit option, where do we get the value from in this api?
      let key = new RSA({b:512})
      let {modulusLength,publicExponent} = params
      keypair = key.generateKeyPair(modulusLength, publicExponent)

    // cast error
    } catch (error) {
      throw new OperationError()
    }

    // cast params to algorithm
    let algorithm = new RsaHashedKeyAlgorithm(params)

    // instantiate publicKey
    let publicKey = new CryptoKey({
      type: 'public',
      algorithm,
      extractable: true,
      usages: ['verify'],
      key: keypair.exportKey('public')
    })

    // instantiate privateKey
    let privateKey = new CryptoKey({
      type: 'private',
      algorithm,
      // TODO is there a typo in the spec?
      // it says "extractable" instead of "false"
      extractable: false,
      usages: ['sign'],
      key: keypair.exportKey('private')
    })

    // return a new keypair
    return new CryptoKeyPair({publicKey,privateKey})
  }

  /**
   * importKey
   *
   * @description
   *
   * @param {string} format
   * @param {string|JsonWebKey} keyData
   * @param {KeyAlgorithm} algorithm
   * @param {Boolean} extractable
   * @param {Array} keyUsages
   *
   * @returns {CryptoKey}
   */
  importKey (format, keyData, algorithm, extractable, keyUsages) {
    let key

    if (format === 'spki') {
      // ...
    } else if (format === 'pkcs8') {

    } else if (format === 'jwk') {
      let jwk = new JsonWebKey(keyData)

      if (jwk.d && usages.some(usage => usage !== 'sign')) {
        throw new SyntaxError()
      }

      if (jwk.d === undefined && usages.some(usage => usage !== 'verify')) {
        throw new SyntaxError()
      }

      if (jwk.kty !== 'RSA') {
        throw new DataError()
      }

      if (jwk.use !== undefined && jwk.use !== 'sig') {
        throw new DataError()
      }

      // TODO
      //if (jwk.key_ops ...) {
      //  throw new DataError()
      //}

      let hash

      if (jwk.alg === undefined) {
        // leave hash undefined
      } else if (jwk.alg === 'RS1') {
        hash = 'SHA-1'
      } else if (jwk.alg === 'RS256') {
        hash = 'SHA-256'
      } else if (jwk.alg === 'RS384') {
        hash = 'SHA-384'
      } else if (jwk.alg === 'RS512') {
        hash = 'SHA-512'
      } else {
        // perform any key import steps defined by other applicable specifications
        // passing format, jwk, and obtaining hash

        throw new DataError()
      }

      if (hash !== undefined) {
        let normalizedHash = algorithms.normalize('digest', hash)

        if (normalizedHash !== normalizedAlgorithm.hash) {
          throw new DataError()
        }

        if (jwk.d) {
          // TODO
          // - validate JWK requirements
          // - translate JWK to PEM
          key = new CryptoKey({
            type: 'private',
            //algorithm,
            //extractable: false,
            usages: ['sign'],
            key: jwk2pem(jwk)
          })
        } else {
          // TODO
          // - validate JWK requirements
          // - translate JWK to PEM
          key = new CryptoKey({
            type: 'public',
            //algorithm,
            //extractable: false,
            usages: ['verify'],
            key: jwk2pem(jwk)
          })
        }
      }
    } else {
      throw new NotSupportedError()
    }

    let algorithm = new RsaHashedKeyAlgorithm({
      name: 'RSASSA-PKCS1-v1_5',
      modulusLength: getBitLength(jwk.n),
      publicExponent: new BigInteger(jwk.e),
      hash: hash
    })

    key.algorithm = algorithm

    return key
  }

  /**
   * exportKey
   *
   * @description
   * @param {}
   * @returns {}
   */
  exportKey () {
    // TODO
  }
}

/**
 * Export
 */
module.exports = RsaHashedKeyAlgorithm
<commit_msg>fix(RsaHashedKeyAlgorithm): rename colliding symbol<commit_after>/**
 * Package dependencies
 */
const RSA = require('node-rsa')
const crypto = require('crypto')

/**
 * Local dependencies
 */
const {buf2ab,ab2buf} = require('../encodings')
const CryptoKey = require('../CryptoKey')
const CryptoKeyPair = require('../CryptoKeyPair')
const KeyAlgorithm = require('./KeyAlgorithm')
const RsaKeyAlgorithm = require('./RsaKeyAlgorithm')
const OperationError = require('../errors/OperationError')
const InvalidAccessError = require('../errors/InvalidAccessError')

/**
 * RsaHashedKeyAlgorithm
 */
class RsaHashedKeyAlgorithm extends RsaKeyAlgorithm {

  /**
   * constructor
   *
   * @param {object} algorithm
   */
  constructor (algorithm) {
    super(algorithm)

    // validate hash
    if (!(this.hash instanceof KeyAlgorithm)) {
      throw new Error('hash of RsaHashedKeyAlgorithm must be a KeyAlgorithm')
    }
  }

  /**
   * sign
   *
   * @description
   * Create an RSA digital signature
   *
   * @param {CryptoKey} key
   * @param {BufferSource} data
   *
   * @returns {string}
   */
  sign (key, data) {
    if (key.type !== 'private') {
      throw new InvalidAccessError()
    }

    try {
      let pem = key.key
      let signer = crypto.createSign('RSA-SHA256')

      signer.update(data.toString())
      return buf2ab(signer.sign(pem))
    } catch (error) {
      throw new OperationError()
    }
  }

  /**
   * verify
   *
   * @description
   *
   * @param {CryptoKey} key
   * @param {BufferSource} signature
   * @param {BufferSource} data
   *
   * @returns {Boolean}
   */
  verify (key, signature, data) {
    if (key.type !== 'public') {
      throw new InvalidAccessError()
    }

    try {
      let pem = key.key
      let verifier = crypto.createVerify('RSA-SHA256')

      verifier.update(data)
      return verifier.verify(pem, ab2buf(signature))
    } catch (error) {
      throw new OperationError()
    }
  }

  /**
   * generateKey
   *
   * @description
   * Generate an RSA key pair
   *
   * @param {RsaHashedKeyGenParams} params
   * @returns {CryptoKeyPair}
   */
  generateKey (params, extractable, usages) {

    // validate usages
    usages.forEach(usage => {
      if (usage !== 'sign' && usage !== 'verify') {
        throw new SyntaxError()
      }
    })

    let keypair

    // Generate RSA keypair
    try {
      // TODO
      // - fallback on system OpenSSL + child_process
      // - what is this bit option, where do we get the value from in this api?
      let key = new RSA({b:512})
      let {modulusLength,publicExponent} = params
      keypair = key.generateKeyPair(modulusLength, publicExponent)

    // cast error
    } catch (error) {
      throw new OperationError()
    }

    // cast params to algorithm
    let algorithm = new RsaHashedKeyAlgorithm(params)

    // instantiate publicKey
    let publicKey = new CryptoKey({
      type: 'public',
      algorithm,
      extractable: true,
      usages: ['verify'],
      key: keypair.exportKey('public')
    })

    // instantiate privateKey
    let privateKey = new CryptoKey({
      type: 'private',
      algorithm,
      // TODO is there a typo in the spec?
      // it says "extractable" instead of "false"
      extractable: false,
      usages: ['sign'],
      key: keypair.exportKey('private')
    })

    // return a new keypair
    return new CryptoKeyPair({publicKey,privateKey})
  }

  /**
   * importKey
   *
   * @description
   *
   * @param {string} format
   * @param {string|JsonWebKey} keyData
   * @param {KeyAlgorithm} algorithm
   * @param {Boolean} extractable
   * @param {Array} keyUsages
   *
   * @returns {CryptoKey}
   */
  importKey (format, keyData, algorithm, extractable, keyUsages) {
    let key

    if (format === 'spki') {
      // ...
    } else if (format === 'pkcs8') {

    } else if (format === 'jwk') {
      let jwk = new JsonWebKey(keyData)

      if (jwk.d && usages.some(usage => usage !== 'sign')) {
        throw new SyntaxError()
      }

      if (jwk.d === undefined && usages.some(usage => usage !== 'verify')) {
        throw new SyntaxError()
      }

      if (jwk.kty !== 'RSA') {
        throw new DataError()
      }

      if (jwk.use !== undefined && jwk.use !== 'sig') {
        throw new DataError()
      }

      // TODO
      //if (jwk.key_ops ...) {
      //  throw new DataError()
      //}

      let hash

      if (jwk.alg === undefined) {
        // leave hash undefined
      } else if (jwk.alg === 'RS1') {
        hash = 'SHA-1'
      } else if (jwk.alg === 'RS256') {
        hash = 'SHA-256'
      } else if (jwk.alg === 'RS384') {
        hash = 'SHA-384'
      } else if (jwk.alg === 'RS512') {
        hash = 'SHA-512'
      } else {
        // perform any key import steps defined by other applicable specifications
        // passing format, jwk, and obtaining hash

        throw new DataError()
      }

      if (hash !== undefined) {
        let normalizedHash = algorithms.normalize('digest', hash)

        if (normalizedHash !== normalizedAlgorithm.hash) {
          throw new DataError()
        }

        if (jwk.d) {
          // TODO
          // - validate JWK requirements
          // - translate JWK to PEM
          key = new CryptoKey({
            type: 'private',
            //algorithm,
            //extractable: false,
            usages: ['sign'],
            key: jwk2pem(jwk)
          })
        } else {
          // TODO
          // - validate JWK requirements
          // - translate JWK to PEM
          key = new CryptoKey({
            type: 'public',
            //algorithm,
            //extractable: false,
            usages: ['verify'],
            key: jwk2pem(jwk)
          })
        }
      }
    } else {
      throw new NotSupportedError()
    }

    let alg = new RsaHashedKeyAlgorithm({
      name: 'RSASSA-PKCS1-v1_5',
      modulusLength: getBitLength(jwk.n),
      publicExponent: new BigInteger(jwk.e),
      hash: hash
    })

    key.algorithm = alg

    return key
  }

  /**
   * exportKey
   *
   * @description
   * @param {}
   * @returns {}
   */
  exportKey () {
    // TODO
  }
}

/**
 * Export
 */
module.exports = RsaHashedKeyAlgorithm
<|endoftext|>


<commit_before>// @flow
import {
  basePlacements,
  top,
  left,
  right,
  bottom,
  type Placement,
} from '../enums';
import type { State, Modifier, Rect, Padding } from '../types';
import getBasePlacement from '../utils/getBasePlacement';
import getMainAxisFromPlacement from '../utils/getMainAxisFromPlacement';
import getAltAxis from '../utils/getAltAxis';
import mergePaddingObject from '../utils/mergePaddingObject';
import expandToHashMap from '../utils/expandToHashMap';
import within from '../utils/within';

type Options = {
  /* Prevents boundaries overflow on the main axis */
  mainAxis: boolean,
  /* Prevents boundaries overflow on the alternate axis */
  altAxis: boolean,
  /* Allows the popper to overflow from its boundaries to keep it near its reference element */
  tether: boolean,
  /* Sets a padding to the provided boundary */
  padding: Padding,
};

export function preventOverflow(state: State, options?: Options = {}) {
  const {
    mainAxis: checkMainAxis = true,
    altAxis: checkAltAxis = false,
    tether = false,
    padding = 0,
  } = options;
  const overflow = state.modifiersData.detectOverflow;
  const basePlacement = getBasePlacement(state.placement);
  const mainAxis = getMainAxisFromPlacement(basePlacement);
  const altAxis = getAltAxis(mainAxis);
  const popperOffsets = state.offsets.popper;
  const referenceRect = state.measures.reference;
  const popperRect = state.measures.popper;
  const paddingObject = mergePaddingObject(
    typeof padding !== 'number'
      ? padding
      : expandToHashMap(padding, basePlacements)
  );

  if (checkMainAxis) {
    const mainSide = mainAxis === 'y' ? top : left;
    const altSide = mainAxis === 'y' ? bottom : right;
    const len = mainAxis === 'y' ? 'height' : 'width';

    let offset = within(
      popperOffsets[mainAxis] + overflow[mainSide] + paddingObject[mainSide],
      popperOffsets[mainAxis],
      popperOffsets[mainAxis] - overflow[altSide] - paddingObject[altSide]
    );

    if (tether) {
      offset = within(
        state.offsets.popper[mainAxis] -
          referenceRect[len] / 2 +
          popperRect[len] / 2,
        offset,
        state.offsets.popper[mainAxis] +
          referenceRect[len] / 2 -
          popperRect[len] / 2
      );
    }

    state.offsets.popper[mainAxis] = offset;
  }
  if (checkAltAxis) {
    const mainSide = mainAxis === 'x' ? top : left;
    const altSide = mainAxis === 'x' ? bottom : right;

    state.offsets.popper[altAxis] = within(
      popperOffsets[altAxis] + overflow[mainSide] + paddingObject[mainSide],
      popperOffsets[altAxis],
      popperOffsets[altAxis] - overflow[altSide] - paddingObject[altSide]
    );
  }

  return state;
}

export default ({
  name: 'preventOverflow',
  enabled: true,
  phase: 'main',
  fn: preventOverflow,
  requires: ['detectOverflow'],
}: Modifier);
<commit_msg>fix: enable tether option by default<commit_after>// @flow
import {
  basePlacements,
  top,
  left,
  right,
  bottom,
  type Placement,
} from '../enums';
import type { State, Modifier, Rect, Padding } from '../types';
import getBasePlacement from '../utils/getBasePlacement';
import getMainAxisFromPlacement from '../utils/getMainAxisFromPlacement';
import getAltAxis from '../utils/getAltAxis';
import mergePaddingObject from '../utils/mergePaddingObject';
import expandToHashMap from '../utils/expandToHashMap';
import within from '../utils/within';

type Options = {
  /* Prevents boundaries overflow on the main axis */
  mainAxis: boolean,
  /* Prevents boundaries overflow on the alternate axis */
  altAxis: boolean,
  /* Allows the popper to overflow from its boundaries to keep it near its reference element */
  tether: boolean,
  /* Sets a padding to the provided boundary */
  padding: Padding,
};

export function preventOverflow(state: State, options?: Options = {}) {
  const {
    mainAxis: checkMainAxis = true,
    altAxis: checkAltAxis = false,
    tether = true,
    padding = 0,
  } = options;
  const overflow = state.modifiersData.detectOverflow;
  const basePlacement = getBasePlacement(state.placement);
  const mainAxis = getMainAxisFromPlacement(basePlacement);
  const altAxis = getAltAxis(mainAxis);
  const popperOffsets = state.offsets.popper;
  const referenceRect = state.measures.reference;
  const popperRect = state.measures.popper;
  const paddingObject = mergePaddingObject(
    typeof padding !== 'number'
      ? padding
      : expandToHashMap(padding, basePlacements)
  );

  if (checkMainAxis) {
    const mainSide = mainAxis === 'y' ? top : left;
    const altSide = mainAxis === 'y' ? bottom : right;
    const len = mainAxis === 'y' ? 'height' : 'width';

    let offset = within(
      popperOffsets[mainAxis] + overflow[mainSide] + paddingObject[mainSide],
      popperOffsets[mainAxis],
      popperOffsets[mainAxis] - overflow[altSide] - paddingObject[altSide]
    );

    if (tether) {
      offset = within(
        state.offsets.popper[mainAxis] -
          referenceRect[len] / 2 +
          popperRect[len] / 2,
        offset,
        state.offsets.popper[mainAxis] +
          referenceRect[len] / 2 -
          popperRect[len] / 2
      );
    }

    state.offsets.popper[mainAxis] = offset;
  }
  if (checkAltAxis) {
    const mainSide = mainAxis === 'x' ? top : left;
    const altSide = mainAxis === 'x' ? bottom : right;

    state.offsets.popper[altAxis] = within(
      popperOffsets[altAxis] + overflow[mainSide] + paddingObject[mainSide],
      popperOffsets[altAxis],
      popperOffsets[altAxis] - overflow[altSide] - paddingObject[altSide]
    );
  }

  return state;
}

export default ({
  name: 'preventOverflow',
  enabled: true,
  phase: 'main',
  fn: preventOverflow,
  requires: ['detectOverflow'],
}: Modifier);
<|endoftext|>


<commit_before>import {createDiv} from '../common/cElement';
import dragStart from '../common/dragStart';
import injectBuffLog from '../buffLog/injectBuffLog';
import injectNotepadShowLogs from '../combatLog';
import injectOnlinePlayers from '../onlinePlayers';
import injectRecipeManager from '../recipeMgr/recipeMgr';
import insertQuickExtract from '../quickExtract';
import insertQuickWear from '../quickWear/quickWear';
import * as findBuffs from '../findBuffs';
import * as fshGa from '../support/fshGa';
import * as lists from '../lists';
import * as misc from '../misc';
import * as system from '../support/system';

var helperMenuBlob =
  '

Character

' +
  '
Buff Log
' +
  '
Combat Log
' +
  '
Recipe Manager
' +
  '
Quick Links
' +
  '

Actions

' +
  '
Find Buffs
' +
  '
Find Other
' +
  '
Online Players
' +
  '
AH Quick Search
' +
  '

Extra

' +
  '
Quick Extract
' +
  '
Quick Wear
' +
  '
FS Box Log
' +
  '

FSH developer quick links

' +
  '
PM ' +
  'PointyHair
' +
  '
PM ' +
  'yuuzhan
' +
  '

';

var functionLookup = {
  'Buff Log': injectBuffLog,
  'Combat Log': injectNotepadShowLogs,
  'Recipe Manager': injectRecipeManager,
  'Quick Links': lists.injectQuickLinkManager,
  'Find Buffs': findBuffs.injectFindBuffs,
  'Find Other': findBuffs.injectFindOther,
  'Online Players': injectOnlinePlayers,
  'AH Quick Search': lists.injectAuctionSearch,
  'Quick Extract': insertQuickExtract,
  'Quick Wear': insertQuickWear,
  'FS Box Log': misc.injectFsBoxContent
};

function callHelperFunction(evt) { // jQuery
  var content = document.getElementById('content');
  if (content) {content.innerHTML = '';} else {
    content = createDiv({
      id: 'content',
      style: {display: 'none'}
    });
    document.body.appendChild(content);
  }
  var functionPath = evt.target.textContent;
  var fn = functionLookup[functionPath];
  if (typeof fn === 'function') {
    fshGa.screenview(functionPath);
    fn(content);
  }
  $(content).dialog({width: 'auto', modal: true});
}

function eventHandler(evt) {
  if (evt.target.classList.contains('fshLink')) {
    callHelperFunction(evt);
    return;
  }
  if (evt.target.classList.contains('a-reply')) {
    window.openQuickMsgDialog(evt.target.getAttribute('target_player'));
  }
}

function showHelperMenu() {
  var helperMenu = document.getElementById('helperMenu');
  helperMenu.removeEventListener('mouseenter', showHelperMenu);

  var helperMenuDiv = createDiv({
    id: 'helperMenuDiv',
    className: 'helperMenuDiv',
    style: {
      backgroundImage: 'url(' + system.imageServer +
        '/skin/inner_bg.jpg)'
    }
  });
  helperMenuDiv.insertAdjacentHTML('beforeend', helperMenuBlob);
  helperMenu.appendChild(helperMenuDiv);
  helperMenu.addEventListener('click', function(evt) {
    if (evt.target.id !== 'helperMenu') {return;}
    var menu = evt.target.firstElementChild;
    menu.classList.toggle('showMenuDiv');
  });
  helperMenuDiv.addEventListener('click', eventHandler);
}

function haveNode(node) {
  var helperMenu = createDiv({
    id: 'helperMenu',
    className: 'helperMenu',
    innerHTML: 'Helper Menu'
  });
  if (system.getValue('keepHelperMenuOnScreen')) {
    helperMenu.classList.add('fshFixed');
  }
  helperMenu.addEventListener('mouseenter', showHelperMenu);
  if (system.getValue('draggableHelperMenu')) {
    helperMenu.setAttribute('draggable', 'true');
    helperMenu.addEventListener('dragstart', dragStart);
  }
  node.parentNode.insertBefore(helperMenu, node);
}

export default function injectHelperMenu() {
  // don't put all the menu code here (but call if clicked) to minimize lag
  var node = document.getElementById('statbar-container');
  if (node) {haveNode(node);}
}
<commit_msg>make helperMenu dialog content closer to top of window<commit_after>import {createDiv} from '../common/cElement';
import dragStart from '../common/dragStart';
import injectBuffLog from '../buffLog/injectBuffLog';
import injectNotepadShowLogs from '../combatLog';
import injectOnlinePlayers from '../onlinePlayers';
import injectRecipeManager from '../recipeMgr/recipeMgr';
import insertQuickExtract from '../quickExtract';
import insertQuickWear from '../quickWear/quickWear';
import * as findBuffs from '../findBuffs';
import * as fshGa from '../support/fshGa';
import * as lists from '../lists';
import * as misc from '../misc';
import * as system from '../support/system';

var helperMenuBlob =
  '

Character

' +
  '
Buff Log
' +
  '
Combat Log
' +
  '
Recipe Manager
' +
  '
Quick Links
' +
  '

Actions

' +
  '
Find Buffs
' +
  '
Find Other
' +
  '
Online Players
' +
  '
AH Quick Search
' +
  '

Extra

' +
  '
Quick Extract
' +
  '
Quick Wear
' +
  '
FS Box Log
' +
  '

FSH developer quick links

' +
  '
PM ' +
  'PointyHair
' +
  '
PM ' +
  'yuuzhan
' +
  '

';

var functionLookup = {
  'Buff Log': injectBuffLog,
  'Combat Log': injectNotepadShowLogs,
  'Recipe Manager': injectRecipeManager,
  'Quick Links': lists.injectQuickLinkManager,
  'Find Buffs': findBuffs.injectFindBuffs,
  'Find Other': findBuffs.injectFindOther,
  'Online Players': injectOnlinePlayers,
  'AH Quick Search': lists.injectAuctionSearch,
  'Quick Extract': insertQuickExtract,
  'Quick Wear': insertQuickWear,
  'FS Box Log': misc.injectFsBoxContent
};

function callHelperFunction(evt) { // jQuery
  var content = document.getElementById('content');
  if (content) {content.innerHTML = '';} else {
    content = createDiv({
      id: 'content',
      style: {display: 'none'}
    });
    document.body.appendChild(content);
  }
  var functionPath = evt.target.textContent;
  var fn = functionLookup[functionPath];
  if (typeof fn === 'function') {
    fshGa.screenview(functionPath);
    fn(content);
  }
  $(content).dialog({
    width: 640,
    modal: true,
    position: {my: 'top', at: 'top', offset: '0 60', collision: 'none'}
  });
}

function eventHandler(evt) {
  if (evt.target.classList.contains('fshLink')) {
    callHelperFunction(evt);
    return;
  }
  if (evt.target.classList.contains('a-reply')) {
    window.openQuickMsgDialog(evt.target.getAttribute('target_player'));
  }
}

function showHelperMenu() {
  var helperMenu = document.getElementById('helperMenu');
  helperMenu.removeEventListener('mouseenter', showHelperMenu);

  var helperMenuDiv = createDiv({
    id: 'helperMenuDiv',
    className: 'helperMenuDiv',
    style: {
      backgroundImage: 'url(' + system.imageServer +
        '/skin/inner_bg.jpg)'
    }
  });
  helperMenuDiv.insertAdjacentHTML('beforeend', helperMenuBlob);
  helperMenu.appendChild(helperMenuDiv);
  helperMenu.addEventListener('click', function(evt) {
    if (evt.target.id !== 'helperMenu') {return;}
    var menu = evt.target.firstElementChild;
    menu.classList.toggle('showMenuDiv');
  });
  helperMenuDiv.addEventListener('click', eventHandler);
}

function haveNode(node) {
  var helperMenu = createDiv({
    id: 'helperMenu',
    className: 'helperMenu',
    innerHTML: 'Helper Menu'
  });
  if (system.getValue('keepHelperMenuOnScreen')) {
    helperMenu.classList.add('fshFixed');
  }
  helperMenu.addEventListener('mouseenter', showHelperMenu);
  if (system.getValue('draggableHelperMenu')) {
    helperMenu.setAttribute('draggable', 'true');
    helperMenu.addEventListener('dragstart', dragStart);
  }
  node.parentNode.insertBefore(helperMenu, node);
}

export default function injectHelperMenu() {
  // don't put all the menu code here (but call if clicked) to minimize lag
  var node = document.getElementById('statbar-container');
  if (node) {haveNode(node);}
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2007-2012 Diego Perini
 * All rights reserved.
 *
 * CSS3 pseudo-classes extension for NWMatcher
 *
 * Added capabilities:
 *
 * - structural pseudo-classes
 *
 * :root, :empty,
 * :nth-child(), nth-of-type(),
 * :nth-last-child(), nth-last-of-type(),
 * :first-child, :last-child, :only-child
 * :first-of-type, :last-of-type, :only-of-type
 *
 * - negation, language, target and UI element pseudo-classes
 *
 * :not(), :target, :lang(), :target
 * :link, :visited, :active, :focus, :hover,
 * :checked, :disabled, :enabled, :selected
 */

(function() {

  var LINK_NODES = {
    'a': 1, 'A': 1,
    'area': 1, 'AREA': 1,
    'link': 1, 'LINK': 1
  },

  root = document.documentElement,

  contains = 'compareDocumentPosition' in root ?
    function(container, element) {
      return (container.compareDocumentPosition(element) & 16) == 16;
    } : 'contains' in root ?
    function(container, element) {
      return element.nodeType == 1 && container.contains(element);
    } :
    function(container, element) {
      while ((element = element.parentNode) && element.nodeType == 1) {
        if (element === container) return true;
      }
      return false;
    },

  isLink =
    function(element) {
      return element.getAttribute('href') && LINK_NODES[element.nodeName];
    },

  isEmpty =
    function(node) {
      node = node.firstChild;
      while (node) {
        if (node.nodeType == 3 || node.nodeName > '@') return false;
        node = node.nextSibling;
      }
      return true;
    },

  nthElement =
    function(element, last) {
      var count = 1, succ = last ? 'nextSibling' : 'previousSibling';
      while ((element = element[succ])) {
        if (element.nodeName > '@') ++count;
      }
      return count;
    },

  nthOfType =
    function(element, last) {
      var count = 1, succ = last ? 'nextSibling' : 'previousSibling', type = element.nodeName;
      while ((element = element[succ])) {
        if (element.nodeName == type) ++count;
      }
      return count;
    };

  NW.Dom.Snapshot['contains'] = contains;

  NW.Dom.Snapshot['isLink'] = isLink;
  NW.Dom.Snapshot['isEmpty'] = isEmpty;
  NW.Dom.Snapshot['nthOfType'] = nthOfType;
  NW.Dom.Snapshot['nthElement'] = nthElement;

})();

NW.Dom.registerSelector(
  'nwmatcher:spseudos',
  /^\:(root|empty|(?:first|last|only)(?:-child|-of-type)|nth(?:-last)?(?:-child|-of-type)\(\s*(even|odd|(?:[-+]{0,1}\d*n\s*)?[-+]{0,1}\s*\d*)\s*\))?(.*)/i,
  function(match, source) {

  var a, n, b, status = true, test, type;

  switch (match[1]) {

    case 'root':
      if (match[3])
        source = 'if(e===h||s.contains(h,e)){' + source + '}';
      else
        source = 'if(e===h){' + source + '}';
      break;

    case 'empty':
      source = 'if(s.isEmpty(e)){' + source + '}';
      break;

    default:
      if (match[1] && match[2]) {

        if (match[2] == 'n') {
          source = 'if(e!==h){' + source + '}';
          break;
        } else if (match[2] == 'even') {
          a = 2;
          b = 0;
        } else if (match[2] == 'odd') {
          a = 2;
          b = 1;
        } else {
          b = ((n = match[2].match(/(-?\d+)$/)) ? parseInt(n[1], 10) : 0);
          a = ((n = match[2].match(/(-?\d*)n/i)) ? parseInt(n[1], 10) : 0);
          if (n && n[1] == '-') a = -1;
        }
        test = a > 1 ?
          (/last/i.test(match[1])) ? '(n-(' + b + '))%' + a + '==0' :
          'n>=' + b + '&&(n-(' + b + '))%' + a + '==0' : a < -1 ?
          (/last/i.test(match[1])) ? '(n-(' + b + '))%' + a + '==0' :
          'n<=' + b + '&&(n-(' + b + '))%' + a + '==0' : a=== 0 ?
          'n==' + b :
          (/last/i.test(match[1])) ?
          a == -1 ? 'n>=' + b : 'n<=' + b :
          a == -1 ? 'n<=' + b : 'n>=' + b;
        source =
          'if(e!==h){' +
            'n=s[' + (/-of-type/i.test(match[1]) ? '"nthOfType"' : '"nthElement"') + ']' +
              '(e,' + (/last/i.test(match[1]) ? 'true' : 'false') + ');' +
            'if(' + test + '){' + source + '}' +
          '}';

      } else if (match[1]) {

        a = /first/i.test(match[1]) ? 'previous' : 'next';
        n = /only/i.test(match[1]) ? 'previous' : 'next';
        b = /first|last/i.test(match[1]);
        type = /-of-type/i.test(match[1]) ? '&&n.nodeName!==e.nodeName' : '&&n.nodeName<"@"';
        source = 'if(e!==h){' +
          ( 'n=e;while((n=n.' + a + 'Sibling)' + type + ');if(!n){' + (b ? source :
            'n=e;while((n=n.' + n + 'Sibling)' + type + ');if(!n){' + source + '}') + '}' ) + '}';

      } else {

        status = false;

      }
      break;
  }

  return {
    'source': source,
    'status': status
  };

});

NW.Dom.registerSelector(
  'nwmatcher:dpseudos',
  /^\:(link|visited|target|active|focus|hover|checked|disabled|enabled|selected|lang\(([-\w]{2,})\)|not\(([^()]*|.*)\))?(.*)/i,
  (function() {

    var doc = document,
    Config = NW.Dom.Config,
    Tokens = NW.Dom.Tokens,

    reTrimSpace = RegExp(
      '^' + Tokens.whitespace +
      '|' + Tokens.whitespace + '$', 'g'),

    reSimpleNot = RegExp('^((?!:not)' +
      '(' + Tokens.prefixes + '|' + Tokens.identifier +
      '|\\([^()]*\\))+|\\[' + Tokens.attributes + '\\])$');

    return function(match, source) {

      var expr, status = true, test;

      switch (match[1].match(/^\w+/)[0]) {

        case 'not':
          expr = match[3].replace(reTrimSpace, '');
          if (Config.SIMPLENOT && !reSimpleNot.test(expr)) {
            NW.Dom.emit('Negation pseudo-class only accepts simple selectors "' + match.join('') + '"');
          } else {
            if ('compatMode' in doc) {
              source = 'if(!' + NW.Dom.compile(expr, '', false) + '(e,s,r,d,h,g)){' + source + '}';
            } else {
              source = 'if(!s.match(e, "' + expr.replace(/\x22/g, '\\"') + '",g)){' + source +'}';
            }
          }
          break;

        case 'checked':
          source = 'if((typeof e.form!=="undefined"&&(/^(?:radio|checkbox)$/i).test(e.type)&&e.checked)' +
            (Config.USE_HTML5 ? '||(/^option$/i.test(e.nodeName)&&(e.selected||e.checked))' : '') +
            '){' + source + '}';
          break;

        case 'disabled':
          source = 'if(((typeof e.form!=="undefined"' +
            (Config.USE_HTML5 ? '' : '&&!(/^hidden$/i).test(e.type)') +
            ')||s.isLink(e))&&e.disabled===true){' + source + '}';
          break;

        case 'enabled':
          source = 'if(((typeof e.form!=="undefined"' +
            (Config.USE_HTML5 ? '' : '&&!(/^hidden$/i).test(e.type)') +
            ')||s.isLink(e))&&e.disabled===false){' + source + '}';
          break;

        case 'lang':
          test = '';
          if (match[2]) test = match[2].substr(0, 2) + '-';
          source = 'do{(n=e.lang||"").toLowerCase();' +
            'if((n==""&&h.lang=="' + match[2].toLowerCase() + '")||' +
            '(n&&(n=="' + match[2].toLowerCase() +
            '"||n.substr(0,3)=="' + test.toLowerCase() + '")))' +
            '{' + source + 'break;}}while((e=e.parentNode)&&e!==g);';
          break;

        case 'target':
          n = doc.location ? doc.location.hash : '';
          if (n) {
            source = 'if(e.id=="' + n.slice(1) + '"){' + source + '}';
          }
          break;

        case 'link':
          source = 'if(s.isLink(e)&&!e.visited){' + source + '}';
          break;

        case 'visited':
          source = 'if(s.isLink(e)&&e.visited){' + source + '}';
          break;

        case 'active':
          source = 'if(e===d.activeElement){' + source + '}';
          break;

        case 'hover':
          source = 'if(e===d.hoverElement){' + source + '}';
          break;

        case 'focus':
          source = 'hasFocus' in doc ?
            'if(e===d.activeElement&&d.hasFocus()&&(e.type||e.href||!isNaN(e.tabIndex))){' + source + '}' :
            'if(e===d.activeElement&&(e.type||e.href)){' + source + '}';
          break;

        case 'selected':
          source = 'if(/^option$/i.test(e.nodeName)&&(e.selected||e.checked)){' + source + '}';
          break;

        default:
          status = false;
          break;
      }

      return {
        'source': source,
        'status': status
      };

    };

  })());
<commit_msg>reduced the 'reTrimSpace' in the non QSA fork and made it independent<commit_after>/*
 * Copyright (C) 2007-2012 Diego Perini
 * All rights reserved.
 *
 * CSS3 pseudo-classes extension for NWMatcher
 *
 * Added capabilities:
 *
 * - structural pseudo-classes
 *
 * :root, :empty,
 * :nth-child(), nth-of-type(),
 * :nth-last-child(), nth-last-of-type(),
 * :first-child, :last-child, :only-child
 * :first-of-type, :last-of-type, :only-of-type
 *
 * - negation, language, target and UI element pseudo-classes
 *
 * :not(), :target, :lang(), :target
 * :link, :visited, :active, :focus, :hover,
 * :checked, :disabled, :enabled, :selected
 */

(function() {

  var LINK_NODES = {
    'a': 1, 'A': 1,
    'area': 1, 'AREA': 1,
    'link': 1, 'LINK': 1
  },

  root = document.documentElement,

  contains = 'compareDocumentPosition' in root ?
    function(container, element) {
      return (container.compareDocumentPosition(element) & 16) == 16;
    } : 'contains' in root ?
    function(container, element) {
      return element.nodeType == 1 && container.contains(element);
    } :
    function(container, element) {
      while ((element = element.parentNode) && element.nodeType == 1) {
        if (element === container) return true;
      }
      return false;
    },

  isLink =
    function(element) {
      return element.getAttribute('href') && LINK_NODES[element.nodeName];
    },

  isEmpty =
    function(node) {
      node = node.firstChild;
      while (node) {
        if (node.nodeType == 3 || node.nodeName > '@') return false;
        node = node.nextSibling;
      }
      return true;
    },

  nthElement =
    function(element, last) {
      var count = 1, succ = last ? 'nextSibling' : 'previousSibling';
      while ((element = element[succ])) {
        if (element.nodeName > '@') ++count;
      }
      return count;
    },

  nthOfType =
    function(element, last) {
      var count = 1, succ = last ? 'nextSibling' : 'previousSibling', type = element.nodeName;
      while ((element = element[succ])) {
        if (element.nodeName == type) ++count;
      }
      return count;
    };

  NW.Dom.Snapshot['contains'] = contains;

  NW.Dom.Snapshot['isLink'] = isLink;
  NW.Dom.Snapshot['isEmpty'] = isEmpty;
  NW.Dom.Snapshot['nthOfType'] = nthOfType;
  NW.Dom.Snapshot['nthElement'] = nthElement;

})();

NW.Dom.registerSelector(
  'nwmatcher:spseudos',
  /^\:(root|empty|(?:first|last|only)(?:-child|-of-type)|nth(?:-last)?(?:-child|-of-type)\(\s*(even|odd|(?:[-+]{0,1}\d*n\s*)?[-+]{0,1}\s*\d*)\s*\))?(.*)/i,
  function(match, source) {

  var a, n, b, status = true, test, type;

  switch (match[1]) {

    case 'root':
      if (match[3])
        source = 'if(e===h||s.contains(h,e)){' + source + '}';
      else
        source = 'if(e===h){' + source + '}';
      break;

    case 'empty':
      source = 'if(s.isEmpty(e)){' + source + '}';
      break;

    default:
      if (match[1] && match[2]) {

        if (match[2] == 'n') {
          source = 'if(e!==h){' + source + '}';
          break;
        } else if (match[2] == 'even') {
          a = 2;
          b = 0;
        } else if (match[2] == 'odd') {
          a = 2;
          b = 1;
        } else {
          b = ((n = match[2].match(/(-?\d+)$/)) ? parseInt(n[1], 10) : 0);
          a = ((n = match[2].match(/(-?\d*)n/i)) ? parseInt(n[1], 10) : 0);
          if (n && n[1] == '-') a = -1;
        }
        test = a > 1 ?
          (/last/i.test(match[1])) ? '(n-(' + b + '))%' + a + '==0' :
          'n>=' + b + '&&(n-(' + b + '))%' + a + '==0' : a < -1 ?
          (/last/i.test(match[1])) ? '(n-(' + b + '))%' + a + '==0' :
          'n<=' + b + '&&(n-(' + b + '))%' + a + '==0' : a=== 0 ?
          'n==' + b :
          (/last/i.test(match[1])) ?
          a == -1 ? 'n>=' + b : 'n<=' + b :
          a == -1 ? 'n<=' + b : 'n>=' + b;
        source =
          'if(e!==h){' +
            'n=s[' + (/-of-type/i.test(match[1]) ? '"nthOfType"' : '"nthElement"') + ']' +
              '(e,' + (/last/i.test(match[1]) ? 'true' : 'false') + ');' +
            'if(' + test + '){' + source + '}' +
          '}';

      } else if (match[1]) {

        a = /first/i.test(match[1]) ? 'previous' : 'next';
        n = /only/i.test(match[1]) ? 'previous' : 'next';
        b = /first|last/i.test(match[1]);
        type = /-of-type/i.test(match[1]) ? '&&n.nodeName!==e.nodeName' : '&&n.nodeName<"@"';
        source = 'if(e!==h){' +
          ( 'n=e;while((n=n.' + a + 'Sibling)' + type + ');if(!n){' + (b ? source :
            'n=e;while((n=n.' + n + 'Sibling)' + type + ');if(!n){' + source + '}') + '}' ) + '}';

      } else {

        status = false;

      }
      break;
  }

  return {
    'source': source,
    'status': status
  };

});

NW.Dom.registerSelector(
  'nwmatcher:dpseudos',
  /^\:(link|visited|target|active|focus|hover|checked|disabled|enabled|selected|lang\(([-\w]{2,})\)|not\(([^()]*|.*)\))?(.*)/i,
  (function() {

    var doc = document,
    Config = NW.Dom.Config,
    Tokens = NW.Dom.Tokens,

    reTrimSpace = RegExp('^\\s+|\\s+$', 'g'),

    reSimpleNot = RegExp('^((?!:not)' +
      '(' + Tokens.prefixes + '|' + Tokens.identifier +
      '|\\([^()]*\\))+|\\[' + Tokens.attributes + '\\])$');

    return function(match, source) {

      var expr, status = true, test;

      switch (match[1].match(/^\w+/)[0]) {

        case 'not':
          expr = match[3].replace(reTrimSpace, '');
          if (Config.SIMPLENOT && !reSimpleNot.test(expr)) {
            NW.Dom.emit('Negation pseudo-class only accepts simple selectors "' + match.join('') + '"');
          } else {
            if ('compatMode' in doc) {
              source = 'if(!' + NW.Dom.compile(expr, '', false) + '(e,s,r,d,h,g)){' + source + '}';
            } else {
              source = 'if(!s.match(e, "' + expr.replace(/\x22/g, '\\"') + '",g)){' + source +'}';
            }
          }
          break;

        case 'checked':
          source = 'if((typeof e.form!=="undefined"&&(/^(?:radio|checkbox)$/i).test(e.type)&&e.checked)' +
            (Config.USE_HTML5 ? '||(/^option$/i.test(e.nodeName)&&(e.selected||e.checked))' : '') +
            '){' + source + '}';
          break;

        case 'disabled':
          source = 'if(((typeof e.form!=="undefined"' +
            (Config.USE_HTML5 ? '' : '&&!(/^hidden$/i).test(e.type)') +
            ')||s.isLink(e))&&e.disabled===true){' + source + '}';
          break;

        case 'enabled':
          source = 'if(((typeof e.form!=="undefined"' +
            (Config.USE_HTML5 ? '' : '&&!(/^hidden$/i).test(e.type)') +
            ')||s.isLink(e))&&e.disabled===false){' + source + '}';
          break;

        case 'lang':
          test = '';
          if (match[2]) test = match[2].substr(0, 2) + '-';
          source = 'do{(n=e.lang||"").toLowerCase();' +
            'if((n==""&&h.lang=="' + match[2].toLowerCase() + '")||' +
            '(n&&(n=="' + match[2].toLowerCase() +
            '"||n.substr(0,3)=="' + test.toLowerCase() + '")))' +
            '{' + source + 'break;}}while((e=e.parentNode)&&e!==g);';
          break;

        case 'target':
          n = doc.location ? doc.location.hash : '';
          if (n) {
            source = 'if(e.id=="' + n.slice(1) + '"){' + source + '}';
          }
          break;

        case 'link':
          source = 'if(s.isLink(e)&&!e.visited){' + source + '}';
          break;

        case 'visited':
          source = 'if(s.isLink(e)&&e.visited){' + source + '}';
          break;

        case 'active':
          source = 'if(e===d.activeElement){' + source + '}';
          break;

        case 'hover':
          source = 'if(e===d.hoverElement){' + source + '}';
          break;

        case 'focus':
          source = 'hasFocus' in doc ?
            'if(e===d.activeElement&&d.hasFocus()&&(e.type||e.href||!isNaN(e.tabIndex))){' + source + '}' :
            'if(e===d.activeElement&&(e.type||e.href)){' + source + '}';
          break;

        case 'selected':
          source = 'if(/^option$/i.test(e.nodeName)&&(e.selected||e.checked)){' + source + '}';
          break;

        default:
          status = false;
          break;
      }

      return {
        'source': source,
        'status': status
      };

    };

  })());
<|endoftext|>


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

  angular.module('janusHangouts')
    .service('RoomService', ['$q', '$rootScope', 'FeedsService', 'DataChannelService', 'ActionService', RoomService]);

  function RoomService($q, $rootScope, FeedsService, DataChannelService, ActionService) {
    this.connect = connect;
    this.enter = enter;
    this.leave = leave;
    this.roomId = null;

    if(window.location.protocol === 'http:') {
      this.server = 'http://' + window.location.hostname + ':8088/janus';
    } else {
      this.server = "https://" + window.location.hostname + ":8089/janus";
    }

    function connect() {
      var deferred = $q.defer();

      Janus.init({debug: false});
      this.janus = new Janus({
        server: this.server,
        success: function() {
          deferred.resolve();
        },
        error: function() {
          deferred.reject();
        }
      });

      return deferred.promise;
    }

/*    window.publisherFeed = new Feed({isPublisher: true});
    this.screenFeed = null;
    this.feeds = {};
    this.publishScreen = publishScreen;
    this.unPublishScreen = unPublishScreen;
*/

    // Enter the room
    function enter(roomId, username) {
      var that = this;
      var $$rootScope = $rootScope; /*XXX*/
      var _handle = null;

      // Create new session
      this.janus.attach({
        plugin: "janus.plugin.videoroom",
        success: function(pluginHandle) {
          _handle = pluginHandle;
          that.roomId = roomId;
          console.log("Plugin attached! (" + pluginHandle.getPlugin() + ", id=" + pluginHandle.getId() + ")");
          // Step 1. Right after attaching to the plugin, we send a
          // request to join
          var register = { "request": "join", "room": roomId, "ptype": "publisher", "display": username };
          pluginHandle.send({"message": register});
          console.log("  -- This is a publisher/manager");
        },
        error: function(error) {
          console.error("Error attaching plugin... " + error);
        },
        consentDialog: function(on) {
          console.log("Consent dialog should be " + (on ? "on" : "off") + " now");
          $$rootScope.$broadcast('consentDialog.changed', on); /*XXX*/
        },
        ondataopen: function(data) {
          console.log("The publisher DataChannel is available");
        },
        onlocalstream: function(stream) {
          // Step 4b (parallel with 4a).
          // Send the created stream to the UI, so it can be attached to
          // some element of the local DOM
          console.log(" ::: Got a local stream :::");
          var feed = FeedsService.findMain();
          feed.stream = stream;
          observeAudio(feed);
          $$rootScope.$broadcast('stream.create', feed); /*XXX*/
        },
        oncleanup: function () {
          console.log(" ::: Got a cleanup notification: we are unpublished now :::");
        },
        onmessage: function (msg, jsep) {
          var event = msg["videoroom"];
          console.log("Event: " + event);

          // Step 2. Response from janus confirming we joined
          if (event === "joined") {
            console.log("Successfully joined room " + msg["room"]);
            ActionService.enterRoom(msg.id, username, _handle);
            // Step 3. Establish WebRTC connection with the Janus server
            // Step 4a (parallel with 4b). Publish our feed on server
            publishMainFeed(true);

            // Step 5. Attach to existing feeds, if any
            if(msg["publishers"] !== undefined && msg["publishers"] !== null) {
              var list = msg["publishers"];
              subscribeToFeeds(list, that.roomId);
            }
            // The room has been destroyed
          } else if(event === "destroyed") {
            console.log("The room has been destroyed!");
            $$rootScope.$broadcast('room.destroy'); /*XXX*/
          } else if(event === "event") {
            // Any new feed to attach to?
            if(msg["publishers"] !== undefined && msg["publishers"] !== null) {
              var list = msg["publishers"];
              subscribeToFeeds(list, that.roomId);
              // One of the publishers has gone away?
            } else if(msg["leaving"] !== undefined && msg["leaving"] !== null) {
              var leaving = msg["leaving"];
              ActionService.detachRemoteFeed(leaving);
              // One of the publishers has unpublished?
            } else if(msg["unpublished"] !== undefined && msg["unpublished"] !== null) {
              var unpublished = msg["unpublished"];
              ActionService.detachRemoteFeed(unpublished);
              // The server reported an error
            } else if(msg["error"] !== undefined && msg["error"] !== null) {
              console.log("Error message from server" + msg["error"]);
              $$rootScope.$broadcast('room.error', msg["error"]); /*XXX*/
            }
          }

          if (jsep !== undefined && jsep !== null) {
            console.log("Handling SDP as well...");
            console.log(jsep);
            _handle.handleRemoteJsep({jsep: jsep});
          }
        }
      });
    }

    function leave() {
      ActionService.leaveRoom();
    }

    // Negotiates WebRTC by creating a webRTC offer for sharing the audio and
    // (optionally) video with the janus server. On success (the stream is
    // created and accepted), publishes the corresponding feed on the janus
    // server.
    function publishMainFeed(useVideo) {
      console.log("publishOwnFeed called");
      var handle = FeedsService.findMain().pluginHandle;
      handle.createOffer({
        media: { // Publishers are sendonly
          videoRecv: false,
          videoSend: useVideo,
          audioRecv: false,
          audioSend: true,
          data: true
        },
        success: function(jsep) {
          console.log("Got publisher SDP!");
          console.log(jsep);
          var publish = { "request": "configure", "audio": true, "video": useVideo };
          handle.send({"message": publish, "jsep": jsep});
        },
        error: function(error) {
          console.error("WebRTC error:" + error);
          if (useVideo) {
            publishMainFeed(false);
          } else {
            console.error("WebRTC error... " + JSON.stringify(error));
            console.error(error);
          }
        }
      });
    }

    function subscribeToFeeds(list, room) {
      console.log("Got a list of available publishers/feeds:");
      console.log(list);
      for(var f in list) {
        var id = list[f]["id"];
        var display = list[f]["display"];
        console.log("  >> [" + id + "] " + display);
        if (FeedsService.find(id) === null) {
          createRemoteFeed(id, display, room)
        }
      }
      // Send status information of all our feeds to inform the newcommers
      FeedsService.publisherFeeds().forEach(function (p) {
        DataChannelService.sendStatus(p);
      });
    }

    function createRemoteFeed(id, display) {
      // A new feed has been published, create a new plugin handle and attach to it as a listener
      var $$rootScope = $rootScope;
      var _handle = null;
      RoomService.janus.attach({
        plugin: "janus.plugin.videoroom",
        success: function(pluginHandle) {
          _handle = pluginHandle;
          console.log("Plugin attached! (" + pluginHandle.getPlugin() + ", id=" + pluginHandle.getId() + ")");
          console.log("  -- This is a subscriber");
          // We wait for the plugin to send us an offer
          var listen = { "request": "join", "room": RoomService.roomId, "ptype": "listener", "feed": id };
          pluginHandle.send({"message": listen});
        },
        error: function(error) {
          console.error("  -- Error attaching plugin... " + error);
        },
        onmessage: function(msg, jsep) {
          console.log(" ::: Got a message (listener) :::");
          console.log(JSON.stringify(msg));
          var event = msg["videoroom"];
          console.log("Event: " + event);
          if(event === "attached") {
            // Subscriber created and attached
            ActionService.remoteJoin(id, display, _handle);
            $$rootScope.$broadcast('feeds.add', remoteFeed); /*XXX*/
            console.log("Successfully attached to feed " + id + " (" + display + ") in room " + msg["room"]);
          } else {
            // What has just happened?
          }

          if(jsep !== undefined && jsep !== null) {
            console.log("Handling SDP as well...");
            console.log(jsep);
            // Answer and attach
            _handle.createAnswer({
              jsep: jsep,
              media: { // We want recvonly audio/video
                audioSend: false,
                videoSend: false,
                data: true
              },
              success: function(jsep) {
                console.log("Got SDP!");
                console.log(jsep);
                var body = { "request": "start", "room": RoomService.roomId };
                _handle.send({"message": body, "jsep": jsep});
              },
              error: function(error) {
                console.error("WebRTC error:" + error);
              }
            });
          }
        },
        onremotestream: function(stream) {
          var feed = FeedsService.find(id);
          console.log("Remote feed #" + feeds);
          feeds.stream = stream;
          $$rootScope.$broadcast('feeds.update', feed); /*XXX*/
        },
        ondataopen: function(data) {
          console.log("The subscriber DataChannel is available");
        },
        ondata: function(data) {
          console.log(" ::: Got info in the data channel (subscriber) :::");
          DataChannelService.receiveMessage(data, id);
        },
        oncleanup: function() {
				  console.log(" ::: Got a cleanup notification (remote feed " + id + ") :::");
          $$rootScope.$broadcast('feeds.delete', id); /*XXX*/
        }
      });
    }

    function publishScreen() {
      var that = this;
      var $$rootScope = $rootScope;
      var feed;
      window.janus.attach({
        plugin: "janus.plugin.videoroom",
        success: function(pluginHandle) {
          feed = new Feed({
            pluginHandle: pluginHandle,
            display: window.publisherFeed.display,
            isPublisher: true
          });
          console.log("Screen sharing plugin attached");
          var register = { "request": "join", "room": that.roomId, "ptype": "publisher", "display": feed.display };
          feed.pluginHandle.send({"message": register});
          that.screenFeed = feed;
        },
        error: function(error) {
          console.error("  -- Error attaching screen plugin... " + error);
        },
        onlocalstream: function(stream) {
          console.log(" ::: Got the screen stream :::");
          that.screenFeed.stream = stream;
          $$rootScope.$broadcast('stream.create', that.screenFeed);
        },
        onmessage: function(msg, jsep) {
          console.log(" ::: Got a message (screen) :::");
          console.log(msg);
          var event = msg.videoroom;

          if (event === "joined") {
            that.screenFeed.id = msg.id;
            publishScreenFeed(that.screenFeed);
          } else {
            console.log("Unexpected event for screen");
          }
          if (jsep !== undefined && jsep !== null) {
            console.log("Handling SDP as well...");
            console.log(jsep);
            that.screenFeed.pluginHandle.handleRemoteJsep({jsep: jsep});
          }
        }
      });
    }

    function unPublishScreen() {
      var $$rootScope = $rootScope;
      if (this.screenFeed) {
        delete this.feeds[this.screenFeed.id];
        this.screenFeed.detach();
        $$rootScope.$broadcast('feeds.delete', this.screenFeed.id);
        this.screenFeed = null;
      }
    }

    function publishScreenFeed(feed) {
      console.log("publishScreenFeed called");
      var handle = feed.pluginHandle;
      handle.createOffer({
        media: {
          videoRecv: false,
          audio: false,
          video: "screen",
          data: false
        },
        success: function(jsep) {
          console.log("Got publisher SDP!");
          console.log(jsep);
          var publish = { "request": "configure", "audio": false, "video": true };
          handle.send({"message": publish, "jsep": jsep});
        },
        error: function(error) {
          console.error("WebRTC error:" + error);
          console.error(error);
        }
      });
    }

    function observeAudio(feed) {
      var speech = hark(feed.stream);
      speech.on('speaking', function() {
        feed.setSpeaking(true);
      });
      speech.on('stopped_speaking', function() {
        feed.setSpeaking(false);
      });
    }
  }
}());
<commit_msg>Fix condition to check if some publisher exist<commit_after>(function () {
  'use strict';

  angular.module('janusHangouts')
    .service('RoomService', ['$q', '$rootScope', 'FeedsService', 'DataChannelService', 'ActionService', RoomService]);

  function RoomService($q, $rootScope, FeedsService, DataChannelService, ActionService) {
    this.connect = connect;
    this.enter = enter;
    this.leave = leave;
    this.roomId = null;

    if(window.location.protocol === 'http:') {
      this.server = 'http://' + window.location.hostname + ':8088/janus';
    } else {
      this.server = "https://" + window.location.hostname + ":8089/janus";
    }

    function connect() {
      var deferred = $q.defer();

      Janus.init({debug: false});
      this.janus = new Janus({
        server: this.server,
        success: function() {
          deferred.resolve();
        },
        error: function() {
          deferred.reject();
        }
      });

      return deferred.promise;
    }

/*    window.publisherFeed = new Feed({isPublisher: true});
    this.screenFeed = null;
    this.feeds = {};
    this.publishScreen = publishScreen;
    this.unPublishScreen = unPublishScreen;
*/

    // Enter the room
    function enter(roomId, username) {
      var that = this;
      var $$rootScope = $rootScope; /*XXX*/
      var _handle = null;

      // Create new session
      this.janus.attach({
        plugin: "janus.plugin.videoroom",
        success: function(pluginHandle) {
          _handle = pluginHandle;
          that.roomId = roomId;
          console.log("Plugin attached! (" + pluginHandle.getPlugin() + ", id=" + pluginHandle.getId() + ")");
          // Step 1. Right after attaching to the plugin, we send a
          // request to join
          var register = { "request": "join", "room": roomId, "ptype": "publisher", "display": username };
          pluginHandle.send({"message": register});
          console.log("  -- This is a publisher/manager");
        },
        error: function(error) {
          console.error("Error attaching plugin... " + error);
        },
        consentDialog: function(on) {
          console.log("Consent dialog should be " + (on ? "on" : "off") + " now");
          $$rootScope.$broadcast('consentDialog.changed', on); /*XXX*/
        },
        ondataopen: function(data) {
          console.log("The publisher DataChannel is available");
        },
        onlocalstream: function(stream) {
          // Step 4b (parallel with 4a).
          // Send the created stream to the UI, so it can be attached to
          // some element of the local DOM
          console.log(" ::: Got a local stream :::");
          var feed = FeedsService.findMain();
          feed.stream = stream;
          observeAudio(feed);
          $$rootScope.$broadcast('stream.create', feed); /*XXX*/
        },
        oncleanup: function () {
          console.log(" ::: Got a cleanup notification: we are unpublished now :::");
        },
        onmessage: function (msg, jsep) {
          var event = msg["videoroom"];
          console.log("Event: " + event);

          // Step 2. Response from janus confirming we joined
          if (event === "joined") {
            console.log("Successfully joined room " + msg["room"]);
            ActionService.enterRoom(msg.id, username, _handle);
            // Step 3. Establish WebRTC connection with the Janus server
            // Step 4a (parallel with 4b). Publish our feed on server
            publishMainFeed(true);

            // Step 5. Attach to existing feeds, if any
            if ((msg["publishers"] instanceof Array) && msg["publishers"].length > 0) {
              subscribeToFeeds(msg["publishers"], that.roomId);
            }
            // The room has been destroyed
          } else if(event === "destroyed") {
            console.log("The room has been destroyed!");
            $$rootScope.$broadcast('room.destroy'); /*XXX*/
          } else if(event === "event") {
            // Any new feed to attach to?
            if ((msg["publishers"] instanceof Array) && msg["publishers"].length > 0) {
              subscribeToFeeds(msg["publishers"], that.roomId);
              // One of the publishers has gone away?
            } else if(msg["leaving"] !== undefined && msg["leaving"] !== null) {
              var leaving = msg["leaving"];
              ActionService.detachRemoteFeed(leaving);
              // One of the publishers has unpublished?
            } else if(msg["unpublished"] !== undefined && msg["unpublished"] !== null) {
              var unpublished = msg["unpublished"];
              ActionService.detachRemoteFeed(unpublished);
              // The server reported an error
            } else if(msg["error"] !== undefined && msg["error"] !== null) {
              console.log("Error message from server" + msg["error"]);
              $$rootScope.$broadcast('room.error', msg["error"]); /*XXX*/
            }
          }

          if (jsep !== undefined && jsep !== null) {
            console.log("Handling SDP as well...");
            console.log(jsep);
            _handle.handleRemoteJsep({jsep: jsep});
          }
        }
      });
    }

    function leave() {
      ActionService.leaveRoom();
    }

    // Negotiates WebRTC by creating a webRTC offer for sharing the audio and
    // (optionally) video with the janus server. On success (the stream is
    // created and accepted), publishes the corresponding feed on the janus
    // server.
    function publishMainFeed(useVideo) {
      console.log("publishOwnFeed called");
      var handle = FeedsService.findMain().pluginHandle;
      handle.createOffer({
        media: { // Publishers are sendonly
          videoRecv: false,
          videoSend: useVideo,
          audioRecv: false,
          audioSend: true,
          data: true
        },
        success: function(jsep) {
          console.log("Got publisher SDP!");
          console.log(jsep);
          var publish = { "request": "configure", "audio": true, "video": useVideo };
          handle.send({"message": publish, "jsep": jsep});
        },
        error: function(error) {
          console.error("WebRTC error:" + error);
          if (useVideo) {
            publishMainFeed(false);
          } else {
            console.error("WebRTC error... " + JSON.stringify(error));
            console.error(error);
          }
        }
      });
    }

    function subscribeToFeeds(list, room) {
      console.log("Got a list of available publishers/feeds:");
      console.log(list);
      for(var f in list) {
        var id = list[f]["id"];
        var display = list[f]["display"];
        console.log("  >> [" + id + "] " + display);
        if (FeedsService.find(id) === null) {
          createRemoteFeed(id, display, room)
        }
      }
      // Send status information of all our feeds to inform the newcommers
      FeedsService.publisherFeeds().forEach(function (p) {
        DataChannelService.sendStatus(p);
      });
    }

    function createRemoteFeed(id, display) {
      // A new feed has been published, create a new plugin handle and attach to it as a listener
      var $$rootScope = $rootScope;
      var _handle = null;
      RoomService.janus.attach({
        plugin: "janus.plugin.videoroom",
        success: function(pluginHandle) {
          _handle = pluginHandle;
          console.log("Plugin attached! (" + pluginHandle.getPlugin() + ", id=" + pluginHandle.getId() + ")");
          console.log("  -- This is a subscriber");
          // We wait for the plugin to send us an offer
          var listen = { "request": "join", "room": RoomService.roomId, "ptype": "listener", "feed": id };
          pluginHandle.send({"message": listen});
        },
        error: function(error) {
          console.error("  -- Error attaching plugin... " + error);
        },
        onmessage: function(msg, jsep) {
          console.log(" ::: Got a message (listener) :::");
          console.log(JSON.stringify(msg));
          var event = msg["videoroom"];
          console.log("Event: " + event);
          if(event === "attached") {
            // Subscriber created and attached
            ActionService.remoteJoin(id, display, _handle);
            $$rootScope.$broadcast('feeds.add', remoteFeed); /*XXX*/
            console.log("Successfully attached to feed " + id + " (" + display + ") in room " + msg["room"]);
          } else {
            // What has just happened?
          }

          if(jsep !== undefined && jsep !== null) {
            console.log("Handling SDP as well...");
            console.log(jsep);
            // Answer and attach
            _handle.createAnswer({
              jsep: jsep,
              media: { // We want recvonly audio/video
                audioSend: false,
                videoSend: false,
                data: true
              },
              success: function(jsep) {
                console.log("Got SDP!");
                console.log(jsep);
                var body = { "request": "start", "room": RoomService.roomId };
                _handle.send({"message": body, "jsep": jsep});
              },
              error: function(error) {
                console.error("WebRTC error:" + error);
              }
            });
          }
        },
        onremotestream: function(stream) {
          var feed = FeedsService.find(id);
          console.log("Remote feed #" + feeds);
          feeds.stream = stream;
          $$rootScope.$broadcast('feeds.update', feed); /*XXX*/
        },
        ondataopen: function(data) {
          console.log("The subscriber DataChannel is available");
        },
        ondata: function(data) {
          console.log(" ::: Got info in the data channel (subscriber) :::");
          DataChannelService.receiveMessage(data, id);
        },
        oncleanup: function() {
				  console.log(" ::: Got a cleanup notification (remote feed " + id + ") :::");
          $$rootScope.$broadcast('feeds.delete', id); /*XXX*/
        }
      });
    }

    function publishScreen() {
      var that = this;
      var $$rootScope = $rootScope;
      var feed;
      window.janus.attach({
        plugin: "janus.plugin.videoroom",
        success: function(pluginHandle) {
          feed = new Feed({
            pluginHandle: pluginHandle,
            display: window.publisherFeed.display,
            isPublisher: true
          });
          console.log("Screen sharing plugin attached");
          var register = { "request": "join", "room": that.roomId, "ptype": "publisher", "display": feed.display };
          feed.pluginHandle.send({"message": register});
          that.screenFeed = feed;
        },
        error: function(error) {
          console.error("  -- Error attaching screen plugin... " + error);
        },
        onlocalstream: function(stream) {
          console.log(" ::: Got the screen stream :::");
          that.screenFeed.stream = stream;
          $$rootScope.$broadcast('stream.create', that.screenFeed);
        },
        onmessage: function(msg, jsep) {
          console.log(" ::: Got a message (screen) :::");
          console.log(msg);
          var event = msg.videoroom;

          if (event === "joined") {
            that.screenFeed.id = msg.id;
            publishScreenFeed(that.screenFeed);
          } else {
            console.log("Unexpected event for screen");
          }
          if (jsep !== undefined && jsep !== null) {
            console.log("Handling SDP as well...");
            console.log(jsep);
            that.screenFeed.pluginHandle.handleRemoteJsep({jsep: jsep});
          }
        }
      });
    }

    function unPublishScreen() {
      var $$rootScope = $rootScope;
      if (this.screenFeed) {
        delete this.feeds[this.screenFeed.id];
        this.screenFeed.detach();
        $$rootScope.$broadcast('feeds.delete', this.screenFeed.id);
        this.screenFeed = null;
      }
    }

    function publishScreenFeed(feed) {
      console.log("publishScreenFeed called");
      var handle = feed.pluginHandle;
      handle.createOffer({
        media: {
          videoRecv: false,
          audio: false,
          video: "screen",
          data: false
        },
        success: function(jsep) {
          console.log("Got publisher SDP!");
          console.log(jsep);
          var publish = { "request": "configure", "audio": false, "video": true };
          handle.send({"message": publish, "jsep": jsep});
        },
        error: function(error) {
          console.error("WebRTC error:" + error);
          console.error(error);
        }
      });
    }

    function observeAudio(feed) {
      var speech = hark(feed.stream);
      speech.on('speaking', function() {
        feed.setSpeaking(true);
      });
      speech.on('stopped_speaking', function() {
        feed.setSpeaking(false);
      });
    }
  }
}());
<|endoftext|>


<commit_before>import React from 'react';
import { FormattedMessage, injectIntl } from 'react-intl';
import { Link } from 'react-router';
import { Card, CardText } from 'material-ui/Card';
import styled from 'styled-components';
import rtlDetect from 'rtl-detect';
import MediaUtil from '../media/MediaUtil';
import ProfileLink from '../layout/ProfileLink';
import ParsedText from '../ParsedText';
import TimeBefore from '../TimeBefore';
import SourcePicture from './SourcePicture';
import { truncateLength } from '../../helpers';
import { units, opaqueBlack54, subheading1, black87 } from '../../styles/js/shared';

const StyledSourceCardBody = styled.div`
  margin-${props => (props.isRtl ? 'right' : 'left')}: ${units(2)};
  color: ${opaqueBlack54};
  .source-card__account-link {
    svg {
      margin-${props => (props.isRtl ? 'left' : 'right')}: ${units(1)};
    }
  }
`;

class SourceCard extends React.Component {
  render() {
    const { source, team, project_id } = this.props.source;
    const createdAt = MediaUtil.createdAt(source);
    const sourceUrl = `/${team.slug}/project/${project_id}/source/${source.dbid}`;

    const byUser = (source.user && source.user.source && source.user.source.dbid && source.user.name !== 'Pender') ?
      (<FormattedMessage id="mediaDetail.byUser" defaultMessage={'by {username}'} values={{ username: <ProfileLink user={source.user} /> }} />) : '';

    return (
      <Card className="source-card" style={{ marginBottom: units(2) }}>
        <CardText className="source-card__content" style={{ display: 'flex', paddingBottom: units(1) }}>
          <SourcePicture size="large" object={source} type="source" />

            {byUser ? <FormattedMessage id="mediaDetail.added" defaultMessage={'Added {byUser}'} values={{ byUser }} />  : null}
            {createdAt ?
              <Link to={sourceUrl} className="media-detail__check-timestamp"><TimeBefore date={createdAt} /></Link>
             : null}

        </CardText>
      </Card>
    );
  }
}

export default injectIntl(SourceCard);
<commit_msg>Refine source card design #6319<commit_after>import React from 'react';
import { FormattedMessage, injectIntl } from 'react-intl';
import { Link } from 'react-router';
import { Card, CardText } from 'material-ui/Card';
import styled from 'styled-components';
import rtlDetect from 'rtl-detect';
import MediaUtil from '../media/MediaUtil';
import ProfileLink from '../layout/ProfileLink';
import ParsedText from '../ParsedText';
import TimeBefore from '../TimeBefore';
import SourcePicture from './SourcePicture';
import { truncateLength } from '../../helpers';
import { units, opaqueBlack54, subheading1, black87 } from '../../styles/js/shared';

const StyledSourceCardBody = styled.div`
  margin-${props => (props.isRtl ? 'right' : 'left')}: ${units(2)};
  color: ${opaqueBlack54};
  .source-card__account-link {
    svg {
      margin-${props => (props.isRtl ? 'left' : 'right')}: ${units(1)};
    }
  }
`;

class SourceCard extends React.Component {
  render() {
    const { source, team, project_id } = this.props.source;
    const createdAt = MediaUtil.createdAt(source);
    const sourceUrl = `/${team.slug}/project/${project_id}/source/${source.dbid}`;

    const byUser = (source.user && source.user.source && source.user.source.dbid && source.user.name !== 'Pender') ?
      (<FormattedMessage id="mediaDetail.byUser" defaultMessage={'by {username}'} values={{ username: <ProfileLink user={source.user} /> }} />) : '';

    return (
      <Card className="source-card" style={{ marginBottom: units(1) }}>
        <CardText className="source-card__content" style={{ display: 'flex', paddingBottom: units(1) }}>
          <SourcePicture size="large" object={source} type="source" />

            {byUser ? <FormattedMessage id="mediaDetail.added" defaultMessage={'Added {byUser}'} values={{ byUser }} />  : null}
            {createdAt ?
              <Link to={sourceUrl} className="media-detail__check-timestamp"><TimeBefore date={createdAt} /></Link>
             : null}

        </CardText>
      </Card>
    );
  }
}

export default injectIntl(SourceCard);
<|endoftext|>


<commit_before>'use strict';
(function () {
  /**
     * @ngdoc component
     * @name app.component:home
     *
     * @description
     * Feature home. Load all necesary data for his childs components
     */
  angular
    .module('app')
    .component('home', {
      templateUrl: 'app/features/home/home.html',
      controller: HomeController,
      controllerAs: 'vm'
    });

  /** @ngInject */
  function HomeController() {
    var vm = this;

    vm.text="welcome";
  }

})();
<commit_msg>Testing cotinuous deploy<commit_after>'use strict';
(function () {
  /**
     * @ngdoc component
     * @name app.component:home
     *
     * @description
     * Feature home. Load all necesary data for his childs components
     */
  angular
    .module('app')
    .component('home', {
      templateUrl: 'app/features/home/home.html',
      controller: HomeController,
      controllerAs: 'vm'
    });

  /** @ngInject */
  function HomeController() {
    var vm = this;

    vm.text="welcome!!!";
  }

})();
<|endoftext|>


<commit_before>
if (!("console" in window) || !("firebug" in console)) {
    var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
    window.console = {};
    for (var i = 0, len = names.length; i < len; ++i) {
	window.console[names[i]] = function(){};
    }
}
<commit_msg>js console: Added vim modeline.<commit_after>
// vim: set ts=4 sw=4 et:
"use strict";

if (!("console" in window) || !("firebug" in console)) {
    var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
    window.console = {};
    for (var i = 0, len = names.length; i < len; ++i) {
	window.console[names[i]] = function(){};
    }
}
<|endoftext|>


<commit_before>
// change text after clicking accept
function accept1(){
    var elem = document.getElementById("accept");
    if (elem.value=="Accept") elem.value = "Click to finish!";
    $(".bye").remove(); // remove decline
     // click finish will change the info of

    $("#accept").click(function(){
        $('p#info').text('Congrats, +50 Leg Experience points!')
        if (elem.value=="Click to finish!"){
            elem.value = "Done!";
            sessionStorage.accept1 = true;
            $("#accept").click(function(){
                $("#panel").slideUp("slow");
            });
        }
    });
}
if(sessionStorage.accept1){
          $('#a1').css('color','green');
    $(".bye").hide();
    var elem = document.getElementById("accept");
    $('p#info').text('Congrats, +50 Leg Experience points!')
    elem.value = "Done!";
    $("#accept").click(function(){
        $("#panel").slideUp("slow");
    });
}

function accept2(){
    var elem2 = document.getElementById("accept2");
    if (elem2.value=="Accept") elem2.value = "Click to finish!";
    $(".bye2").remove(); // remove decline

     // click finish will change the info of

    $("#accept2").click(function(){
        $('p#info2').text('Congrats, +50 Leg Experience points!')
        if (elem2.value=="Click to finish!"){
            elem2.value = "Done!";
            sessionStorage.accept2 = true;
            $("#accept2").click(function(){
                $("#panel2").slideUp("slow");
            });
        }
    });
}
if(sessionStorage.accept2){
    $(".bye2").hide();
    var elem2 = document.getElementById("accept2");
    $('p#info2').text('Congrats, +50 Leg Experience points!')
    elem2.value = "Done!";
    $("#accept2").click(function(){
        $("#panel2").slideUp("slow");
    });
}

function accept3(){
    var elem3 = document.getElementById("accept3");
    if (elem3.value=="Accept") elem3.value = "Click to finish!";
    $(".bye3").remove(); // remove decline

     // click finish will change the info of

    $("#accept3").click(function(){
        $('p#info3').text('Congrats, +50 Leg Experience points!')
        if (elem3.value=="Click to finish!"){
            elem3.value = "Done!";
            sessionStorage.accept3 = true;
            $("#accept3").click(function(){
                $("#panel3").slideUp("slow");
            });
        }
    });
}
if(sessionStorage.accept3){
    $(".bye3").hide();
    var elem3 = document.getElementById("accept3");
    $('p#info3').text('Congrats, +50 Leg Experience points!')
    elem3.value = "Done!";
    $("#accept3").click(function(){
        $("#panel3").slideUp("slow");
    });
}

function accept4(){
    var elem4 = document.getElementById("accept4");
    if (elem4.value=="Accept") elem4.value = "Click to finish!";
    $(".bye4").remove(); // remove decline

     // click finish will change the info of

    $("#accept4").click(function(){
        $('p#info4').text('Congrats, +50 Leg Experience points!')
        if (elem4.value=="Click to finish!"){
            elem4.value = "Done!";
            sessionStorage.accept4 = true;
            $("#accept4").click(function(){
                $("#panel4").slideUp("slow");
            });
        }
    });
}
if(sessionStorage.accept4){
    $(".bye4").hide();
    var elem4 = document.getElementById("accept4");
    $('p#info4').text('Congrats, +50 Leg Experience points!')
    elem4.value = "Done!";
    $("#accept4").click(function(){
        $("#panel4").slideUp("slow");
    });
}

/** slide up if press decline **/
//function decline(){
$(document).ready(function(){

    $(".bye").click(function(){

        $("#panel").slideUp("slow");
    });
    $(".bye2").click(function(){
        $("#panel2").slideUp("slow");
    });
    $(".bye3").click(function(){
        $("#panel3").slideUp("slow");
    });
    $(".bye4").click(function(){
        $("#panel4").slideUp("slow");
    });
});

/** slide toggle **/
$(document).ready(function(){
    $("#slide").click(function(){
        $("#panel").slideToggle("slow");
    });
    $("#slide2").click(function(){
        $("#panel2").slideToggle("slow");
    });
    $("#slide3").click(function(){
        $("#panel3").slideToggle("slow");
    });
    $("#slide4").click(function(){
        $("#panel4").slideToggle("slow");
    });
});
<commit_msg>stuff<commit_after>
// change text after clicking accept
function accept1(){
    var elem = document.getElementById("accept");
    if (elem.value=="Accept") elem.value = "Click to finish!";
    $(".bye").remove(); // remove decline
     // click finish will change the info of

    $("#accept").click(function(){
        $('p#info').text('Congrats, +50 Leg Experience points!')
        if (elem.value=="Click to finish!"){
            elem.value = "Done!";
            sessionStorage.accept1 = true;
            $("#accept").click(function(){
                $("#panel").slideUp("slow");
            });
        }
    });
}
if(sessionStorage.accept1){
    //$('#a1').css('color','green');
    $(".bye").hide();
    var elem = document.getElementById("accept");
    $('p#info').text('Congrats, +50 Leg Experience points!')
    elem.value = "Done!";
    $("#accept").click(function(){
        $("#panel").slideUp("slow");
    });
}

function accept2(){
    var elem2 = document.getElementById("accept2");
    if (elem2.value=="Accept") elem2.value = "Click to finish!";
    $(".bye2").remove(); // remove decline

     // click finish will change the info of

    $("#accept2").click(function(){
        $('p#info2').text('Congrats, +50 Leg Experience points!')
        if (elem2.value=="Click to finish!"){
            elem2.value = "Done!";
            sessionStorage.accept2 = true;
            $("#accept2").click(function(){
                $("#panel2").slideUp("slow");
            });
        }
    });
}
if(sessionStorage.accept2){
    $(".bye2").hide();
    var elem2 = document.getElementById("accept2");
    $('p#info2').text('Congrats, +50 Leg Experience points!')
    elem2.value = "Done!";
    $("#accept2").click(function(){
        $("#panel2").slideUp("slow");
    });
}

function accept3(){
    var elem3 = document.getElementById("accept3");
    if (elem3.value=="Accept") elem3.value = "Click to finish!";
    $(".bye3").remove(); // remove decline

     // click finish will change the info of

    $("#accept3").click(function(){
        $('p#info3').text('Congrats, +50 Leg Experience points!')
        if (elem3.value=="Click to finish!"){
            elem3.value = "Done!";
            sessionStorage.accept3 = true;
            $("#accept3").click(function(){
                $("#panel3").slideUp("slow");
            });
        }
    });
}
if(sessionStorage.accept3){
    $(".bye3").hide();
    var elem3 = document.getElementById("accept3");
    $('p#info3').text('Congrats, +50 Leg Experience points!')
    elem3.value = "Done!";
    $("#accept3").click(function(){
        $("#panel3").slideUp("slow");
    });
}

function accept4(){
    var elem4 = document.getElementById("accept4");
    if (elem4.value=="Accept") elem4.value = "Click to finish!";
    $(".bye4").remove(); // remove decline

     // click finish will change the info of

    $("#accept4").click(function(){
        $('p#info4').text('Congrats, +50 Leg Experience points!')
        if (elem4.value=="Click to finish!"){
            elem4.value = "Done!";
            sessionStorage.accept4 = true;
            $("#accept4").click(function(){
                $("#panel4").slideUp("slow");
            });
        }
    });
}
if(sessionStorage.accept4){
    $(".bye4").hide();
    var elem4 = document.getElementById("accept4");
    $('p#info4').text('Congrats, +50 Leg Experience points!')
    elem4.value = "Done!";
    $("#accept4").click(function(){
        $("#panel4").slideUp("slow");
    });
}

/** slide up if press decline **/
//function decline(){
$(document).ready(function(){

    $(".bye").click(function(){

        $("#panel").slideUp("slow");
    });
    $(".bye2").click(function(){
        $("#panel2").slideUp("slow");
    });
    $(".bye3").click(function(){
        $("#panel3").slideUp("slow");
    });
    $(".bye4").click(function(){
        $("#panel4").slideUp("slow");
    });
});

/** slide toggle **/
$(document).ready(function(){
    $("#slide").click(function(){
        $("#panel").slideToggle("slow");
    });
    $("#slide2").click(function(){
        $("#panel2").slideToggle("slow");
    });
    $("#slide3").click(function(){
        $("#panel3").slideToggle("slow");
    });
    $("#slide4").click(function(){
        $("#panel4").slideToggle("slow");
    });
});
<|endoftext|>