Source: test/dist/bundle.js

/*! @name videojs-contextmenu @version 2.0.0 @license Apache-2.0 */
(function (videojs,QUnit,sinon) {
	'use strict';

	videojs = videojs && videojs.hasOwnProperty('default') ? videojs['default'] : videojs;
	QUnit = QUnit && QUnit.hasOwnProperty('default') ? QUnit['default'] : QUnit;
	sinon = sinon && sinon.hasOwnProperty('default') ? sinon['default'] : sinon;

	var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};

	var empty = {};

	var empty$1 = /*#__PURE__*/Object.freeze({
		default: empty
	});

	var minDoc = ( empty$1 && empty ) || empty$1;

	var topLevel = typeof commonjsGlobal !== 'undefined' ? commonjsGlobal :
	    typeof window !== 'undefined' ? window : {};


	var doccy;

	if (typeof document !== 'undefined') {
	    doccy = document;
	} else {
	    doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'];

	    if (!doccy) {
	        doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc;
	    }
	}

	var document_1 = doccy;

	/**
	 * @module plugin
	 */

	// vjs 5/6 cross compatibility.
	var registerPlugin = videojs.registerPlugin || videojs.plugin;

	/* eslint func-style: 0 */

	var defaults = {
	  cancel: true,
	  sensitivity: 10,
	  wait: 500,
	  disabled: false
	};

	var EVENT_NAME = 'vjs-contextmenu';

	/**
	 * Abstracts a DOM standard event into a vjs-contextmenu event.
	 *
	 * @private
	 * @param  {Player} player
	 * @param  {Event} event
	 *         A triggering, native event.
	 * @return {Player}
	 */
	function sendAbstractedEvent(player, event) {
	  if (player.contextmenu.options.disabled) {
	    // videojs-contextmenu is disabled
	    return player;
	  }
	  var abstracted = {
	    target: player,
	    type: EVENT_NAME
	  };

	  ['clientX', 'clientY', 'pageX', 'pageY', 'screenX', 'screenY'].forEach(function (k) {
	    abstracted[k] = event[k];
	  });

	  return player.trigger(abstracted);
	}

	/**
	 * Handles both touchcancel and touchend events.
	 *
	 * @private
	 * @param  {Event} e
	 */
	function handleTouchEnd(e) {
	  var current = this.contextmenu.current;

	  if (!current) {
	    return;
	  }

	  var wait = this.contextmenu.options.wait;

	  if (e.type === 'touchend' && Number(new Date()) - current.time >= wait) {
	    sendAbstractedEvent(this, e);
	  }

	  this.contextmenu.current = null;
	}

	/**
	 * Handles touchmove events.
	 *
	 * @private
	 * @param  {Event} e
	 */
	function handleTouchMove(e) {
	  var current = this.contextmenu.current;

	  if (!current) {
	    return;
	  }

	  var touch = e.touches[0];
	  var sensitivity = this.contextmenu.options.sensitivity;

	  // Cancel the current touch if the pointer has moved in either direction
	  // more than the sensitivity number of pixels.
	  if (touch.screenX - current.screenX > sensitivity || touch.screenY - current.screenY > sensitivity) {
	    this.contextmenu.current = null;
	  }
	}

	/**
	 * Handles touchstart events.
	 *
	 * @private
	 * @param  {Event} e
	 */
	function handleTouchStart(e) {

	  // We only care about the first touch point.
	  if (this.contextmenu.current) {
	    return;
	  }

	  var touch = e.touches[0];

	  this.contextmenu.current = {
	    screenX: touch.screenX,
	    screenY: touch.screenY,
	    time: Number(new Date())
	  };
	}

	/**
	 * Handles contextmenu events.
	 *
	 * @private
	 * @param  {Event} e
	 */
	function handleContextMenu(e) {
	  if (this.contextmenu.options.cancel && !this.contextmenu.options.disabled) {
	    e.preventDefault();
	  }

	  sendAbstractedEvent(this, e);

	  // If we get a "contextmenu" event, we can rely on that going forward
	  // because this client supports it; so, we can stop listening for
	  // touch events.
	  this.off(['touchcancel', 'touchend'], handleTouchEnd);
	  this.off('touchmove', handleTouchMove);
	  this.off('touchstart', handleTouchStart);
	}

	/**
	 * A cross-device context menu implementation for video.js players.
	 *
	 * @param    {Object}  [options={}]
	 * @param    {Boolean} [cancel=true]
	 *           Whether or not to cancel the native "contextmenu" event when
	 *           it is seen.
	 *
	 * @param    {Number} [sensitivity=10]
	 *           The maximum number of pixels a finger can move because a touch
	 *           is no longer considered to be "held".
	 *
	 * @param    {Number} [wait=500]
	 *           The minimum number of milliseconds a touch must be "held" before
	 *           it registers.
	 */
	function contextmenu(options) {
	  var _this = this;

	  this.contextmenu.options = videojs.mergeOptions(defaults, options);
	  this.contextmenu.VERSION = '__VERSION__';

	  this.on('contextmenu', handleContextMenu);
	  this.on(['touchcancel', 'touchend'], handleTouchEnd);
	  this.on('touchmove', handleTouchMove);
	  this.on('touchstart', handleTouchStart);

	  this.ready(function () {
	    return _this.addClass(EVENT_NAME);
	  });
	}

	registerPlugin('contextmenu', contextmenu);
	contextmenu.VERSION = '__VERSION__';

	var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
	  return typeof obj;
	} : function (obj) {
	  return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
	};

	var Player = videojs.getComponent('Player');

	QUnit.test('the environment is sane', function (assert) {
	  assert.strictEqual(_typeof(Array.isArray), 'function', 'es5 exists');
	  assert.strictEqual(typeof sinon === 'undefined' ? 'undefined' : _typeof(sinon), 'object', 'sinon exists');
	  assert.strictEqual(typeof videojs === 'undefined' ? 'undefined' : _typeof(videojs), 'function', 'videojs exists');
	  assert.strictEqual(typeof contextmenu === 'undefined' ? 'undefined' : _typeof(contextmenu), 'function', 'plugin is a function');
	});

	QUnit.module('videojs-contextmenu', {
	  beforeEach: function beforeEach() {

	    // Mock the environment's timers because certain things - particularly
	    // player readiness - are asynchronous in video.js 5. This MUST come
	    // before any player is created; otherwise, timers could get created
	    // with the actual timer methods!
	    this.clock = sinon.useFakeTimers();

	    this.fixture = document_1.getElementById('qunit-fixture');
	    this.video = document_1.createElement('video');
	    this.fixture.appendChild(this.video);
	    this.player = videojs(this.video);
	    this.player.contextmenu();
	    this.spy = sinon.spy();
	    this.player.on('vjs-contextmenu', this.spy);

	    // Tick the clock forward enough to trigger the player to be "ready".
	    this.clock.tick(1);
	  },
	  afterEach: function afterEach() {
	    this.player.dispose();
	    this.clock.restore();
	  }
	});

	QUnit.test('registers itself with video.js', function (assert) {
	  assert.strictEqual(_typeof(Player.prototype.contextmenu), 'function', 'videojs-contextmenu plugin was registered');

	  assert.ok(this.player.hasClass('vjs-contextmenu'), 'the plugin adds a class to the player');
	});

	QUnit.test('sends a "vjs-contextmenu" event when a native "contextmenu" event occurs', function (assert) {
	  assert.notOk(this.spy.called, '"vjs-contextmenu" has not been triggered yet');
	  this.player.trigger('contextmenu');
	  assert.ok(this.spy.calledOnce, '"contextmenu" triggered a "vjs-contextmenu"');
	});

	QUnit.test('sends a "vjs-contextmenu" on long touch', function (assert) {
	  this.player.trigger({
	    type: 'touchstart',
	    touches: [{
	      screenX: 1,
	      screenY: 1
	    }]
	  });

	  this.clock.tick(1000);
	  assert.notOk(this.spy.called, '"vjs-contextmenu" was not triggered between "touchstart" and "touchend"');
	  this.player.trigger({ type: 'touchend' });
	  assert.ok(this.spy.calledOnce, '"vjs-contextmenu" was triggered once a "touchend" triggered');
	});

	QUnit.test('stops listening for touches if it encounters a native "contextmenu" event', function (assert) {
	  assert.notOk(this.spy.called, '"vjs-contextmenu" has not been triggered yet');
	  this.player.trigger('contextmenu');
	  assert.ok(this.spy.calledOnce, '"contextmenu" triggered a "vjs-contextmenu"');

	  this.player.trigger({
	    type: 'touchstart',
	    touches: [{
	      screenX: 1,
	      screenY: 1
	    }]
	  });

	  this.clock.tick(1000);

	  this.player.trigger({
	    type: 'touchend'
	  });

	  assert.ok(this.spy.calledOnce, 'touches did not trigger a second "vjs-contextmenu"');
	  this.player.trigger('contextmenu');
	  assert.ok(this.spy.calledTwice, '"contextmenu" triggered a second "vjs-contextmenu"');
	});

	QUnit.test('will not fire "vjs-contextmenu" if the touch point has moved beyond the sensitivity range in either direction', function (assert) {
	  this.player.trigger({
	    type: 'touchstart',
	    touches: [{
	      screenX: 1,
	      screenY: 1
	    }]
	  });

	  this.player.trigger({
	    type: 'touchmove',
	    touches: [{
	      screenX: 12,
	      screenY: 1
	    }]
	  });

	  this.clock.tick(1000);

	  this.player.trigger({
	    type: 'touchend'
	  });

	  assert.notOk(this.spy.called, '"vjs-contextmenu" was not triggered because the touch point moved');

	  this.player.trigger({
	    type: 'touchstart',
	    touches: [{
	      screenX: 1,
	      screenY: 1
	    }]
	  });

	  this.player.trigger({
	    type: 'touchmove',
	    touches: [{
	      screenX: 1,
	      screenY: 12
	    }]
	  });

	  this.clock.tick(1000);

	  this.player.trigger({
	    type: 'touchend'
	  });

	  assert.notOk(this.spy.called, '"vjs-contextmenu" was not triggered because the touch point moved');
	});

}(videojs,QUnit,sinon));