practisemaster 1.0.9 → 1.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,17 @@
1
1
  This is the PractiseMaster repo, treat it with respect! [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/StephanLuis/PractiseMaster)
2
2
 
3
3
 
4
- Getting started with npm and Webpack
4
+ # CI pathways
5
+
6
+
7
+ | Dev Stage | Pub Trigger | NPM Endpoint|
8
+ | ----------- | ------------- |------------ |
9
+ | Local Debug/ Manual Tests | local devbuild| gitpod ./dist/bundle on 8000
10
+ | BS tests | Git Commit Bundle.js | https://cdn.jsdelivr.net/npm/practisemaster@dev/dist/PMbundle.js |
11
+ | Release | Manual Build and Release (no tag) | https://cdn.jsdelivr.net/npm/practisemaster@latest/dist/PMbundle.js|
12
+ | Homepage w/ Style | None | https://cdn.jsdelivr.net/gh/StephanLuis/PractiseMasterJSplugin@latest/nonobfs/PMbundle.js|
13
+
14
+
15
+ # End To End Test URLs
16
+
17
+ See https://github.com/StephanLuis/BrowserStackSelenium/blob/main/TestURLs/PMtestURLs.js
package/dist/PMbundle.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
6
6
  * or disable the default devtool with "devtool: false".
7
7
  * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
8
- * Does this trigger CI? 4x
8
+ * trigger publish and test 1x
9
9
  */
10
10
  /******/ (() => { // webpackBootstrap
11
11
  /******/ var __webpack_modules__ = ({
@@ -103,7 +103,7 @@ eval("var __WEBPACK_AMD_DEFINE_RESULT__;////////////////////////////////////////
103
103
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
104
104
 
105
105
  "use strict";
106
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _modules_practisemasterWebComponent__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./modules/practisemasterWebComponent */ \"./src/modules/practisemasterWebComponent.js\");\n/* harmony import */ var _modules_linkEditorWebComponent__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./modules/linkEditorWebComponent */ \"./src/modules/linkEditorWebComponent.js\");\n// __ __ ___ ___ __ ___ __ ___ \n// /\\ |__) / ` |__| | | |__ / ` | | | |__) |__ \n// /~~\\ | \\ \\__, | | | | |___ \\__, | \\__/ | \\ |___ \n// \n// \n// read https://github.com/StephanLuis/PractiseMaster/blob/1.0Architecture/src/README.md\n\n\n\n\n\n\n/**\n * this kicks off the webcomponents (entry point)\n */\ncustomElements.define(\"practise-master\", _modules_practisemasterWebComponent__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n \n\n// export default customElements.define('PM-LinkEditer', PMLinkEditerWebComp);\ncustomElements.define('pm-linkediter', _modules_linkEditorWebComponent__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n\n\n\n//# sourceURL=webpack://practisemaster/./src/PM.js?");
106
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _modules_practisemasterWebComponent__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./modules/practisemasterWebComponent */ \"./src/modules/practisemasterWebComponent.js\");\n/* harmony import */ var _modules_linkEditorWebComponent__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./modules/linkEditorWebComponent */ \"./src/modules/linkEditorWebComponent.js\");\n/* harmony import */ var _modules_pageSupport_pm__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./modules/pageSupport-pm */ \"./src/modules/pageSupport-pm.js\");\n/* harmony import */ var _modules_practiseMaster__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./modules/practiseMaster */ \"./src/modules/practiseMaster.js\");\n// __ __ ___ ___ __ ___ __ ___ \n// /\\ |__) / ` |__| | | |__ / ` | | | |__) |__ \n// /~~\\ | \\ \\__, | | | | |___ \\__, | \\__/ | \\ |___ \n// \n// \n// read https://github.com/StephanLuis/PractiseMaster/blob/1.0Architecture/src/README.md\n\n\n\n\n\n\n\n\n\n\n/**\n * this kicks off the webcomponents (entry point)\n */\n\ncustomElements.define(\"practise-master\", _modules_practisemasterWebComponent__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n \n\n\n// export default customElements.define('PM-LinkEditer', PMLinkEditerWebComp);\n\ncustomElements.define('pm-linkediter', _modules_linkEditorWebComponent__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n\n\n\n// then need to new up a PractiseMaster class\n// only want one of these (per page) once init'd then pass array of elements then call PM.player()\n\nwindow.PMpageSupport = new _modules_pageSupport_pm__WEBPACK_IMPORTED_MODULE_2__[\"default\"]();\n\n// question remains of how to pass css into PM? A: use pagesupport above!\n\nwindow.PractiseMaster = new _modules_practiseMaster__WEBPACK_IMPORTED_MODULE_3__[\"default\"]();\n\n\nwindow.PractiseMaster.Loop = (x, y, z) => { return window.PMpageSupport.PMloop(x, y, z);};\n\n\nwindow.PractiseMaster.Chapter = (x, y, z) => { return window.PMpageSupport.PMchapter(x, y, z);};\n\n\n// would like a delete here will have to use await or listen for a final listener\n// window.addEventListener('pmControlsReady', function (e) {\n// delete window.PMpageSupport;\n// });\n\n\n//# sourceURL=webpack://practisemaster/./src/PM.js?");
107
107
 
108
108
  /***/ }),
109
109
 
@@ -114,7 +114,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _mod
114
114
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
115
115
 
116
116
  "use strict";
117
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var input_duration__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! input-duration */ \"./node_modules/input-duration/index.js\");\n/**\n * module provides UIprep class\n * @module UIprep Module\n * @requires InputDuration Module\n */\n\n// chronly self boots / news it self up so here the import is needed but the module is show as not used\n// import ChronlyHMS from 'chronlyhms';\n// import 'chronlyhms/src/chrono.css';\n\n\n\n\n\n\n/**\n * class is for assets that appear once on each page, independant from the number of videos\n * @class UIprep\n * @property {number} id player/plyr/div id\n * @property {boolean} isOnScreen ex. always yes, Safari\n */\n\nclass UIprep {\n\n /**\n * class construlctor\n * @param {element} el PM element\n */\n\n constructor(el) {\n\n this.id = el.id;\n\n this.isOnScreen;\n\n if (window.PractiseMaster.PageSupport.isSafari) {\n this.isOnScreen = false;\n }\n\n }\n\n // Class methods\n\n addAudioStyle(id) {\n\n // this is the same as off player control so may be good to refactor and keep the \n // two together\n\n\n // update control div with buttons\n\n var controls = document.querySelector('#' + id + ' > div.plyr__controls');\n\n // var did = document.querySelectorAll('#' + id + ' input-duration');\n\n // did.forEach(x => x.shadowRoot.querySelectorAll(\".ts_digit\").forEach(x => { x.style.background = \"#BFBFBF\"; }))\n\n controls.style.position = 'inherit';\n\n controls.style.paddingTop = '5px';\n\n controls.style.paddingBottom = '5px';\n\n controls.style.background = '#BFBFBF';\n\n\n document.querySelectorAll('#' + id + ' input-duration').forEach(x => {\n\n x.shadowRoot.querySelectorAll(\".ts_digit\").forEach(x => { x.style.color = \"#ebebeb\"; x.style.fontSize = \" initial\"; });\n\n });\n\n // update player container\n\n document.querySelector('#' + id).style.background = '#BFBFBF';\n\n document.querySelector('#' + id).style.borderRadius = '5px';\n\n // end of duplicate code\n\n var controlsRest = document.querySelector('.plyr--audio .plyr__controls');\n\n controlsRest.style.color = 'white';\n\n\n }\n\n /**\n * sets up loop builder links\n */\n\n addHTMLlink() {\n\n\n // method call\n // window.PractiseMaster.PageSupport.PMloop('HplayerLinks', 5, 6)\n\n var startTime = document.querySelector('#' + this.id + '_timeStart').value.substring(3)\n var endTime = document.querySelector('#' + this.id + '_timeEnd').value.substring(3)\n\n\n var loopLinkLiteral = `\n <br>\n <a href=\"#${this.id}\" onclick=\"window.PractiseMaster.PageSupport.PMloop(\\'${this.id}\\', \\'${startTime}\\', \\'${endTime}\\')\">Loop from ${startTime} to ${endTime}</a>\n <input id='${this.id}_loopbox' type=\"text\" value=\"<a href='#${this.id}' onclick='window.PractiseMaster.PageSupport.PMloop(&quot;${this.id}&quot;, &quot;${startTime}&quot;, &quot;${endTime}&quot;)'>Loop from ${startTime} to ${endTime}</a>\" style=\"width: -webkit-fill-available;\" disabled>\n <input type=\"button\" value=\"Copy Link\" onclick= \"navigator.clipboard.writeText(this.previousElementSibling.value)\">\n </div>\n <br>\n `\n\n\n\n var chapterLinkLiteral = `\n <br>\n <a href=\"#${this.id}\" onclick=\"window.PractiseMaster.PageSupport.PMchapter(\\'${this.id}\\', \\'${startTime}\\', \\'${endTime}\\')\">Chapter from ${startTime} to ${endTime}</a>\n <input type=\"text\" value=\"<a href='#${this.id}' onclick='window.PractiseMaster.PageSupport.PMchapter(&quot;${this.id}&quot;, &quot;${startTime}&quot;, &quot;${endTime}&quot;)'>Chapter from ${startTime} to ${endTime}</a>\" style=\"width: -webkit-fill-available;\" disabled>\n <input type=\"button\" value=\"Copy Link\" onclick= \"navigator.clipboard.writeText(this.previousElementSibling.value)\">\n </div>\n <br>\n `\n\n\n // get player div, add new div as sibling\n\n var broOfLinks = document.querySelector('#' + this.id);\n\n broOfLinks.insertAdjacentHTML('afterend', `<div id='linksShadow'> </div>`);\n\n var broOfLinksShad = document.querySelector('#linksShadow');\n\n\n\n var chosenLiteral = window[\"PMinstance_\" + this.id].loop.off ? chapterLinkLiteral : loopLinkLiteral;\n\n const element = (tag, props) => Object.assign(document.createElement(tag), props);\n\n broOfLinksShad.attachShadow({ mode: 'open' }) // sets and returns this.shadowRoot\n .append(\n element(\"DIV\", {\n innerHTML: chosenLiteral,\n id: this.id\n }),\n element(\"STYLE\", {\n innerHTML : `input,\n textarea,\n select {\n all: revert;\n }`\n })\n );\n\n\n\n\n document.querySelector('#linksShadow').scrollIntoView();\n\n }\n\n\n\n /**\n * sets up chapter builder button and links\n */\n\n addHTMLchapter(start, end) {\n\n alert('The Loop is <a> start: ' + start + ' and end :' + end);\n }\n\n\n\n /**\n * disables ChronlyHMS inputs (for end user)\n */\n\n diableDurationInputs(id) {\n\n\n\n var did = document.querySelectorAll('#' + id + ' input-duration');\n\n did.forEach(one => one.disable());\n\n did.forEach(x => x.shadowRoot.querySelectorAll(\".ts_digit\").forEach(x => { x.style.color = \"lightgray\"; x.style.background = \"none\"; x.style.border = \"none\" }))\n\n }\n\n\n\n /**\n * sets up loop builder button\n * @param {string} id player/plyr/div id\n */\n\n addLinkButton(id) {\n\n var linkButtonLiteral = `\n \n \n <button id=\"${id}_links\" class=\"plyr__controls__item plyr__control\" type=\"button\" style=\"padding-top: 3px; padding-bottom: 6px;\">\n <svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"fak\" data-icon=\"light-link-circle-arrow-down\" role=\"img\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 610 510\" class=\"uploaded-icon-preview svg-inline--fa fa-light-link-circle-arrow-down\" style=\"width: 31px;height: 22px;\"><path fill=\"currentColor\" d=\"M173 131.4c49.1-49.9 130.9-49.9 180.8 0c26.2 26.2 38.5 61 37 95.5c-28 20.9-49.6 50-61.2 83.7c-4.2-5.8-4-14 .9-19.8c1.8-2.1 3.6-4.1 5.4-6.2c32.9-38 30.9-95-4.7-130.5c-37.4-37.5-98.1-37.5-135.5 0c-41.5 41.5-83.1 83-124.6 124.5c-37.5 37.5-37.5 98.3 0 135.8c37.5 37.5 98.3 37.5 135.8 0c7.5-7.5 15.1-15.1 22.6-22.6c6.2-6.3 16.4-6.3 22.6 0c6.3 6.2 6.3 16.3 0 22.6c-7.5 7.5-15.1 15.1-22.6 22.6c-50 50-131 50-181 0s-50-131.9 0-181c41.5-41.5 83-83.1 124.5-124.6zM286.2 380.6c-47.5-47.5-50.2-123.5-7.1-174.2c2.1-2 4.1-4.1 6.2-6.1c5.8-6.7 15.9-7.4 22.6-1.6c6.6 5.7 7.4 15.8 1.6 22.5c-1.8 2.1-3.6 4.1-5.4 6.2c-32.9 38-30.9 95 4.7 130.5c3.5 3.5 7.3 6.8 11.2 9.6c0 .2 0 .3 0 .5c0 13.4 1.5 26.4 4.3 38.9c-13.8-6.2-26.8-15-38.1-26.3zm282.7-283c-37.5-37.5-98.3-37.5-135.8 0c-7.5 7.5-15.1 15.1-22.6 22.6c-6.2 6.3-16.4 6.3-22.6 0c-6.3-7.1-6.3-16.3 0-22.6c7.5-7.5 15.1-15.1 22.6-22.6c50-50 131-50 181 0c43.2 42.4 49.1 109.2 17.7 158.3c-8.1-6.8-16.8-12.9-26-18.1c22.3-36.9 17.6-85.7-14.3-117.5zM496 480c40 0 77-21.3 97-56s20-77.3 0-112s-57-56-97-56s-77 21.3-97 56s-20 77.3 0 112s57 56 97 56zm0-256c51.4 0 99 27.4 124.7 72s25.7 99.4 0 144S547.4 512 496 512s-99-27.4-124.7-72s-25.7-99.4 0-144s73.3-72 124.7-72zm67.3 163.3l-56 56c-6.2 6.3-16.4 6.3-22.6 0c-18.7-18.7-37.3-37.3-56-56c-6.2-6.2-6.2-16.4 0-22.6s16.4-6.2 22.6 0c9.6 9.6 19.1 19.1 28.7 28.7c0-29.8 0-59.6 0-89.4c0-8.8 7.2-16 16-16s16 7.2 16 16c0 29.8 0 59.6 0 89.4c9.6-9.6 19.1-19.1 28.7-28.7c6.2-6.2 16.4-6.2 22.6 0s6.2 16.4 0 22.6z\" class=\"\"></path></svg>\n <span class=\"label--pressed plyr__sr-only\">Text for Label</span>\n <span class=\"label--not-pressed plyr__sr-only\">Text for Label</span>\n </button>\n <div style=\"flex-grow: 1;\"></div>\n `\n\n // append lbl\n\n document.querySelector(\"#\" + id + \" > div.plyr__controls\").insertAdjacentHTML('beforeend', linkButtonLiteral);\n }\n\n\n\n /**\n * adds chronlyHMS to page and styles\n * @param {string} id player/plyr/div id\n */\n\n styleInputDuration(id) {\n\n // general style for 'active' time selector\n\n document.querySelectorAll('#' + id + ' input-duration').forEach(x => {\n\n // removes hours from input duration\n\n x.noHours();\n\n // style timecase\n\n x.shadowRoot.querySelector('.timeCase').style.maxWidth = 'none' // style max width of total control\n x.shadowRoot.querySelector('.timeCase').style.width = \"130px\";\n\n\n\n // style width of inputs\n\n x.shadowRoot.querySelectorAll(\"input.ts_digit\").forEach(y => y.style.width = \"25px\");\n\n x.shadowRoot.querySelectorAll(\"input.sMS.ts_digit\").forEach(y => y.style.width = \"35px\");\n\n\n // style svg\n\n // x.shadowRoot.querySelector(\"#svgContainer\").style.padding = '5px';\n\n x.shadowRoot.querySelector(\"#svgContainer\").style.color = 'white';\n\n });\n\n }\n\n\n\n /**\n * currently unused\n */\n\n applyPlyrReadyCssHTMLSettings() {\n\n // change plyr to static if neccessary \n // early host specific css\n\n }\n\n\n\n /**\n * The player's id for CSS update\n * @param {string} id playerID\n */\n\n applyPMReadyCssHTMLSettings(id) {\n\n\n // PM Controls Style\n\n\n // should this be id based, incase user page has time input on it?\n\n // Array.from(document.querySelectorAll(\"input[type=time]\")).forEach(element => {\n // element.disabled = true;\n\n // element.type = \"text\";\n\n // element.style.minWidth = \"70px\";\n // element.style.maxWidth = \"80px\";\n\n // element.value = \"00:00.00\";\n\n // });\n\n\n // turn off the practise master logo\n\n Array.from(document.querySelectorAll(\".PMlogo\")).forEach(element => {\n element.style.display = \"none\";\n });\n\n\n document.querySelector(\"#\" + id + \" div.plyr__controls\").style.flexWrap = \"wrap\";\n // I think this is the play button display\n // document.querySelector(\"#\" + id + \" div.plyr__controls > button:nth-child(5)\").style.display = \"none\";\n\n\n // late host site specific css \n\n // quick test mode\n\n\n // debug 10 Oct 2022 style at bottom of PM\n // this.hostSite.formatIndependantCSS(id);\n\n // this.hostSite.cssForFiddleHedVimeo(id);\n\n }\n\n\n\n /**\n * @param {object} player \n */\n\n setOffPlayerControls(player) {\n\n if (player.CSSclasses.includes('offScreen') || window.PractiseMaster.PageSupport.isSafari) {\n\n this.offPlayerControls(player.id);\n }\n\n }\n\n\n\n /**\n * see setOffPlayerControls()\n * @param {string} id player/plyr/div id\n */\n\n offPlayerControls(id) {\n\n\n // update control div with buttons\n\n var controls = document.querySelector('#' + id + ' > div.plyr__controls');\n\n controls.style.position = 'inherit';\n\n controls.style.paddingTop = '5px';\n\n controls.style.paddingBottom = '5px';\n\n controls.style.background = '#BFBFBF';\n\n\n // update player container\n\n document.querySelector('#' + id).style.background = '#BFBFBF';\n\n document.querySelector('#' + id).style.borderRadius = '5px';\n\n\n // place controls after wrapper\n\n var wrapper = document.querySelector('#' + id + ' > div.plyr__video-wrapper');\n\n wrapper.after(controls);\n\n }\n\n}\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (UIprep);\n\n//# sourceURL=webpack://practisemaster/./src/modules/UIprep-pm.js?");
117
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var input_duration__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! input-duration */ \"./node_modules/input-duration/index.js\");\n/**\n * module provides UIprep class\n * @module UIprep Module\n * @requires InputDuration Module\n */\n\n// chronly self boots / news it self up so here the import is needed but the module is show as not used\n// import ChronlyHMS from 'chronlyhms';\n// import 'chronlyhms/src/chrono.css';\n\n\n\n\n\n\n/**\n * class is for assets that appear once on each page, independant from the number of videos\n * @class UIprep\n * @property {number} id player/plyr/div id\n * @property {boolean} isOnScreen ex. always yes, Safari\n */\n\nclass UIprep {\n\n /**\n * class construlctor\n * @param {element} el PM element\n */\n\n constructor(el) {\n\n this.id = el.id;\n\n this.isOnScreen;\n\n if (window.PMpageSupport.isSafari) {\n this.isOnScreen = false;\n }\n\n }\n\n // Class methods\n\n addAudioStyle(id) {\n\n // this is the same as off player control so may be good to refactor and keep the \n // two together\n\n\n // update control div with buttons\n\n var controls = document.querySelector('#' + id + ' > div.plyr__controls');\n\n // var did = document.querySelectorAll('#' + id + ' input-duration');\n\n // did.forEach(x => x.shadowRoot.querySelectorAll(\".ts_digit\").forEach(x => { x.style.background = \"#BFBFBF\"; }))\n\n controls.style.position = 'inherit';\n\n controls.style.paddingTop = '5px';\n\n controls.style.paddingBottom = '5px';\n\n controls.style.background = '#BFBFBF';\n\n\n document.querySelectorAll('#' + id + ' input-duration').forEach(x => {\n\n x.shadowRoot.querySelectorAll(\".ts_digit\").forEach(x => { x.style.color = \"#ebebeb\"; x.style.fontSize = \" initial\"; });\n\n });\n\n // update player container\n\n document.querySelector('#' + id).style.background = '#BFBFBF';\n\n document.querySelector('#' + id).style.borderRadius = '5px';\n\n // end of duplicate code\n\n var controlsRest = document.querySelector('.plyr--audio .plyr__controls');\n\n controlsRest.style.color = 'white';\n\n\n }\n\n /**\n * sets up loop builder links\n */\n\n addHTMLlink() {\n\n\n // method call\n // window.PMpageSupport.PMloop('HplayerLinks', 5, 6)\n\n var startTime = document.querySelector('#' + this.id + '_timeStart').value.substring(3)\n var endTime = document.querySelector('#' + this.id + '_timeEnd').value.substring(3)\n\n\n var loopLinkLiteral = `\n <br>\n <a href=\"#${this.id}\" onclick=\"window.PMpageSupport.PMloop(\\'${this.id}\\', \\'${startTime}\\', \\'${endTime}\\')\">Loop from ${startTime} to ${endTime}</a>\n <input id='${this.id}_loopbox' type=\"text\" value=\"<a href='#${this.id}' onclick='window.PMpageSupport.PMloop(&quot;${this.id}&quot;, &quot;${startTime}&quot;, &quot;${endTime}&quot;)'>Loop from ${startTime} to ${endTime}</a>\" style=\"width: -webkit-fill-available;\" disabled>\n <input type=\"button\" value=\"Copy Link\" onclick= \"navigator.clipboard.writeText(this.previousElementSibling.value)\">\n </div>\n <br>\n `\n\n\n\n var chapterLinkLiteral = `\n <br>\n <a href=\"#${this.id}\" onclick=\"window.PMpageSupport.PMchapter(\\'${this.id}\\', \\'${startTime}\\', \\'${endTime}\\')\">Chapter from ${startTime} to ${endTime}</a>\n <input type=\"text\" value=\"<a href='#${this.id}' onclick='window.PMpageSupport.PMchapter(&quot;${this.id}&quot;, &quot;${startTime}&quot;, &quot;${endTime}&quot;)'>Chapter from ${startTime} to ${endTime}</a>\" style=\"width: -webkit-fill-available;\" disabled>\n <input type=\"button\" value=\"Copy Link\" onclick= \"navigator.clipboard.writeText(this.previousElementSibling.value)\">\n </div>\n <br>\n `\n\n\n // get player div, add new div as sibling\n\n var broOfLinks = document.querySelector('#' + this.id);\n\n broOfLinks.insertAdjacentHTML('afterend', `<div id='linksShadow'> </div>`);\n\n var broOfLinksShad = document.querySelector('#linksShadow');\n\n\n\n var chosenLiteral = window[\"PMinstance_\" + this.id].loop.off ? chapterLinkLiteral : loopLinkLiteral;\n\n const element = (tag, props) => Object.assign(document.createElement(tag), props);\n\n broOfLinksShad.attachShadow({ mode: 'open' }) // sets and returns this.shadowRoot\n .append(\n element(\"DIV\", {\n innerHTML: chosenLiteral,\n id: this.id\n }),\n element(\"STYLE\", {\n innerHTML : `input,\n textarea,\n select {\n all: revert;\n }`\n })\n );\n\n\n\n\n document.querySelector('#linksShadow').scrollIntoView();\n\n }\n\n\n\n /**\n * sets up chapter builder button and links\n */\n\n addHTMLchapter(start, end) {\n\n alert('The Loop is <a> start: ' + start + ' and end :' + end);\n }\n\n\n\n /**\n * disables ChronlyHMS inputs (for end user)\n */\n\n diableDurationInputs(id) {\n\n\n\n var did = document.querySelectorAll('#' + id + ' input-duration');\n\n did.forEach(one => one.disable());\n\n did.forEach(x => x.shadowRoot.querySelectorAll(\".ts_digit\").forEach(x => { x.style.color = \"lightgray\"; x.style.background = \"none\"; x.style.border = \"none\" }))\n\n }\n\n\n\n /**\n * sets up loop builder button\n * @param {string} id player/plyr/div id\n */\n\n addLinkButton(id) {\n\n var linkButtonLiteral = `\n \n \n <button id=\"${id}_links\" class=\"plyr__controls__item plyr__control\" type=\"button\" style=\"padding-top: 3px; padding-bottom: 6px;\">\n <svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"fak\" data-icon=\"light-link-circle-arrow-down\" role=\"img\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 610 510\" class=\"uploaded-icon-preview svg-inline--fa fa-light-link-circle-arrow-down\" style=\"width: 31px;height: 22px;\"><path fill=\"currentColor\" d=\"M173 131.4c49.1-49.9 130.9-49.9 180.8 0c26.2 26.2 38.5 61 37 95.5c-28 20.9-49.6 50-61.2 83.7c-4.2-5.8-4-14 .9-19.8c1.8-2.1 3.6-4.1 5.4-6.2c32.9-38 30.9-95-4.7-130.5c-37.4-37.5-98.1-37.5-135.5 0c-41.5 41.5-83.1 83-124.6 124.5c-37.5 37.5-37.5 98.3 0 135.8c37.5 37.5 98.3 37.5 135.8 0c7.5-7.5 15.1-15.1 22.6-22.6c6.2-6.3 16.4-6.3 22.6 0c6.3 6.2 6.3 16.3 0 22.6c-7.5 7.5-15.1 15.1-22.6 22.6c-50 50-131 50-181 0s-50-131.9 0-181c41.5-41.5 83-83.1 124.5-124.6zM286.2 380.6c-47.5-47.5-50.2-123.5-7.1-174.2c2.1-2 4.1-4.1 6.2-6.1c5.8-6.7 15.9-7.4 22.6-1.6c6.6 5.7 7.4 15.8 1.6 22.5c-1.8 2.1-3.6 4.1-5.4 6.2c-32.9 38-30.9 95 4.7 130.5c3.5 3.5 7.3 6.8 11.2 9.6c0 .2 0 .3 0 .5c0 13.4 1.5 26.4 4.3 38.9c-13.8-6.2-26.8-15-38.1-26.3zm282.7-283c-37.5-37.5-98.3-37.5-135.8 0c-7.5 7.5-15.1 15.1-22.6 22.6c-6.2 6.3-16.4 6.3-22.6 0c-6.3-7.1-6.3-16.3 0-22.6c7.5-7.5 15.1-15.1 22.6-22.6c50-50 131-50 181 0c43.2 42.4 49.1 109.2 17.7 158.3c-8.1-6.8-16.8-12.9-26-18.1c22.3-36.9 17.6-85.7-14.3-117.5zM496 480c40 0 77-21.3 97-56s20-77.3 0-112s-57-56-97-56s-77 21.3-97 56s-20 77.3 0 112s57 56 97 56zm0-256c51.4 0 99 27.4 124.7 72s25.7 99.4 0 144S547.4 512 496 512s-99-27.4-124.7-72s-25.7-99.4 0-144s73.3-72 124.7-72zm67.3 163.3l-56 56c-6.2 6.3-16.4 6.3-22.6 0c-18.7-18.7-37.3-37.3-56-56c-6.2-6.2-6.2-16.4 0-22.6s16.4-6.2 22.6 0c9.6 9.6 19.1 19.1 28.7 28.7c0-29.8 0-59.6 0-89.4c0-8.8 7.2-16 16-16s16 7.2 16 16c0 29.8 0 59.6 0 89.4c9.6-9.6 19.1-19.1 28.7-28.7c6.2-6.2 16.4-6.2 22.6 0s6.2 16.4 0 22.6z\" class=\"\"></path></svg>\n <span class=\"label--pressed plyr__sr-only\">Text for Label</span>\n <span class=\"label--not-pressed plyr__sr-only\">Text for Label</span>\n </button>\n <div style=\"flex-grow: 1;\"></div>\n `\n\n // append lbl\n\n document.querySelector(\"#\" + id + \" > div.plyr__controls\").insertAdjacentHTML('beforeend', linkButtonLiteral);\n }\n\n\n\n /**\n * adds chronlyHMS to page and styles\n * @param {string} id player/plyr/div id\n */\n\n styleInputDuration(id) {\n\n // general style for 'active' time selector\n\n document.querySelectorAll('#' + id + ' input-duration').forEach(x => {\n\n // removes hours from input duration\n\n x.noHours();\n\n // style timecase\n\n x.shadowRoot.querySelector('.timeCase').style.maxWidth = 'none' // style max width of total control\n x.shadowRoot.querySelector('.timeCase').style.width = \"130px\";\n\n\n\n // style width of inputs\n\n x.shadowRoot.querySelectorAll(\"input.ts_digit\").forEach(y => y.style.width = \"25px\");\n\n x.shadowRoot.querySelectorAll(\"input.sMS.ts_digit\").forEach(y => y.style.width = \"35px\");\n\n\n // style svg\n\n // x.shadowRoot.querySelector(\"#svgContainer\").style.padding = '5px';\n\n x.shadowRoot.querySelector(\"#svgContainer\").style.color = 'white';\n\n });\n\n }\n\n\n\n /**\n * currently unused\n */\n\n applyPlyrReadyCssHTMLSettings() {\n\n // change plyr to static if neccessary \n // early host specific css\n\n }\n\n\n\n /**\n * The player's id for CSS update\n * @param {string} id playerID\n */\n\n applyPMReadyCssHTMLSettings(id) {\n\n\n // PM Controls Style\n\n\n // should this be id based, incase user page has time input on it?\n\n // Array.from(document.querySelectorAll(\"input[type=time]\")).forEach(element => {\n // element.disabled = true;\n\n // element.type = \"text\";\n\n // element.style.minWidth = \"70px\";\n // element.style.maxWidth = \"80px\";\n\n // element.value = \"00:00.00\";\n\n // });\n\n\n // turn off the practise master logo\n\n Array.from(document.querySelectorAll(\".PMlogo\")).forEach(element => {\n element.style.display = \"none\";\n });\n\n\n document.querySelector(\"#\" + id + \" div.plyr__controls\").style.flexWrap = \"wrap\";\n // I think this is the play button display\n // document.querySelector(\"#\" + id + \" div.plyr__controls > button:nth-child(5)\").style.display = \"none\";\n\n\n // late host site specific css \n\n // quick test mode\n\n\n // debug 10 Oct 2022 style at bottom of PM\n // this.hostSite.formatIndependantCSS(id);\n\n // this.hostSite.cssForFiddleHedVimeo(id);\n\n }\n\n\n\n /**\n * @param {object} player \n */\n\n setOffPlayerControls(player) {\n\n if (player.CSSclasses.includes('offScreen') || window.PMpageSupport.isSafari) {\n\n this.offPlayerControls(player.id);\n }\n\n }\n\n\n\n /**\n * see setOffPlayerControls()\n * @param {string} id player/plyr/div id\n */\n\n offPlayerControls(id) {\n\n\n // update control div with buttons\n\n var controls = document.querySelector('#' + id + ' > div.plyr__controls');\n\n controls.style.position = 'inherit';\n\n controls.style.paddingTop = '5px';\n\n controls.style.paddingBottom = '5px';\n\n controls.style.background = '#BFBFBF';\n\n\n // update player container\n\n document.querySelector('#' + id).style.background = '#BFBFBF';\n\n document.querySelector('#' + id).style.borderRadius = '5px';\n\n\n // place controls after wrapper\n\n var wrapper = document.querySelector('#' + id + ' > div.plyr__video-wrapper');\n\n wrapper.after(controls);\n\n }\n\n}\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (UIprep);\n\n//# sourceURL=webpack://practisemaster/./src/modules/UIprep-pm.js?");
118
118
 
119
119
  /***/ }),
120
120
 
@@ -158,7 +158,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
158
158
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
159
159
 
160
160
  "use strict";
161
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _practiseMaster__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./practiseMaster */ \"./src/modules/practiseMaster.js\");\n\n\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = /*html*/`\n<style>\n\n\ninput,\n textarea,\n select {\n all: revert;\n }\n</style>\n<div id =\"lbContainer\">\n<div id=\"pmHeader\">\n <h1 >PractiseMaster Precision Loop Editor</h1>\n <br>\n <br>\n <br>\n </div>\n \n <h3> Step 0 (Optional): Install Link Builder</h3>\n <br>\n <div>See instruction to install PM (link), simplified copy the script tag to webpage (or its masterpage)</div>\n <br><br>\n <label for=\"jsURLdisplay\">Script Tag</label>\n <input style=\"width: -webkit-fill-available;\" id=\"jsURLdisplay\" disabled value=\"<script type='module' src='https://cdn.jsdelivr.net/gh/StephanLuis/PractiseMasterJSplugin@latest/nonobfs/PMbundle.js'></script>\">\n <input type=\"button\" value=\"Copy\" onclick= \"navigator.clipboard.writeText(this.previousElementSibling.value)\">\n <br><br>\n and add a pm-linkediter element to the webpage\n <br><br>\n <label for=\"linkBuilderDisplay\">Video Embed</label>\n <input style=\"width: -webkit-fill-available;\" id=\"linkBuilderDisplay\" disabled value=\"<pm-linkediter></pm-linkediter>\" >\n <input type=\"button\" value=\"Copy\" onclick= \"navigator.clipboard.writeText(this.previousElementSibling.value)\">\n <br><br>\n\n <div> or try non dom locked videos here.</div>\n <br><br>\n <h3> Step 1: Select Source</h3>\n \n <fieldset>\n <legend>Please select your preferred video/audio source:</legend>\n <div>\n <input type=\"radio\" id=\"source1\" name=\"source\" value=\"vimeo\" />\n <label for=\"source1\">Vimeo</label>\n <input type=\"radio\" id=\"source2\" name=\"source\" value=\"youtube\" />\n <label for=\"source2\">YouTube</label>\n \n </div>\n <label for=\"providerVidID\">YouTube or Vimeo ID</label>\n <input id=\"providerVidID\" type=\"text\">\n <div>\n <br> \n <div>\n <input type=\"radio\" id=\"source3\" name=\"source\" value=\"MP4\" />\n <label for=\"source3\">MP4</label>\n <input type=\"radio\" id=\"source4\" name=\"source\" value=\"MP3\" />\n <label for=\"source4\">MP3</label>\n <input type=\"radio\" id=\"source3\" name=\"source\" value=\"OGG\" />\n <label for=\"source3\">OGG</label>\n </div>\n <label for=\"sourceURL\">Hosted Source</label>\n <input id=\"sourceURL\" type=\"text\"> (Public URL)\n <div>\n <br>\n <button id=\"doMine\">Start Video</button> <button id=\"refresh\" onclick=\"location.reload();\">Clear Player & Start Again</button>\n </div>\n <br>\n <br>\n <fieldset>\n <div>\n If you need sources to try:\n <ul>\n <li>Vimeo: 650483703 <button class=\"demoButton\" id=\"demoVimeoB\">Start Vimeo</button>\n <li>YouTube: Ve_iBdF9mF0 <button class=\"demoButton\" id=\"demoYTB\">Start YouTube</button>\n <li>MP4 Video: https://cdnpmvideoaudioendpoint-h3efathnece6dngs.z01.azurefd.net/pmcontainer/diyPopFullSize.mp4 <button class=\"demoButton\" id=\"demoMP4B\">Start MP4</button>\n <li>MP3 Audio: https://cdnpmvideoaudioendpoint-h3efathnece6dngs.z01.azurefd.net/pmcontainer/diyPop.mp3 <button class=\"demoButton\" id=\"demoMP3B\">Start MP3</button>\n </ul>\n </div>\n </fieldset>\n </fieldset>\n \n\n\n <div id=\"copyInputDiv\"style=\"display: none;\" >\n\n <br>\n <br>\n <br>\n\n <h3 id=\"step2\"> Step 2: Copy video embed </h3>\n <label for=\"vidDivDisplay\">Video Embed</label>\n <input style=\"width: -webkit-fill-available;\" id=\"vidDivDisplay\" disabled >\n <br>\n <br>\n <br>\n <h3>Step 3: Code Loops (<svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"fak\" data-icon=\"light-link-circle-arrow-down\" role=\"img\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 610 510\" class=\"uploaded-icon-preview svg-inline--fa fa-light-link-circle-arrow-down\" style=\"width: 31px;height: 22px;\"><path fill=\"currentColor\" d=\"M173 131.4c49.1-49.9 130.9-49.9 180.8 0c26.2 26.2 38.5 61 37 95.5c-28 20.9-49.6 50-61.2 83.7c-4.2-5.8-4-14 .9-19.8c1.8-2.1 3.6-4.1 5.4-6.2c32.9-38 30.9-95-4.7-130.5c-37.4-37.5-98.1-37.5-135.5 0c-41.5 41.5-83.1 83-124.6 124.5c-37.5 37.5-37.5 98.3 0 135.8c37.5 37.5 98.3 37.5 135.8 0c7.5-7.5 15.1-15.1 22.6-22.6c6.2-6.3 16.4-6.3 22.6 0c6.3 6.2 6.3 16.3 0 22.6c-7.5 7.5-15.1 15.1-22.6 22.6c-50 50-131 50-181 0s-50-131.9 0-181c41.5-41.5 83-83.1 124.5-124.6zM286.2 380.6c-47.5-47.5-50.2-123.5-7.1-174.2c2.1-2 4.1-4.1 6.2-6.1c5.8-6.7 15.9-7.4 22.6-1.6c6.6 5.7 7.4 15.8 1.6 22.5c-1.8 2.1-3.6 4.1-5.4 6.2c-32.9 38-30.9 95 4.7 130.5c3.5 3.5 7.3 6.8 11.2 9.6c0 .2 0 .3 0 .5c0 13.4 1.5 26.4 4.3 38.9c-13.8-6.2-26.8-15-38.1-26.3zm282.7-283c-37.5-37.5-98.3-37.5-135.8 0c-7.5 7.5-15.1 15.1-22.6 22.6c-6.2 6.3-16.4 6.3-22.6 0c-6.3-7.1-6.3-16.3 0-22.6c7.5-7.5 15.1-15.1 22.6-22.6c50-50 131-50 181 0c43.2 42.4 49.1 109.2 17.7 158.3c-8.1-6.8-16.8-12.9-26-18.1c22.3-36.9 17.6-85.7-14.3-117.5zM496 480c40 0 77-21.3 97-56s20-77.3 0-112s-57-56-97-56s-77 21.3-97 56s-20 77.3 0 112s57 56 97 56zm0-256c51.4 0 99 27.4 124.7 72s25.7 99.4 0 144S547.4 512 496 512s-99-27.4-124.7-72s-25.7-99.4 0-144s73.3-72 124.7-72zm67.3 163.3l-56 56c-6.2 6.3-16.4 6.3-22.6 0c-18.7-18.7-37.3-37.3-56-56c-6.2-6.2-6.2-16.4 0-22.6s16.4-6.2 22.6 0c9.6 9.6 19.1 19.1 28.7 28.7c0-29.8 0-59.6 0-89.4c0-8.8 7.2-16 16-16s16 7.2 16 16c0 29.8 0 59.6 0 89.4c9.6-9.6 19.1-19.1 28.7-28.7c6.2-6.2 16.4-6.2 22.6 0s6.2 16.4 0 22.6z\" class=\"\"></path></svg>).</h1>\n <p>Set loop times and click link button</p>\n <br>\n <br>\n <br>\n </div>\n </div>\n `\n\nclass linkEditorWebComponent extends HTMLElement {\n constructor() {\n \n // Always call super first in constructor\n super();\n\n\n this.pmElements = [];\n\n this.myElement = this.attachShadow({ mode: 'open' });\n\n // property injection (init here use later)\n this.PM = new _practiseMaster__WEBPACK_IMPORTED_MODULE_0__[\"default\"]();\n\n this.initialiseContainers();\n\n }\n\n initialiseContainers() {\n\n // add a wrapper div to <pm-linkediter>\n\n // element that will be wrapped\n var el = document.querySelector('pm-linkediter');\n\n // create wrapper container\n var wrapper = document.createElement('div');\n\n wrapper.id = 'lbContainer';\n\n // insert wrapper before el in the DOM tree\n el.parentNode.insertBefore(wrapper, el);\n\n // move el into wrapper\n wrapper.appendChild(el);\n\n }\n\n // end constructor\n\n\n connectedCallback() {\n\n\n\n this.shadowRoot.appendChild(template.content.cloneNode(true));\n\n this.startLinkBuilder();\n\n var siteCSS = 'toBeCreatedSiteCSS';\n\n // initialiseContainers should have popluated\n\n this.PM.pmElements = this.pmElements;\n this.PM.player(siteCSS);\n\n }\n\n\n startLinkBuilder() {\n\n this.addDoMineButtonListener();\n\n this.addDoDemosButtonListener();\n\n }\n\n\n addDoMineButtonListener() {\n\n // 'submit' from the LoopBuilder form\n\n const button = this.myElement.querySelector(\"#doMine\");\n\n button.addEventListener(\n \"click\",\n (event) => {\n\n\n //create new div to replicate \n // and place it after .container\n\n // radio button for source type ex MP4, MP3\n\n const radioButtons = this.myElement.querySelectorAll('input[name=\"source\"]');\n\n\n // text box value for youtube / vimeo id\n\n const vidID = this.myElement.querySelector('#providerVidID').value.trim();\n\n\n // text box for source url (mp4/mp3)\n\n const sourceURL = this.myElement.querySelector('#sourceURL').value.trim();\n\n\n let choice;\n\n for (const radioButton of radioButtons) {\n if (radioButton.checked) {\n choice = radioButton.value;\n break;\n }\n }\n\n\n // html for player and for user to copy\n\n var htmlLitPage;\n\n if (choice === 'MP4') {\n\n htmlLitPage = `<video id=\"myMP4\" class=\"pm links\" controls crossorigin playsinline> <source src=\"${sourceURL}\" type=\"video/mp4\"> <!-- Fallback for browsers that don't support the <video> element -->\n <a href=\"${sourceURL}\" download>Download</a> </video>`;\n\n }\n\n else if (choice === 'MP3') {\n\n htmlLitPage = `<audio id=\"myMP3\" class=\"pm links\" crossorigin playsinline> <source src=\"${sourceURL}\" type=\"audio/mp3\"> </audio> `;\n\n }\n\n else if (choice === 'OGG') {\n\n htmlLitPage = `<audio id=\"myOGG\" class=\"pm links\" crossorigin playsinline> <source src=\"${sourceURL}\" type=\"audio/ogg\"> </audio> `;\n\n }\n\n else {\n\n htmlLitPage = `\n <div id=\"${choice}_${vidID}\" class=\"pm links\" data-plyr-provider=\"${choice}\" data-plyr-embed-id=\"${vidID}\"></div>\n `;\n\n }\n\n\n this.postOnPage(htmlLitPage);\n\n\n event.preventDefault();\n\n\n this.startAndShow();\n\n },\n\n false\n );\n }\n\n\n \n\n addDoDemosButtonListener() {\n\n // 'submit' from the LoopBuilder form\n\n const buttons = this.myElement.querySelectorAll(\"button.demoButton\");\n\n buttons.forEach(button =>\n\n button.addEventListener(\n \"click\",\n (event) => {\n //create new div to replicate \n // and place it after .container\n\n const vimeoID = '650483703';\n const YTubeID = 'Ve_iBdF9mF0';\n const MP3url = 'https://cdnpmvideoaudioendpoint-h3efathnece6dngs.z01.azurefd.net/pmcontainer/diyPop.mp3';\n const MP4url = 'https://cdnpmvideoaudioendpoint-h3efathnece6dngs.z01.azurefd.net/pmcontainer/diyPopFullSize.mp4';\n\n\n var htmlLitPage;\n\n if (button.id === 'demoMP4B') {\n\n htmlLitPage = `<video id=\"demoMP4\" class=\"pm links\" controls crossorigin playsinline> <source src=\"${MP4url}\" type=\"video/mp4\"> <!-- Fallback for browsers that don't support the <video> element --> <a href=\"${MP4url}\" download>Download</a> </video>\n\n `;\n\n }\n\n else if (button.id === 'demoMP3B') {\n\n htmlLitPage = `<audio id=\"demoMP3\" class=\"pm links\" crossorigin playsinline> <source src=\"${MP3url}\" type=\"audio/mp3\"> </audio> `;\n\n }\n\n\n else if (button.id === 'demoVimeoB') {\n\n htmlLitPage = `<div id=\"Vimeo_650483703\" class=\"pm links\" data-plyr-provider=\"vimeo\" data-plyr-embed-id=\"650483703\"></div>`;\n\n\n }\n\n else if (button.id === 'demoYTB') {\n\n htmlLitPage = ` <div id=\"YouTube_Ve_iBdF9mF0\" class=\"pm links\" data-plyr-provider=\"youtube\" data-plyr-embed-id=\"Ve_iBdF9mF0\"></div> `;\n\n\n }\n\n\n this.postOnPage(htmlLitPage);\n\n\n this.startAndShow();\n\n\n event.preventDefault();\n\n },\n\n\n false\n\n )\n );\n }\n\n postOnPage(litHTML) {\n\n // should refactor from here! to end\n\n // for the textbox (user's code) need to remove the links class\n\n var htmlLitTextBox = litHTML.replace(' links', '');\n\n\n // add video player to page\n\n document.querySelector('#lbContainer').insertAdjacentHTML('beforeend', litHTML);\n\n\n // this is the container for step 2\n this.myElement.querySelector('#copyInputDiv').style.display = \"block\";\n\n\n // add disabled text box to display link code\n var vidDivDisplay = this.myElement.querySelector(\"#vidDivDisplay\");\n\n\n vidDivDisplay.value = htmlLitTextBox;\n\n\n // add button to copy loop link code \n\n var vidDivCopyButtonLit = `<input id=\"copyVidDiv\" type=\"button\" onclick=\"((event) => {navigator.clipboard.writeText(document.querySelector('pm-linkediter').shadowRoot.querySelector('#vidDivDisplay').value);})()\" value=\"Copy Video Div\">`;\n\n vidDivDisplay.insertAdjacentHTML('afterend', vidDivCopyButtonLit);\n\n }\n\n\n startAndShow() {\n\n\n\n this.pmElements.push(document.querySelector('.pm'));\n // // start practisemaster\n this.PM.player();\n\n // scroll to step 2 for the user\n\n document.querySelector(\"pm-linkediter\").shadowRoot.querySelector(\"#step2\").scrollIntoView({ behavior: 'smooth' });\n\n\n }\n\n}\n// end class\n\n\n//export default customElements.define('PM-LinkEditer', PMLinkEditerWebComp);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (linkEditorWebComponent);\n\n\n\n//# sourceURL=webpack://practisemaster/./src/modules/linkEditorWebComponent.js?");
161
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _practiseMaster__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./practiseMaster */ \"./src/modules/practiseMaster.js\");\n\n\nconst template = document.createElement(\"template\");\ntemplate.innerHTML = /*html*/`\n<style>\n\n\ninput,\n textarea,\n select {\n all: revert;\n }\n</style>\n<div id =\"lbContainerIn\">\n<div id=\"pmHeader\">\n <h1 >PractiseMaster Precision Loop Editor</h1>\n <br>\n <br>\n <br>\n </div>\n \n <h3> Step 0 (Optional): Install Link Builder</h3>\n <br>\n <div>See instruction to install PM (link), simplified copy the script tag to webpage (or its masterpage)</div>\n <br><br>\n <label for=\"jsURLdisplay\">Script Tag</label>\n <input style=\"width: -webkit-fill-available;\" id=\"jsURLdisplay\" disabled value=\"<script type='module' src='https://cdn.jsdelivr.net/npm/practisemaster@latest/dist/PMbundle.js'></script>\">\n <input type=\"button\" value=\"Copy\" onclick= \"navigator.clipboard.writeText(this.previousElementSibling.value)\">\n <br><br>\n and add a pm-linkediter element to the webpage\n <br><br>\n <label for=\"linkBuilderDisplay\">Video Embed</label>\n <input style=\"width: -webkit-fill-available;\" id=\"linkBuilderDisplay\" disabled value=\"<pm-linkediter></pm-linkediter>\" >\n <input type=\"button\" value=\"Copy\" onclick= \"navigator.clipboard.writeText(this.previousElementSibling.value)\">\n <br><br>\n\n <div> or try non dom locked videos here.</div>\n <br><br>\n <h3> Step 1: Select Source</h3>\n \n <fieldset>\n <legend>Please select your preferred video/audio source:</legend>\n <div>\n <input type=\"radio\" id=\"source1\" name=\"source\" value=\"vimeo\" />\n <label for=\"source1\">Vimeo</label>\n <input type=\"radio\" id=\"source2\" name=\"source\" value=\"youtube\" />\n <label for=\"source2\">YouTube</label>\n \n </div>\n <label for=\"providerVidID\">YouTube or Vimeo ID</label>\n <input id=\"providerVidID\" type=\"text\">\n <div>\n <br> \n <div>\n <input type=\"radio\" id=\"source3\" name=\"source\" value=\"MP4\" />\n <label for=\"source3\">MP4</label>\n <input type=\"radio\" id=\"source4\" name=\"source\" value=\"MP3\" />\n <label for=\"source4\">MP3</label>\n <input type=\"radio\" id=\"source3\" name=\"source\" value=\"OGG\" />\n <label for=\"source3\">OGG</label>\n </div>\n <label for=\"sourceURL\">Hosted Source</label>\n <input id=\"sourceURL\" type=\"text\"> (Public URL)\n <div>\n <br>\n <button id=\"doMine\">Start Video</button> <button id=\"refresh\" onclick=\"location.reload();\">Clear Player & Start Again</button>\n </div>\n <br>\n <br>\n <fieldset>\n <div>\n If you need sources to try:\n <ul>\n <li>Vimeo: 650483703 <button class=\"demoButton\" id=\"demoVimeoB\">Start Vimeo</button>\n <li>YouTube: Ve_iBdF9mF0 <button class=\"demoButton\" id=\"demoYTB\">Start YouTube</button>\n <li>MP4 Video: https://cdnpmvideoaudioendpoint-h3efathnece6dngs.z01.azurefd.net/pmcontainer/diyPopFullSize.mp4 <button class=\"demoButton\" id=\"demoMP4B\">Start MP4</button>\n <li>MP3 Audio: https://cdnpmvideoaudioendpoint-h3efathnece6dngs.z01.azurefd.net/pmcontainer/diyPop.mp3 <button class=\"demoButton\" id=\"demoMP3B\">Start MP3</button>\n </ul>\n </div>\n </fieldset>\n </fieldset>\n \n\n\n <div id=\"copyInputDiv\"style=\"display: none;\" >\n\n <br>\n <br>\n <br>\n\n <h3 id=\"step2\"> Step 2: Copy video embed </h3>\n <label for=\"vidDivDisplay\">Video Embed</label>\n <input style=\"width: -webkit-fill-available;\" id=\"vidDivDisplay\" disabled >\n <br>\n <br>\n <br>\n <h3>Step 3: Code Loops (<svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"fak\" data-icon=\"light-link-circle-arrow-down\" role=\"img\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 610 510\" class=\"uploaded-icon-preview svg-inline--fa fa-light-link-circle-arrow-down\" style=\"width: 31px;height: 22px;\"><path fill=\"currentColor\" d=\"M173 131.4c49.1-49.9 130.9-49.9 180.8 0c26.2 26.2 38.5 61 37 95.5c-28 20.9-49.6 50-61.2 83.7c-4.2-5.8-4-14 .9-19.8c1.8-2.1 3.6-4.1 5.4-6.2c32.9-38 30.9-95-4.7-130.5c-37.4-37.5-98.1-37.5-135.5 0c-41.5 41.5-83.1 83-124.6 124.5c-37.5 37.5-37.5 98.3 0 135.8c37.5 37.5 98.3 37.5 135.8 0c7.5-7.5 15.1-15.1 22.6-22.6c6.2-6.3 16.4-6.3 22.6 0c6.3 6.2 6.3 16.3 0 22.6c-7.5 7.5-15.1 15.1-22.6 22.6c-50 50-131 50-181 0s-50-131.9 0-181c41.5-41.5 83-83.1 124.5-124.6zM286.2 380.6c-47.5-47.5-50.2-123.5-7.1-174.2c2.1-2 4.1-4.1 6.2-6.1c5.8-6.7 15.9-7.4 22.6-1.6c6.6 5.7 7.4 15.8 1.6 22.5c-1.8 2.1-3.6 4.1-5.4 6.2c-32.9 38-30.9 95 4.7 130.5c3.5 3.5 7.3 6.8 11.2 9.6c0 .2 0 .3 0 .5c0 13.4 1.5 26.4 4.3 38.9c-13.8-6.2-26.8-15-38.1-26.3zm282.7-283c-37.5-37.5-98.3-37.5-135.8 0c-7.5 7.5-15.1 15.1-22.6 22.6c-6.2 6.3-16.4 6.3-22.6 0c-6.3-7.1-6.3-16.3 0-22.6c7.5-7.5 15.1-15.1 22.6-22.6c50-50 131-50 181 0c43.2 42.4 49.1 109.2 17.7 158.3c-8.1-6.8-16.8-12.9-26-18.1c22.3-36.9 17.6-85.7-14.3-117.5zM496 480c40 0 77-21.3 97-56s20-77.3 0-112s-57-56-97-56s-77 21.3-97 56s-20 77.3 0 112s57 56 97 56zm0-256c51.4 0 99 27.4 124.7 72s25.7 99.4 0 144S547.4 512 496 512s-99-27.4-124.7-72s-25.7-99.4 0-144s73.3-72 124.7-72zm67.3 163.3l-56 56c-6.2 6.3-16.4 6.3-22.6 0c-18.7-18.7-37.3-37.3-56-56c-6.2-6.2-6.2-16.4 0-22.6s16.4-6.2 22.6 0c9.6 9.6 19.1 19.1 28.7 28.7c0-29.8 0-59.6 0-89.4c0-8.8 7.2-16 16-16s16 7.2 16 16c0 29.8 0 59.6 0 89.4c9.6-9.6 19.1-19.1 28.7-28.7c6.2-6.2 16.4-6.2 22.6 0s6.2 16.4 0 22.6z\" class=\"\"></path></svg>).</h1>\n <p>Set loop times and click link button</p>\n <br>\n <br>\n <br>\n </div>\n </div>\n `\n\nclass linkEditorWebComponent extends HTMLElement {\n constructor() {\n\n // Always call super first in constructor\n super();\n\n\n // 19 Jan\n // this.pmElements = [];\n\n this.myElement = this.attachShadow({ mode: 'open' });\n\n \n this.initialiseContainers();\n\n }\n\n initialiseContainers() {\n\n // add a wrapper div to <pm-linkediter>\n\n // element that will be wrapped\n var el = document.querySelector('pm-linkediter');\n\n // create wrapper container\n var wrapper = document.createElement('div');\n\n wrapper.id = 'lbContainerOut';\n\n // insert wrapper before el in the DOM tree\n el.parentNode.insertBefore(wrapper, el);\n\n // move el into wrapper\n wrapper.appendChild(el);\n\n }\n\n // end constructor\n\n\n connectedCallback() {\n\n\n\n this.shadowRoot.appendChild(template.content.cloneNode(true));\n\n this.startLinkBuilder();\n\n\n // initialiseContainers should have popluated\n\n \n\n }\n\n\n startLinkBuilder() {\n\n this.addDoMineButtonListener();\n\n this.addDoDemosButtonListener();\n\n }\n\n\n addDoMineButtonListener() {\n\n // 'submit' from the LoopBuilder form\n\n const button = this.myElement.querySelector(\"#doMine\");\n\n button.addEventListener(\n \"click\",\n (event) => {\n\n\n //create new div to replicate \n // and place it after .container\n\n // radio button for source type ex MP4, MP3\n\n const radioButtons = this.myElement.querySelectorAll('input[name=\"source\"]');\n\n\n // text box value for youtube / vimeo id\n\n const vidID = this.myElement.querySelector('#providerVidID').value.trim();\n\n\n // text box for source url (mp4/mp3)\n\n const sourceURL = this.myElement.querySelector('#sourceURL').value.trim();\n\n\n let choice;\n\n for (const radioButton of radioButtons) {\n if (radioButton.checked) {\n choice = radioButton.value;\n break;\n }\n }\n\n\n // html for player and for user to copy\n\n var htmlLitPage;\n\n if (choice === 'MP4') {\n\n htmlLitPage = `<video id=\"myMP4\" class=\"pm links\" controls crossorigin playsinline> <source src=\"${sourceURL}\" type=\"video/mp4\"> <!-- Fallback for browsers that don't support the <video> element -->\n <a href=\"${sourceURL}\" download>Download</a> </video>`;\n\n }\n\n else if (choice === 'MP3') {\n\n htmlLitPage = `<audio id=\"myMP3\" class=\"pm links\" crossorigin playsinline> <source src=\"${sourceURL}\" type=\"audio/mp3\"> </audio> `;\n\n }\n\n else if (choice === 'OGG') {\n\n htmlLitPage = `<audio id=\"myOGG\" class=\"pm links\" crossorigin playsinline> <source src=\"${sourceURL}\" type=\"audio/ogg\"> </audio> `;\n\n }\n\n else {\n\n htmlLitPage = `\n <div id=\"${choice}_${vidID}\" class=\"pm links\" data-plyr-provider=\"${choice}\" data-plyr-embed-id=\"${vidID}\"></div>\n `;\n\n }\n\n\n this.postOnPage(htmlLitPage);\n\n\n event.preventDefault();\n\n\n this.startAndShow();\n\n },\n\n false\n );\n }\n\n\n\n\n addDoDemosButtonListener() {\n\n // 'submit' from the LoopBuilder form\n\n const buttons = this.myElement.querySelectorAll(\"button.demoButton\");\n\n buttons.forEach(button =>\n\n button.addEventListener(\n \"click\",\n (event) => {\n //create new div to replicate \n // and place it after .container\n\n const vimeoID = '650483703';\n const YTubeID = 'Ve_iBdF9mF0';\n const MP3url = 'https://cdnpmvideoaudioendpoint-h3efathnece6dngs.z01.azurefd.net/pmcontainer/diyPop.mp3';\n const MP4url = 'https://cdnpmvideoaudioendpoint-h3efathnece6dngs.z01.azurefd.net/pmcontainer/diyPopFullSize.mp4';\n\n\n var htmlLitPage;\n\n if (button.id === 'demoMP4B') {\n\n htmlLitPage = `<video id=\"demoMP4\" class=\"pm links\" controls crossorigin playsinline> <source src=\"${MP4url}\" type=\"video/mp4\"> <!-- Fallback for browsers that don't support the <video> element --> <a href=\"${MP4url}\" download>Download</a> </video>\n\n `;\n\n }\n\n else if (button.id === 'demoMP3B') {\n\n htmlLitPage = `<audio id=\"demoMP3\" class=\"pm links\" crossorigin playsinline> <source src=\"${MP3url}\" type=\"audio/mp3\"> </audio> `;\n\n }\n\n\n else if (button.id === 'demoVimeoB') {\n\n htmlLitPage = `<div id=\"Vimeo_650483703\" class=\"pm links\" data-plyr-provider=\"vimeo\" data-plyr-embed-id=\"650483703\"></div>`;\n\n\n }\n\n else if (button.id === 'demoYTB') {\n\n htmlLitPage = ` <div id=\"YouTube_Ve_iBdF9mF0\" class=\"pm links\" data-plyr-provider=\"youtube\" data-plyr-embed-id=\"Ve_iBdF9mF0\"></div> `;\n\n\n }\n\n\n this.postOnPage(htmlLitPage);\n\n\n this.startAndShow();\n\n\n event.preventDefault();\n\n },\n\n\n false\n\n )\n );\n }\n\n postOnPage(litHTML) {\n\n // should refactor from here! to end\n\n // for the textbox (user's code) need to remove the links class\n\n var htmlLitTextBox = litHTML.replace(' links', '');\n\n\n // add video player to page\n\n document.querySelector('#lbContainerOut').insertAdjacentHTML('beforeend', litHTML);\n\n \n\n // this is the container for step 2\n this.myElement.querySelector('#copyInputDiv').style.display = \"block\";\n\n\n // add disabled text box to display link code\n var vidDivDisplay = this.myElement.querySelector(\"#vidDivDisplay\");\n\n\n vidDivDisplay.value = htmlLitTextBox;\n\n\n // add button to copy loop link code \n\n var vidDivCopyButtonLit = `<input id=\"copyVidDiv\" type=\"button\" onclick=\"((event) => {navigator.clipboard.writeText(document.querySelector('pm-linkediter').shadowRoot.querySelector('#vidDivDisplay').value);})()\" value=\"Copy Video Div\">`;\n\n vidDivDisplay.insertAdjacentHTML('afterend', vidDivCopyButtonLit);\n\n }\n\n\n startAndShow() {\n\n\n // override Class property\n\n window.PractiseMaster.pmElements = document.querySelectorAll('div.pm');\n \n // start practisemaster\n window.PractiseMaster.player();\n\n // scroll to step 2 for the user\n\n document.querySelector(\"pm-linkediter\").shadowRoot.querySelector(\"#step2\").scrollIntoView({ behavior: 'smooth' });\n\n\n }\n\n}\n// end class\n\n\n//export default customElements.define('PM-LinkEditer', PMLinkEditerWebComp);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (linkEditorWebComponent);\n\n\n\n//# sourceURL=webpack://practisemaster/./src/modules/linkEditorWebComponent.js?");
162
162
 
163
163
  /***/ }),
164
164
 
@@ -169,7 +169,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
169
169
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
170
170
 
171
171
  "use strict";
172
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/**\n * module provides the Loop class, currently member of the Player class\n * @module Loop Module\n */\n\n\n/**\n * loops a time range of video/audio \n * @class Loop\n * @property {string} id from element\n * @property {number} videoDuration in seconds\n * @property {number} startTimeSeconds in seconds\n * @property {number} endTimeSeconds in seconds\n * @property {boolean} off is loop turned off\n * @property {declaration} code block event listener for loops\n */\n\nclass Loop {\n\n /**\n * class constructor\n * @param {string} id player/plyr/div id\n */\n\n constructor(id) {\n\n this.id = id;\n this._videoDuration = 1;\n\n // need initial value for arrow key <> addition of time on UI\n this._startTimeSeconds = 0;\n this._endTimeSeconds = 0;\n\n this.off = true;\n\n /// This event listener drives the looping, on timeupdate event from plyr\n\n // can try to update to something like // document.addEventListener('timeupdate', id, this.playSegment);\n\n\n document.addEventListener('timeupdate', window.PractiseMaster.PageSupport.helpers.delegateByIDparams(this.id, this.startTimeSeconds, this.endTimeSeconds, this.playSegment));\n\n\n \n\n }\n\n\n /**\n * for precision of loops all time values will be seconds * 10000 (times ten thousand)\n */\n set startTimeSeconds(secs) {\n this._startTimeSeconds = secs * 10000;\n }\n /**\n * for precision of loops all time values will be seconds * 10000 (times ten thousand)\n */\n get startTimeSeconds() {\n return this._startTimeSeconds;\n }\n /**\n * for precision of loops all time values will be seconds * 10000 (times ten thousand)\n */\n set endTimeSeconds(secs) {\n this._endTimeSeconds = secs * 10000;\n }\n /**\n * for precision of loops all time values will be seconds * 10000 (times ten thousand)\n */\n get endTimeSeconds() {\n return this._endTimeSeconds;\n }\n /**\n * for precision of loops all time values will be seconds * 10000 (times ten thousand)\n */\n set videoDuration(secs) {\n this._videoDuration = secs * 10000;\n }\n /**\n * for precision of loops all time values will be seconds * 10000 (times ten thousand)\n */\n get videoDuration() {\n return this._videoDuration;\n }\n\n\n\n /**\n * plays a loop\n */\n\n playSegment() {\n\n // not sure of the reason for this empty string check. Think it's about not picking up the events from non practisemaster Plyr videos on the page\n\n if (this.id !== \"\") {\n\n // if Loop not switched offF\n\n if (!window[\"PMinstance_\" + this.id].loop.off) {\n\n\n // control time of chapter\n\n var currentTime = window[\"PMinstance_\" + this.id].plyrInstance.currentTime * 10000;\n\n if (currentTime < window[\"PMinstance_\" + this.id].loop.startTimeSeconds || window[\"PMinstance_\" + this.id].loop.endTimeSeconds < currentTime) {\n\n window[\"PMinstance_\" + this.id].plyrInstance.currentTime = window[\"PMinstance_\" + this.id].loop.startTimeSeconds / 10000;\n\n console.log('reset video to start : ' + window[\"PMinstance_\" + this.id].loop.startTimeSeconds / 10000);\n\n console.log('Player ' + this.id + ' has looped, current time: ' + currentTime + ' , end time: ' + window[\"PMinstance_\" + this.id].loop.endTimeSeconds);\n }\n\n }\n\n }\n\n }\n\n}\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Loop);\n\n//# sourceURL=webpack://practisemaster/./src/modules/loop-pm.js?");
172
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/**\n * module provides the Loop class, currently member of the Player class\n * @module Loop Module\n */\n\n\n/**\n * loops a time range of video/audio \n * @class Loop\n * @property {string} id from element\n * @property {number} videoDuration in seconds\n * @property {number} startTimeSeconds in seconds\n * @property {number} endTimeSeconds in seconds\n * @property {boolean} off is loop turned off\n * @property {declaration} code block event listener for loops\n */\n\nclass Loop {\n\n /**\n * class constructor\n * @param {string} id player/plyr/div id\n */\n\n constructor(id) {\n\n this.id = id;\n this._videoDuration = 1;\n\n // need initial value for arrow key <> addition of time on UI\n this._startTimeSeconds = 0;\n this._endTimeSeconds = 0;\n\n this.off = true;\n\n /// This event listener drives the looping, on timeupdate event from plyr\n\n // can try to update to something like // document.addEventListener('timeupdate', id, this.playSegment);\n\n\n document.addEventListener('timeupdate', window.PMpageSupport.helpers.delegateByIDparams(this.id, this.startTimeSeconds, this.endTimeSeconds, this.playSegment));\n\n\n \n\n }\n\n\n /**\n * for precision of loops all time values will be seconds * 10000 (times ten thousand)\n */\n set startTimeSeconds(secs) {\n this._startTimeSeconds = secs * 10000;\n }\n /**\n * for precision of loops all time values will be seconds * 10000 (times ten thousand)\n */\n get startTimeSeconds() {\n return this._startTimeSeconds;\n }\n /**\n * for precision of loops all time values will be seconds * 10000 (times ten thousand)\n */\n set endTimeSeconds(secs) {\n this._endTimeSeconds = secs * 10000;\n }\n /**\n * for precision of loops all time values will be seconds * 10000 (times ten thousand)\n */\n get endTimeSeconds() {\n return this._endTimeSeconds;\n }\n /**\n * for precision of loops all time values will be seconds * 10000 (times ten thousand)\n */\n set videoDuration(secs) {\n this._videoDuration = secs * 10000;\n }\n /**\n * for precision of loops all time values will be seconds * 10000 (times ten thousand)\n */\n get videoDuration() {\n return this._videoDuration;\n }\n\n\n\n /**\n * plays a loop\n */\n\n playSegment() {\n\n // not sure of the reason for this empty string check. Think it's about not picking up the events from non practisemaster Plyr videos on the page\n\n if (this.id !== \"\") {\n\n // if Loop not switched offF\n\n if (!window[\"PMinstance_\" + this.id].loop.off) {\n\n\n // control time of chapter\n\n var currentTime = window[\"PMinstance_\" + this.id].plyrInstance.currentTime * 10000;\n\n if (currentTime < window[\"PMinstance_\" + this.id].loop.startTimeSeconds || window[\"PMinstance_\" + this.id].loop.endTimeSeconds < currentTime) {\n\n window[\"PMinstance_\" + this.id].plyrInstance.currentTime = window[\"PMinstance_\" + this.id].loop.startTimeSeconds / 10000;\n\n console.log('reset video to start : ' + window[\"PMinstance_\" + this.id].loop.startTimeSeconds / 10000);\n\n console.log('Player ' + this.id + ' has looped, current time: ' + currentTime + ' , end time: ' + window[\"PMinstance_\" + this.id].loop.endTimeSeconds);\n }\n\n }\n\n }\n\n }\n\n}\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Loop);\n\n//# sourceURL=webpack://practisemaster/./src/modules/loop-pm.js?");
173
173
 
174
174
  /***/ }),
175
175
 
@@ -180,7 +180,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
180
180
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
181
181
 
182
182
  "use strict";
183
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _help1_0digit7_png__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../help1.0digit7.png */ \"./src/help1.0digit7.png\");\n/* harmony import */ var _red_png__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../red.png */ \"./src/red.png\");\n/* harmony import */ var _PM_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../PM.css */ \"./src/PM.css\");\n/* harmony import */ var _helpers_pm__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./helpers-pm */ \"./src/modules/helpers-pm.js\");\n/* harmony import */ var _hostSite_pm__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./hostSite-pm */ \"./src/modules/hostSite-pm.js\");\n/* harmony import */ var _userRequest_pm__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./userRequest-pm */ \"./src/modules/userRequest-pm.js\");\n/**\n * module that provides the PageSupport Class\n * @module PageSupport Module\n * @requires HelpImage png\n * @requires RedImage png\n * @requires CSS PM.css\n * @requires Helpers Module\n * @requires HostSite Module\n * @requires UserRequest Module\n * \n */\n\n\n\n\n\n\n\n\n\n\n\n/**\n * This class is for assets that appear once on each page, independant from the number of videos\n * @class PageSupport\n * @property {object} cssOpts object passed in PM constructor\n * @property {HostSite} HostSite Module\n * @property {Helpers} Helpers Module\n * @property {PlyrInstance} that should be paused for modal\n * @property {UserRequest} UserRequest Module\n * \n */\n\nclass PageSupport {\n\n /**\n * class constructor\n * @param {object} cssOpts passed in from PM\n */\n\n constructor() {\n\n // css options ex. for WordPress\n // this.cssOpts = cssOpts;\n\n // injected properties\n this.hostSite = new _hostSite_pm__WEBPACK_IMPORTED_MODULE_4__[\"default\"]();\n this.helpers = new _helpers_pm__WEBPACK_IMPORTED_MODULE_3__[\"default\"]();\n\n // properties\n this.PMvideoToPauseModal;\n\n // init methods\n\n // first help host site and check that all pm class elements\n // have an id if not, create one for them\n\n this.pmClassElements = document.getElementsByClassName(\"pm\");\n\n this.checkIds();\n\n // this.checkContainer();\n\n this.placeInfoModal();\n\n this.pageEventsModal();\n\n\n this.userRequest = new _userRequest_pm__WEBPACK_IMPORTED_MODULE_5__[\"default\"]();\n\n // isSafari will be the same for all players on page\n // with multiple players\n\n this.isSafari = this.checkUserBrowserSafari();\n\n \n\n }\n\n // Class methods\n\n // these three checks will eventually need some type of validation\n // so a user doesn't add ex. static and button to pm div.\n\n /**\n * @returns boolean\n */\n checkUserBrowserSafari() {\n if (this.userRequest.browserDetected == 'Safari') {\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * currently unused\n */\n applyPageLoadCssHTMLSettings() {\n // user request / browser specific \n\n }\n\n\n\n /**\n * used (for links) to play loops, where the play starts and ends at a specific time\n * @param {string} id player/plyr/div id\n * @param {string|number} startTime \n * @param {string|number} endTime \n */\n\n PMloop(id, startTime, endTime) {\n\n // from the top\n // 0) prep a) turn chapter off\n\n window[\"PMinstance_\" + id].chapter.off = true;\n\n //1) convert user time into PM time == (decimal seconds*1000) a) string i) \"hh:mm:ss.uuu\" and truncations b) number i) seconds w & w/o decimal\n\n var startSeconds = this.helpers.secondsNumber(startTime);\n var endSeconds = this.helpers.secondsNumber(endTime);\n\n\n // 2) get loop for id in param and set the new loop values, turn loop on \n\n window[\"PMinstance_\" + id].loop.startTimeSeconds = startSeconds;\n window[\"PMinstance_\" + id].loop.endTimeSeconds = endSeconds;\n\n window[\"PMinstance_\" + id].loop.off = false;\n\n\n // 3) set up UI a) loop switch b) time inputs\n\n document.querySelector(\"#\" + id + \"_timeStart\").value = this.helpers.toStringTime(startSeconds);\n document.querySelector(\"#\" + id + \"_timeEnd\").value = this.helpers.toStringTime(endSeconds);\n\n document.querySelector(\"#\" + id + \"_onOff > input\").checked = true;\n\n // 4) get plyr playing (at correct time) so that it will loop\n\n window[\"PMinstance_\" + id].plyrInstance.play();\n\n window[\"PMinstance_\" + id].plyrInstance.currentTime = startSeconds;\n\n // report state\n console.log('Looping :' + id + ' from ' + startSeconds + ' to ' + endSeconds);\n\n }\n\n\n\n /**\n * used (for links) to create Chapters, where the play starts and ends at a specific time\n * a loop is also set up so that when a user wants to loop the chapter all they have to do is toggle on the \n * looper switch\n * @param {string} id \n * @param {string|number} startTime \n * @param {string|number} endTime \n */\n\n PMchapter(id, startTime, endTime) {\n\n \n\n // update loop, turn it off and gui switch\n window[\"PMinstance_\" + id].loop.off = true;\n\n\n document.querySelector(\"#\" + id + \"_onOff > input\").checked = false;\n\n\n\n let st = this.helpers.secondsNumber(startTime);\n\n\n let et = this.helpers.secondsNumber(endTime);\n\n\n // update the instance chapter\n window[\"PMinstance_\" + id].chapter.off = false;\n\n\n window[\"PMinstance_\" + id].chapter.startTimeSeconds = st;\n\n\n window[\"PMinstance_\" + id].chapter.endTimeSeconds = et;\n\n\n // update UI\n\n document.querySelector(\"#\" + id + \"_timeStart\").value = this.helpers.toStringTime(st);\n\n\n document.querySelector(\"#\" + id + \"_timeEnd\").value = this.helpers.toStringTime(et);\n\n\n // must play bfore setting current time !!\n window[\"PMinstance_\" + id].plyrInstance.play();\n\n\n window[\"PMinstance_\" + id].plyrInstance.currentTime = st;\n\n }\n\n\n\n /**\n * adds an ID to PM class element, if id is not there.\n */\n\n checkIds() {\n\n // tidy up of video divs and container divs for user\n Array.from(this.pmClassElements).forEach(function (item) {\n\n // IDs: for each of the pm class videos, check for id and add if not present\n\n // generate 'random' name for .pm elements without ids\n const genRanHex = size => [...Array(size)].map(() => Math.floor(Math.random() * 16).toString(16)).join('');\n\n // check each for an id if element doesn't have an id then add a hex id\n item.id ? item.id : item.id = \"pm\" + genRanHex(3);\n\n });\n\n }\n\n\n\n /**\n * The outter .contianer Class is required for several plyr library functions.\n * This method guarantees the formatting of players so there is an outter container. Even for WordPress where there is more than one\n * div with class='container' (ex WP),\n * This method also adds a class PractiseMaster as the parent div for (videos, iframes or divs)\n */\n\n checkContainer() {\n\n Array.from(this.pmClassElements).forEach(function (item) {\n\n\n // logic: 1) if user has div container use it, add PractiseMaster class \n\n var parentNode = item.parentNode;\n\n if (parentNode.tagName == \"DIV\" && parentNode.classList.contains('container')) {\n\n // ( if PractiseMaster class is already there that's ok)\n\n parentNode.classList.add('PractiseMaster');\n\n }\n else {\n\n // wrap pre-player element with a div to become class='container PractiseMaster'\n\n // create wrapper container\n var wrapper = document.createElement('div');\n wrapper.classList.add(\"container\");\n wrapper.classList.add(\"PractiseMaster\");\n\n // insert wrapper before el in the DOM tree\n item.parentNode.insertBefore(wrapper, item);\n\n // move el into wrapper\n wrapper.appendChild(item);\n\n }\n\n });\n\n }\n\n\n\n /**\n * places help modal on page and it's button listeners\n */\n\n placeInfoModal() {\n\n // Modal pauses and plays video\n // reference to video is a global called window.PMvideoToPauseModal \n\n // modal div\n\n var divModal = document.createElement(\"div\");\n divModal.id = \"myModal\";\n divModal.classList.add(\"modal\");\n\n\n // modal test content => put photo on js cdn!\n\n\n // Modal Content\n divModal.innerHTML = `<div class=\"modal-content\" style= \"max-width: 700px;\">\n <span id=\"closeModal\" class=\"close\">&times;</span>\n <div style=\"float: left;\"> &#9612; &#9612; Video Paused</div> <br><br>\n <h2>PractiseMaster&trade; Looper</h2>\n <div>Allows you to continuously repeat any section of lesson material.\n <br>\n <br>\n <div> To set your own loops:</div>\n <ol><li>Hit the play button </li><li> Set start time on the left time field, set the end time on the right field </li><li>Turn on PractiseMaster using switch in the lower right corner.</li></div>\n <br>\n <div>Time is displayed \"minutes: seconds. fraction of second\".</div>\n <br><br>\n <div> Or use the pre-set loops if given on the lesson, below the video.\n <br>\n <div id=\"howTo\"></div>\n <br>\n <br>\n <!-- <div id=\"yellow\">Yellow Warning! Start Time > End Time</div>\n <br> \n <br> -->\n <div id=\"red\">The PractiseMaster won't function and will turn red when the start time is later than the end time.</div>\n \n <br><br>\n <div id=\"modalFinePrint\"><a href=\"http://practisemaster.com\" target=\"_blank\">Practice Master</a> is developed by Learnsense LTD.</div>`;\n\n\n var divModalContent = document.createElement(\"p\");\n\n divModalContent.id = \"modalContent\";\n\n divModalContent.innerHTML = '<p>';\n\n\n divModal.appendChild(divModalContent);\n\n\n document.querySelector(\"body\").appendChild(divModal);\n\n\n // Modal Image Help\n\n const helpImage = new Image();\n helpImage.src = _help1_0digit7_png__WEBPACK_IMPORTED_MODULE_0__;\n helpImage.style.width = \"100%\";\n\n document.querySelector(\"#howTo\").appendChild(helpImage);\n\n\n\n\n // Modal Image Red Warning\n\n const redImage = new Image();\n redImage.src = _red_png__WEBPACK_IMPORTED_MODULE_1__;\n redImage.style.width = \"100%\";\n\n document.querySelector(\"#red\").appendChild(redImage);\n\n\n console.log(\"modal should be on dom!\");\n\n }\n\n\n\n /**\n * modal close event listener\n * @listens document click\n */\n \n pageEventsModal() {\n\n // modal close event on 'document' because of injected element\n\n document.addEventListener('click', function (e) {\n\n if (e.target && e.target.id === 'closeModal') {\n\n console.log('time to close modal');\n\n document.querySelector(\"#myModal\").style.display = \"none\";\n\n // Jason says not to play video after modal close\n // window.PMvideoToPauseModal.play();\n }\n\n });\n\n\n //add event listener: click outside modal, close modal\n\n window.onclick = function (event) {\n\n if (event.target.id === 'myModal') {\n document.querySelector(\"#myModal\").style.display = \"none\";\n\n // Jason says not to play video after modal close\n // window.PMvideoToPauseModal.play();\n }\n\n }\n\n document.addEventListener('click', function (e) {\n\n if (e.target && e.target.classList.contains('infoButton')) {\n // pause video play\n\n // global so that it can be called without an id when closing modal\n window.PMvideoToPauseModal = window[\"PMinstance_\" + e.target.id.split(\"_\")[0]].plyrInstance;\n // pause video when modal opens\n window.PMvideoToPauseModal.pause();\n\n document.querySelector(\"#myModal\").style.display = \"block\";\n\n }\n\n });\n\n }\n\n}\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PageSupport);\n\n//# sourceURL=webpack://practisemaster/./src/modules/pageSupport-pm.js?");
183
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _help1_0digit7_png__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../help1.0digit7.png */ \"./src/help1.0digit7.png\");\n/* harmony import */ var _red_png__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../red.png */ \"./src/red.png\");\n/* harmony import */ var _PM_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../PM.css */ \"./src/PM.css\");\n/* harmony import */ var _helpers_pm__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./helpers-pm */ \"./src/modules/helpers-pm.js\");\n/* harmony import */ var _hostSite_pm__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./hostSite-pm */ \"./src/modules/hostSite-pm.js\");\n/* harmony import */ var _userRequest_pm__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./userRequest-pm */ \"./src/modules/userRequest-pm.js\");\n/**\n * module that provides the PageSupport Class\n * @module PageSupport Module\n * @requires HelpImage png\n * @requires RedImage png\n * @requires CSS PM.css\n * @requires Helpers Module\n * @requires HostSite Module\n * @requires UserRequest Module\n * \n */\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * This class is for assets that appear once on each page, independant from the number of videos\n * @class PageSupport\n * @property {object} cssOpts object passed in PM constructor\n * @property {HostSite} HostSite Module\n * @property {Helpers} Helpers Module\n * @property {PlyrInstance} that should be paused for modal\n * @property {UserRequest} UserRequest Module\n * \n */\n\nclass PageSupport {\n\n /**\n * class constructor\n * @param {object} cssOpts passed in from PM\n */\n\n constructor() {\n\n // css options ex. for WordPress\n // this.cssOpts = cssOpts;\n\n // injected properties\n this.hostSite = new _hostSite_pm__WEBPACK_IMPORTED_MODULE_4__[\"default\"]();\n this.helpers = new _helpers_pm__WEBPACK_IMPORTED_MODULE_3__[\"default\"]();\n\n // properties\n this.PMvideoToPauseModal;\n\n // init methods\n\n // first help host site and check that all pm class elements\n // have an id if not, create one for them\n\n this.pmClassElements = document.getElementsByClassName(\"pm\");\n\n this.checkIds();\n\n // this.checkContainer();\n\n this.placeInfoModal();\n\n this.pageEventsModal();\n\n\n this.userRequest = new _userRequest_pm__WEBPACK_IMPORTED_MODULE_5__[\"default\"]();\n\n // isSafari will be the same for all players on page\n // with multiple players\n\n this.isSafari = this.checkUserBrowserSafari();\n\n \n \n\n }\n\n // Class methods\n\n // these three checks will eventually need some type of validation\n // so a user doesn't add ex. static and button to pm div.\n\n /**\n * @returns boolean\n */\n checkUserBrowserSafari() {\n if (this.userRequest.browserDetected == 'Safari') {\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * currently unused\n */\n applyPageLoadCssHTMLSettings() {\n // user request / browser specific \n\n }\n\n\n\n /**\n * used (for links) to play loops, where the play starts and ends at a specific time\n * @param {string} id player/plyr/div id\n * @param {string|number} startTime \n * @param {string|number} endTime \n */\n\n PMloop(id, startTime, endTime) {\n\n\n // from the top\n // 0) prep a) turn chapter off\n\n window[\"PMinstance_\" + id].chapter.off = true;\n\n //1) convert user time into PM time == (decimal seconds*1000) a) string i) \"hh:mm:ss.uuu\" and truncations b) number i) seconds w & w/o decimal\n\n var startSeconds = this.helpers.secondsNumber(startTime);\n var endSeconds = this.helpers.secondsNumber(endTime);\n\n\n // 2) get loop for id in param and set the new loop values, turn loop on \n\n window[\"PMinstance_\" + id].loop.startTimeSeconds = startSeconds;\n window[\"PMinstance_\" + id].loop.endTimeSeconds = endSeconds;\n\n window[\"PMinstance_\" + id].loop.off = false;\n\n\n // 3) set up UI a) loop switch b) time inputs\n\n document.querySelector(\"#\" + id + \"_timeStart\").value = this.helpers.toStringTime(startSeconds);\n document.querySelector(\"#\" + id + \"_timeEnd\").value = this.helpers.toStringTime(endSeconds);\n\n document.querySelector(\"#\" + id + \"_onOff > input\").checked = true;\n\n // 4) get plyr playing (at correct time) so that it will loop\n\n window[\"PMinstance_\" + id].plyrInstance.play();\n\n window[\"PMinstance_\" + id].plyrInstance.currentTime = startSeconds;\n\n // report state\n console.log('Looping :' + id + ' from ' + startSeconds + ' to ' + endSeconds);\n\n }\n\n\n\n /**\n * used (for links) to create Chapters, where the play starts and ends at a specific time\n * a loop is also set up so that when a user wants to loop the chapter all they have to do is toggle on the \n * looper switch\n * @param {string} id \n * @param {string|number} startTime \n * @param {string|number} endTime \n */\n\n PMchapter(id, startTime, endTime) {\n\n \n\n // update loop, turn it off and gui switch\n window[\"PMinstance_\" + id].loop.off = true;\n\n\n document.querySelector(\"#\" + id + \"_onOff > input\").checked = false;\n\n\n\n let st = this.helpers.secondsNumber(startTime);\n\n\n let et = this.helpers.secondsNumber(endTime);\n\n\n // update the instance chapter\n window[\"PMinstance_\" + id].chapter.off = false;\n\n\n window[\"PMinstance_\" + id].chapter.startTimeSeconds = st;\n\n\n window[\"PMinstance_\" + id].chapter.endTimeSeconds = et;\n\n\n // update UI\n\n document.querySelector(\"#\" + id + \"_timeStart\").value = this.helpers.toStringTime(st);\n\n\n document.querySelector(\"#\" + id + \"_timeEnd\").value = this.helpers.toStringTime(et);\n\n\n // must play bfore setting current time !!\n window[\"PMinstance_\" + id].plyrInstance.play();\n\n\n window[\"PMinstance_\" + id].plyrInstance.currentTime = st;\n\n }\n\n\n\n /**\n * adds an ID to PM class element, if id is not there.\n */\n\n checkIds() {\n\n // tidy up of video divs and container divs for user\n Array.from(this.pmClassElements).forEach(function (item) {\n\n // IDs: for each of the pm class videos, check for id and add if not present\n\n // generate 'random' name for .pm elements without ids\n const genRanHex = size => [...Array(size)].map(() => Math.floor(Math.random() * 16).toString(16)).join('');\n\n // check each for an id if element doesn't have an id then add a hex id\n item.id ? item.id : item.id = \"pm\" + genRanHex(3);\n\n });\n\n }\n\n\n\n /**\n * The outter .contianer Class is required for several plyr library functions.\n * This method guarantees the formatting of players so there is an outter container. Even for WordPress where there is more than one\n * div with class='container' (ex WP),\n * This method also adds a class PractiseMaster as the parent div for (videos, iframes or divs)\n */\n\n checkContainer() {\n\n Array.from(this.pmClassElements).forEach(function (item) {\n\n\n // logic: 1) if user has div container use it, add PractiseMaster class \n\n var parentNode = item.parentNode;\n\n if (parentNode.tagName == \"DIV\" && parentNode.classList.contains('container')) {\n\n // ( if PractiseMaster class is already there that's ok)\n\n parentNode.classList.add('PractiseMaster');\n\n }\n else {\n\n // wrap pre-player element with a div to become class='container PractiseMaster'\n\n // create wrapper container\n var wrapper = document.createElement('div');\n wrapper.classList.add(\"container\");\n wrapper.classList.add(\"PractiseMaster\");\n\n // insert wrapper before el in the DOM tree\n item.parentNode.insertBefore(wrapper, item);\n\n // move el into wrapper\n wrapper.appendChild(item);\n\n }\n\n });\n\n }\n\n\n\n /**\n * places help modal on page and it's button listeners\n */\n\n placeInfoModal() {\n\n // Modal pauses and plays video\n // reference to video is a global called window.PMvideoToPauseModal \n\n // modal div\n\n var divModal = document.createElement(\"div\");\n divModal.id = \"myModal\";\n divModal.classList.add(\"modal\");\n\n\n // modal test content => put photo on js cdn!\n\n\n // Modal Content\n divModal.innerHTML = `<div class=\"modal-content\" style= \"max-width: 700px;\">\n <span id=\"closeModal\" class=\"close\">&times;</span>\n <div style=\"float: left;\"> &#9612; &#9612; Video Paused</div> <br><br>\n <h2>PractiseMaster&trade; Looper</h2>\n <div>Allows you to continuously repeat any section of lesson material.\n <br>\n <br>\n <div> To set your own loops:</div>\n <ol><li>Hit the play button </li><li> Set start time on the left time field, set the end time on the right field </li><li>Turn on PractiseMaster using switch in the lower right corner.</li></div>\n <br>\n <div>Time is displayed \"minutes: seconds. fraction of second\".</div>\n <br><br>\n <div> Or use the pre-set loops if given on the lesson, below the video.\n <br>\n <div id=\"howTo\"></div>\n <br>\n <br>\n <!-- <div id=\"yellow\">Yellow Warning! Start Time > End Time</div>\n <br> \n <br> -->\n <div id=\"red\">The PractiseMaster won't function and will turn red when the start time is later than the end time.</div>\n \n <br><br>\n <div id=\"modalFinePrint\"><a href=\"http://practisemaster.com\" target=\"_blank\">Practice Master</a> is developed by Learnsense LTD.</div>`;\n\n\n var divModalContent = document.createElement(\"p\");\n\n divModalContent.id = \"modalContent\";\n\n divModalContent.innerHTML = '<p>';\n\n\n divModal.appendChild(divModalContent);\n\n\n document.querySelector(\"body\").appendChild(divModal);\n\n\n // Modal Image Help\n\n const helpImage = new Image();\n helpImage.src = _help1_0digit7_png__WEBPACK_IMPORTED_MODULE_0__;\n helpImage.style.width = \"100%\";\n\n document.querySelector(\"#howTo\").appendChild(helpImage);\n\n\n\n\n // Modal Image Red Warning\n\n const redImage = new Image();\n redImage.src = _red_png__WEBPACK_IMPORTED_MODULE_1__;\n redImage.style.width = \"100%\";\n\n document.querySelector(\"#red\").appendChild(redImage);\n\n\n console.log(\"modal should be on dom!\");\n\n }\n\n\n\n /**\n * modal close event listener\n * @listens document click\n */\n \n pageEventsModal() {\n\n // modal close event on 'document' because of injected element\n\n document.addEventListener('click', function (e) {\n\n if (e.target && e.target.id === 'closeModal') {\n\n console.log('time to close modal');\n\n document.querySelector(\"#myModal\").style.display = \"none\";\n\n // Jason says not to play video after modal close\n // window.PMvideoToPauseModal.play();\n }\n\n });\n\n\n //add event listener: click outside modal, close modal\n\n window.onclick = function (event) {\n\n if (event.target.id === 'myModal') {\n document.querySelector(\"#myModal\").style.display = \"none\";\n\n // Jason says not to play video after modal close\n // window.PMvideoToPauseModal.play();\n }\n\n }\n\n document.addEventListener('click', function (e) {\n\n if (e.target && e.target.classList.contains('infoButton')) {\n // pause video play\n\n // global so that it can be called without an id when closing modal\n window.PMvideoToPauseModal = window[\"PMinstance_\" + e.target.id.split(\"_\")[0]].plyrInstance;\n // pause video when modal opens\n window.PMvideoToPauseModal.pause();\n\n document.querySelector(\"#myModal\").style.display = \"block\";\n\n }\n\n });\n\n }\n\n}\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PageSupport);\n\n//# sourceURL=webpack://practisemaster/./src/modules/pageSupport-pm.js?");
184
184
 
185
185
  /***/ }),
186
186
 
@@ -191,7 +191,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
191
191
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
192
192
 
193
193
  "use strict";
194
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var plyr__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! plyr */ \"./node_modules/plyr/dist/plyr.min.js\");\n/* harmony import */ var plyr__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(plyr__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var plyr_dist_plyr_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! plyr/dist/plyr.css */ \"./node_modules/plyr/dist/plyr.css\");\n/* harmony import */ var _loop_pm__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./loop-pm */ \"./src/modules/loop-pm.js\");\n/* harmony import */ var _chapter_pm__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./chapter-pm */ \"./src/modules/chapter-pm.js\");\n/* harmony import */ var _UIprep_pm__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./UIprep-pm */ \"./src/modules/UIprep-pm.js\");\n/**\n * an instance of Player is used for each video on the DOM\n * the Player class manages Plyr, Loop, Chapter, HTML and events.\n * the plyr ready event listener instantiats a global window[\"PMinstance_\" + id] that is used by loop and chapter CSS classes\n * that are injected later\n * @module Player Module\n * @requires Plyr Module\n * @requires Plyr CSS\n * @requires Loop Module\n * @requires Chapter Module\n * @requires UIprep Module\n */\n\n\n\n\n\n\n\n\n\n\n\n/**\n * adds PractiseMaster looping and chapter controls to Plyr\n * @class Player\n * @property {string} id from element\n * @property {class} plyrInstance from plyr module\n * @property {boolean} isStatic as marked by user\n * @property {obsolete} CSSclasses refactor to classList if possible and remove (used once)\n * @property {classlist} classList\n * @property {declaration} code block sets isStatic for given conditions\n * @property {declaration} code block creates audio or video plyr for given properties\n * @property {class} uiPrep a new uiPrep class\n * @property {class} loop a Loop class instance\n * @property {class} chapter a Chapter class instance\n * @property {method} addPMReadyListeners adds any listeners required (ex PMready)\n * \n * \n */\nclass Player {\n\n /**\n * class constructor\n * @param {element} el div with pm class and plyr data requirements \n */\n constructor(el) {\n\n this.id = el.id;\n\n this.plyrInstance;\n\n // note static is set when Plyr is instantiated\n // otherwise this would be in UIprep\n // can toggleControls vis/no vis while playing but not set property\n\n this.isStatic;\n\n // class list for element, CSSclasses added back after player created\n\n this.CSSclasses = el.className.split(' ');\n\n this.classList = el.classList;\n\n // classlist check for static (user implemented)\n\n if (el.classList.contains('static') || el.classList.contains('offScreen') || window.PractiseMaster.PageSupport.isSafari || el.classList.contains('links')) {\n\n this.isStatic = true; // create plyr with static controls\n\n } else {\n // create plyr with hover controls\n this.isStatic = false;\n }\n\n\n if (el.tagName === 'AUDIO') {\n\n this.newPlyrAudio(el);\n\n }\n else {\n\n this.newPlyrVideo(el);\n\n }\n\n\n this.uiPrep = new _UIprep_pm__WEBPACK_IMPORTED_MODULE_4__[\"default\"](el);\n\n this.loop;\n\n this.chapter;\n\n // this will fire after everything to set any universal style\n\n this.addPMReadyListeners();\n\n\n\n }\n\n\n\n /**\n * creates a new video Plyr with the pm element\n * @param {element} el - div with pm class \n */\n\n newPlyrVideo(el) {\n\n this.plyrInstance = new (plyr__WEBPACK_IMPORTED_MODULE_0___default())('#' + el.id, {\n controls: [\n 'play', // Play/pause playback\n 'progress', // The progress bar and scrubber for playback and buffering\n 'current-time', // The current time of playback\n 'duration', // The full duration of the media\n 'mute', // Toggle mute\n 'volume', // Volume control\n 'settings', // Settings menu\n 'fullscreen', // Toggle fullscreen\n ],\n\n hideControls: !this.isStatic\n\n });\n\n this.setVideoListeners(el.id);\n\n this.eventListeners();\n\n }\n\n\n\n /**\n * creates a new audio Plyr with the pm element\n * @param {element} el - div with pm class \n */\n\n newPlyrAudio(el) {\n\n this.plyrInstance = new (plyr__WEBPACK_IMPORTED_MODULE_0___default())('audio#' + el.id, {});\n\n this.setAudioListeners(el.id)\n\n this.eventListeners();\n\n }\n\n\n\n /**\n * called from the plyr ready event listener, this method places the HTML controls on the video player\n * @param {string} id player/plyr/div id\n * @emits {event} called 'pmControlsReady'\n */\n\n HTMLControls(id) {\n\n var loopDivsLiteral = `\n <div style=\"flex-basis: 100%; height: 0;\"></div>\n <div style=\"flex-grow: 0.25;\"></div>\n <button id=\"${this.id}_info\" class=\"infoButton plyr__controls__item plyr__control\" type=\"button\">\n <svg id=\"infoSVG\" class=\"icon--not-pressed\" aria-hidden=\"true\" focusable=\"false\" viewBox=\"0 0 18 18\" >\n <path xmlns=\"http://www.w3.org/2000/svg\" d=\"m9.0598 0.42333c-4.9453 0-8.9522 3.8514-8.9522 8.6049 0 4.7535 4.0068 8.6049 8.9522 8.6049 4.9453 0 8.9522-3.8514 8.9522-8.6049 0-4.7535-4.0068-8.6049-8.9522-8.6049zm0 15.544c-3.9924 0-7.2195-3.1019-7.2195-6.9394 0-3.8306 3.2271-6.9394 7.2195-6.9394 3.9852 0 7.2195 3.1019 7.2195 6.9394 0 3.8375-3.2271 6.9394-7.2195 6.9394zm0-11.728c0.83746 0 1.5161 0.65231 1.5161 1.4573 0 0.80498-0.67863 1.4573-1.5161 1.4573-0.83746 0-1.5161-0.65231-1.5161-1.4573 0-0.80498 0.67863-1.4573 1.5161-1.4573zm2.0215 8.8131c0 0.229-0.19493 0.41637-0.43317 0.41637h-3.1766c-0.23824 0-0.43317-0.18736-0.43317-0.41637v-0.83273c0-0.229 0.19493-0.41637 0.43317-0.41637h0.43317v-2.2206h-0.43317c-0.23824 0-0.43317-0.18736-0.43317-0.41637v-0.83273c0-0.229 0.19493-0.41637 0.43317-0.41637h2.3102c0.23824 0 0.43317 0.18737 0.43317 0.41637v3.4697h0.43317c0.23824 0 0.43317 0.18736 0.43317 0.41637z\"/>\n </svg>\n <span class=\"label--not-pressed plyr__sr-only\">Info</span>\n </button>\n <span class=\"PMlogo\" style=\"font-style: italic; font-size: smaller; line-height: 12px;\">Practise<br>Master</span>\n <div style=\"flex-grow: 1;\"></div>\n <button id=\"${this.id}_nowTimeStart\" class=\"plyr__controls__item plyr__control\" type=\"button\">\n <svg id=\"nowSVG\" class=\"icon--not-pressed\" aria-hidden=\"true\" focusable=\"false\" viewBox=\"0 0 18 18\" style=\"transform: scaleY(-1)\" >\n <path xmlns=\"http://www.w3.org/2000/svg\" d=\"m13.83 0.12947c-0.60243 0.001022-0.93199 0.76661-1.3344 1.2481-0.42034 0.6401-0.18152 1.5806 0.28874 2.0369 0.40781 0.38221 0.08162 0.35863-0.24583 0.33434-3.3737 0.011276-6.7487-0.022766-10.121 0.017257-1.3482 0.13812-2.4025 1.9022-2.2584 3.6894 0.006509 2.7641-0.011751 4.6472 0.01577 7.4105 0.10198 1.8037 1.4251 3.1952 2.7541 3.0023 2.1542-0.01129 3.1065 0.02276 5.26-0.01727 1.3476-0.13717 2.3846-1.9108 2.2409-3.6895-0.01218-1.3917 0.02481-2.7875-0.01954-4.1765-0.096853-0.79696-0.72647-1.1446-1.2687-1.0422-0.527-0.049194-1.1834 0.011045-1.4058 0.78294-0.16627 0.81285-0.048406 1.6792-0.083807 2.5159v1.9074h-4.7123c0.0021-2.5223-0.00462-4.1591-0.00294-6.6814h10.095c-0.3871 0.56351-1.025 1.085-0.87246 1.9767 0.12204 0.66517 0.59476 1.0425 0.92175 1.5235 0.48086 0.55576 1.1804 0.23938 1.5247-0.38686 1.0531-1.4245 2.1432-2.8048 3.1729-4.2573 0.34907-0.65253 0.093278-1.5004-0.34614-1.9384-1.0264-1.3413-2.0186-2.7349-3.0667-4.0431-0.15772-0.13891-0.34622-0.21302-0.53492-0.21263z\" style=\"stroke-width:.014514\"/>\n </svg>\n <span class=\"label--pressed plyr__sr-only\">Text for Label</span>\n <span class=\"label--not-pressed plyr__sr-only\">Text for Label</span>\n </button>\n <button id=\"${this.id}_subtrTimeStart\" class=\"plyr__controls__item plyr__control\" type=\"button\">\n <svg id=\"cheveronSVG\" class=\"icon--not-pressed\" aria-hidden=\"true\" focusable=\"false\" viewBox=\"0 0 18 18\" style=\"transform: scaleX(-1)\" >\n <g xmlns=\"http://www.w3.org/2000/svg\" transform=\"matrix(.036353 0 0 .036621 -3.4195 .1145)\" style=\"stroke-width:7.2515\"><g style=\"stroke-width:7.2515\"><g style=\"stroke-width:7.2515\"><path d=\"m382.68 226.8c-73.671-73.548-147.1-147.35-220.92-220.74-12.991-11.358-32.333-5.3965-41.748 7.4512-10.355 9.4864-22.632 21.691-17.227 37.166 6.041 14.425 20.131 23.247 30.207 34.805 53.47 53.47 106.94 106.94 160.41 160.41-61.919 62.042-124.09 123.84-185.85 186.04-11.359 12.99-5.3968 32.335 7.4522 41.748 9.5221 10.409 21.812 22.708 37.35 17.168 14.308-6.1241 23.115-20.108 34.623-30.154 65.802-65.925 131.86-131.6 197.5-197.68 8.6934-10.271 7.9092-26.86-1.7952-36.212z\" style=\"stroke-width:7.2515\"/></g></g></g>\n </svg>\n <span class=\"label--pressed plyr__sr-only\">Text for Label</span>\n <span class=\"label--not-pressed plyr__sr-only\">Text for Label</span>\n </button>\n <input-duration id=\"${this.id}_timeStart\"></input-duration>\n <button id=\"${this.id}_addTimeStart\" class=\"plyr__controls__item plyr__control\" type=\"button\">\n <svg id=\"cheveronRevSVG\" class=\"icon--not-pressed\" aria-hidden=\"true\" focusable=\"false\" viewBox=\"0 0 18 18\">\n <use xlink:href=\"#cheveronSVG\" />\n </svg>\n <span class=\"label--pressed plyr__sr-only\">Text for Label</span>\n <span class=\"label--not-pressed plyr__sr-only\">Text for Label</span>\n </button>\n <div style=\"flex-grow: 1;\"></div>\n <button id=\"${this.id}_nowTimeEnd\" class=\"plyr__controls__item plyr__control\" type=\"button\">\n <svg id=\"pointSVG\" class=\"icon--not-pressed\" aria-hidden=\"true\" focusable=\"false\" viewBox=\"0 0 18 18\" style=\"transform: scale(-1, -1)\" >\n <path xmlns=\"http://www.w3.org/2000/svg\" d=\"m13.83 0.12947c-0.60243 0.001022-0.93199 0.76661-1.3344 1.2481-0.42034 0.6401-0.18152 1.5806 0.28874 2.0369 0.40781 0.38221 0.08162 0.35863-0.24583 0.33434-3.3737 0.011276-6.7487-0.022766-10.121 0.017257-1.3482 0.13812-2.4025 1.9022-2.2584 3.6894 0.006509 2.7641-0.011751 4.6472 0.01577 7.4105 0.10198 1.8037 1.4251 3.1952 2.7541 3.0023 2.1542-0.01129 3.1065 0.02276 5.26-0.01727 1.3476-0.13717 2.3846-1.9108 2.2409-3.6895-0.01218-1.3917 0.02481-2.7875-0.01954-4.1765-0.096853-0.79696-0.72647-1.1446-1.2687-1.0422-0.527-0.049194-1.1834 0.011045-1.4058 0.78294-0.16627 0.81285-0.048406 1.6792-0.083807 2.5159v1.9074h-4.7123c0.0021-2.5223-0.00462-4.1591-0.00294-6.6814h10.095c-0.3871 0.56351-1.025 1.085-0.87246 1.9767 0.12204 0.66517 0.59476 1.0425 0.92175 1.5235 0.48086 0.55576 1.1804 0.23938 1.5247-0.38686 1.0531-1.4245 2.1432-2.8048 3.1729-4.2573 0.34907-0.65253 0.093278-1.5004-0.34614-1.9384-1.0264-1.3413-2.0186-2.7349-3.0667-4.0431-0.15772-0.13891-0.34622-0.21302-0.53492-0.21263z\" style=\"stroke-width:.014514\"/>\n </svg>\n <span class=\"label--pressed plyr__sr-only\">Text for Label</span>\n <span class=\"label--not-pressed plyr__sr-only\">Text for Label</span>\n </button>\n <button id=\"${this.id}_subtrTimeEnd\" class=\"plyr__controls__item plyr__control\" type=\"button\">\n <svg class=\"icon--not-pressed\" aria-hidden=\"true\" focusable=\"false\" viewBox=\"0 0 18 18\" style=\"transform: scaleX(-1)\" >\n <use xlink:href=\"#cheveronSVG\" />\n </svg>\n <span class=\"label--pressed plyr__sr-only\">Text for Label</span>\n <span class=\"label--not-pressed plyr__sr-only\">Text for Label</span>\n </button>\n <input-duration id=\"${this.id}_timeEnd\"></input-duration>\n <button id=\"${this.id}_addTimeEnd\" class=\"plyr__controls__item plyr__control\" type=\"button\">\n <svg class=\"icon--not-pressed\" aria-hidden=\"true\" focusable=\"false\" viewBox=\"0 0 18 18\">\n <use xlink:href=\"#cheveronSVG\" />\n </svg>\n <span class=\"label--pressed plyr__sr-only\">Text for Label</span>\n <span class=\"label--not-pressed plyr__sr-only\">Text for Label</span>\n </button>\n <div style=\"flex-grow: 2;\"></div>\n <div id=\"${this.id}_onOff\" class=\"onoffswitch onoffDiv\">\n <input type=\"checkbox\" name=\"onoffswitch\" class=\"onoffswitch-checkbox\" tabindex=\"0\">\n <label class=\"onoffswitch-label\" for=\"myonoffswitch\">\n <span class=\"onoffswitch-inner\"></span>\n <span class=\"onoffswitch-switch\"></span>\n </label>\n </div>\n <div style=\"flex-grow: 0.5;\"> &nbsp;</div>\n `;\n\n\n document.querySelector(\"#\" + id + \" > div.plyr__controls\").insertAdjacentHTML('beforeend', loopDivsLiteral);\n\n\n window.dispatchEvent(new CustomEvent('pmControlsReady', { detail: id }));\n\n }\n\n\n\n /**\n * this method places event listeners on page for PM controls buttons through a delegate in Helpers module \n */\n\n eventListeners() {\n\n // events these events need delegates to encapsulate id data as closures\n // https://stackoverflow.com/questions/46101024/add-event-listener-to-future-item-without-jquery\n\n // start time events \n\n document.addEventListener('click', window.PractiseMaster.PageSupport.helpers.delegate('#' + this.id + '_nowTimeStart', this.setTimeStart));\n\n document.addEventListener('click', window.PractiseMaster.PageSupport.helpers.delegate('#' + this.id + '_subtrTimeStart', this.subtrTimeStart));\n\n // event for input-duration \n document.addEventListener('keyup', window.PractiseMaster.PageSupport.helpers.delegate('#' + this.id + '_timeStart', this.timeStart));\n\n document.addEventListener('click', window.PractiseMaster.PageSupport.helpers.delegate('#' + this.id + '_addTimeStart', this.addTimeStart));\n\n\n // end time events (add return key for starting loop)\n\n document.addEventListener('click', window.PractiseMaster.PageSupport.helpers.delegate('#' + this.id + '_nowTimeEnd', this.setTimeEnd));\n\n document.addEventListener('click', window.PractiseMaster.PageSupport.helpers.delegate('#' + this.id + '_subtrTimeEnd', this.subtrTimeEnd));\n\n // event for input-duration\n document.addEventListener('keyup', window.PractiseMaster.PageSupport.helpers.delegate('#' + this.id + '_timeEnd', this.timeEnd));\n\n document.addEventListener('click', window.PractiseMaster.PageSupport.helpers.delegate('#' + this.id + '_addTimeEnd', this.addTimeEnd));\n\n // loop on / off button event\n\n document.addEventListener('click', window.PractiseMaster.PageSupport.helpers.delegate('#' + this.id + '_onOff', this.offToggle));\n\n\n // Loop and Chapter Link button event\n\n document.addEventListener('click', window.PractiseMaster.PageSupport.helpers.delegate('#' + this.id + '_links', this.linkLoopOrChapter));\n\n\n \n }\n\n\n // actual event listeners\n\n /**\n * event listener sets start time\n * @listens click event of *_nowTimeStart \n * @param {event} e unused\n */\n\n setTimeStart(e) {\n\n // 'this' is button so\n\n\n const id = this.id.replace('_nowTimeStart', '');\n\n\n\n console.log(\"Hey, I'll set the start time for player: \" + id);\n\n\n // Does: \n // set loop start\n\n const currentTime = window.PractiseMaster[\"PM_\" + id].plyrInstance.currentTime;\n window.PractiseMaster[\"PM_\" + id].loop.startTimeSeconds = currentTime;\n\n\n // trims string for mobile devices, where input time is updated to input string\n\n document.querySelector(\"#\" + id + \"_timeStart\").value = window.PractiseMaster.PageSupport.helpers.toStringTime(currentTime);\n\n\n // run warning validation\n\n window.PractiseMaster.PageSupport.helpers.redWarningValidation(id);\n\n }\n\n\n\n\n /**\n * event listener reduces start time\n * @listens click event of *_subtrTimeStart \n * @param {event} e unused\n */\n\n subtrTimeStart(e) {\n\n // 'this' is button so\n const id = this.id.replace('_subtrTimeStart', '');\n\n\n console.log(\"Hey, I'll subtract time start for player: \" + id);\n\n\n /// update loop object\n\n var inputTimeFloat = window.PractiseMaster[\"PM_\" + id].loop.startTimeSeconds / 10000 - 0.25 > 0 ? window.PractiseMaster[\"PM_\" + id].loop.startTimeSeconds / 10000 - 0.25 : 0;\n\n window.PractiseMaster[\"PM_\" + id].loop.startTimeSeconds = inputTimeFloat;\n\n\n /// video\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.pause();\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.currentTime = inputTimeFloat;\n\n\n\n document.querySelector(\"#\" + id + \"_timeStart\").value = window.PractiseMaster.PageSupport.helpers.toStringTime(inputTimeFloat);\n\n\n // run warning validation\n\n window.PractiseMaster.PageSupport.helpers.redWarningValidation(id);\n\n }\n\n\n\n /**\n * event listener increases start time\n * @listens click event of *_addTimeStart \n * @param {event} e unused\n */\n\n addTimeStart(e) {\n\n // 'this' is button so\n\n const id = this.id.replace('_addTimeStart', '');\n\n\n console.log(\"Hey, I'll add time end for player: \" + id);\n\n\n /// update loop object\n\n var inputTimeFloat = window.PractiseMaster[\"PM_\" + id].loop.startTimeSeconds / 10000 + 0.25;\n\n\n window.PractiseMaster[\"PM_\" + id].loop.startTimeSeconds = inputTimeFloat;\n\n\n /// video\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.pause();\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.currentTime = inputTimeFloat;\n\n\n document.querySelector(\"#\" + id + \"_timeStart\").value = window.PractiseMaster.PageSupport.helpers.toStringTime(inputTimeFloat);\n\n\n // run warning validation\n\n window.PractiseMaster.PageSupport.helpers.redWarningValidation(id);\n\n }\n\n\n\n\n /**\n * event listener for <input type=\"time\"> or chronlyHMS updating start time\n * @listens keyup event of *_timeStart\n * @param {e} event \n */\n\n timeStart(e) {\n\n // 'this' is button so\n\n const id = this.id.replace('_timeStart', '');\n\n console.log(\"Hey, I'll digit adjust the start time for player: \" + id);\n\n\n // update loop instance\n\n var startTimeString = this.value;\n\n\n // was toFloatSecs x2\n\n window.PractiseMaster[\"PM_\" + id].loop.startTimeSeconds = window.PractiseMaster.PageSupport.helpers.secondsNumber(startTimeString);\n\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.currentTime = window.PractiseMaster.PageSupport.helpers.secondsNumber(startTimeString);\n\n // run warning validation\n\n window.PractiseMaster.PageSupport.helpers.redWarningValidation(id);\n\n\n }\n\n\n\n /**\n * event listener sets end time\n * @listens click event of *_nowTimeEnd \n * @param {event} e unused\n */\n\n setTimeEnd(e) {\n\n // 'this' is button so\n\n const id = this.id.replace('_nowTimeEnd', '');\n\n\n console.log(\"Hey, I'll set the end time for player: \" + id);\n\n\n // get current time of plyr\n\n // set loop end\n\n var currentTime = window.PractiseMaster[\"PM_\" + id].plyrInstance.currentTime;\n\n\n window.PractiseMaster[\"PM_\" + id].loop.endTimeSeconds = currentTime;\n\n\n // trims string for mobile devices, where input time is updated to input string\n\n document.querySelector(\"#\" + id + \"_timeEnd\").value = window.PractiseMaster.PageSupport.helpers.toStringTime(currentTime);\n\n\n // run warning validation\n\n window.PractiseMaster.PageSupport.helpers.redWarningValidation(id);\n\n }\n\n\n\n\n /**\n * event listener reduces end time\n * @listens click event of *_subtrTimeEnd\n * @param {event} e unused\n */\n\n subtrTimeEnd(e) {\n\n // 'this' is button so\n\n const id = this.id.replace('_subtrTimeEnd', '');\n\n\n console.log(\"Hey, I'll subtract time end for player: \" + id);\n\n\n /// update loop object\n\n var inputTimeFloat = window.PractiseMaster[\"PM_\" + id].loop.endTimeSeconds / 10000 - 0.25 > 0 ? window.PractiseMaster[\"PM_\" + id].loop.endTimeSeconds / 10000 - 0.25 : 0;\n\n window.PractiseMaster[\"PM_\" + id].loop.endTimeSeconds = inputTimeFloat;\n\n\n /// video\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.pause();\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.currentTime = inputTimeFloat;\n\n\n // trims string for mobile devices, where input time is updated to input string\n document.querySelector(\"#\" + id + \"_timeEnd\").value = window.PractiseMaster.PageSupport.helpers.toStringTime(inputTimeFloat);\n\n\n // run warning validation\n\n window.PractiseMaster.PageSupport.helpers.redWarningValidation(id);\n\n }\n\n\n\n /**\n * event listener increases end time\n * @listens click event of *_addTimeEnd \n * @param {event} e unused\n */\n\n addTimeEnd(event) {\n\n // 'this' is button so\n\n const id = this.id.replace('_addTimeEnd', '');\n\n\n console.log(\"Hey, I'll add time end for player: \" + id);\n\n\n /// update loop object\n\n var inputTimeFloat = window.PractiseMaster[\"PM_\" + id].loop.endTimeSeconds / 10000 + 0.25;\n\n\n window.PractiseMaster[\"PM_\" + id].loop.endTimeSeconds = inputTimeFloat;\n\n\n /// video\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.pause();\n\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.currentTime = inputTimeFloat;\n\n\n document.querySelector(\"#\" + id + \"_timeEnd\").value = window.PractiseMaster.PageSupport.helpers.toStringTime(inputTimeFloat);\n\n\n //run warning validation\n\n window.PractiseMaster.PageSupport.helpers.redWarningValidation(id);\n\n }\n\n\n\n /**\n * event listener for <input type=\"time\"> or chronlyHMS updating end time\n * @listens keyup event of *_timeEnd\n * @param {event} e unused \n */\n\n timeEnd(e) {\n\n // 'this' is button so\n\n const id = this.id.replace('_timeEnd', '');\n\n\n console.log(\"Hey, I'll digit adjust the end time for player: \" + id);\n\n\n var endTimeString = this.value;\n\n\n window.PractiseMaster[\"PM_\" + id].loop.endTimeSeconds = window.PractiseMaster.PageSupport.helpers.secondsNumber(endTimeString);\n\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.currentTime = window.PractiseMaster.PageSupport.helpers.secondsNumber(endTimeString);\n\n\n //run warning validation\n\n window.PractiseMaster.PageSupport.helpers.redWarningValidation(id);\n\n }\n\n\n\n /**\n * event listener toggles on/off looping\n * @listens click event of *_onOff \n * @param {event} e unused\n */\n\n offToggle(e) {\n\n // 'this' is button so\n\n const id = this.id.replace('_onOff', '');\n\n\n console.log(\"Hey, I'll toggle off/on player: \" + id);\n\n\n // toggle the ui switch\n\n document.querySelector('#' + id + '_onOff > input').checked = !document.querySelector('#' + id + '_onOff > input').checked;\n\n // Get loop instance\n\n const loop = window.PractiseMaster[\"PM_\" + id].loop;\n\n\n // toggle the loop object instance \n\n loop.off = !loop.off;\n\n console.log(\"The loop is now switched off: \" + loop.off);\n\n\n\n // warning and invalid states check\n // and further in own method \n\n if (!loop.off) {\n\n // run validation \n\n console.log('asking to run validation for' + id);\n\n if (window.PractiseMaster.PageSupport.helpers.redWarningValidation(id)) {\n\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.pause();\n\n // turn looping off\n loop.off = !loop.off;\n\n // toggle switch back to off\n\n setTimeout(() => {\n document.querySelector('#' + id + '_onOff > input').checked = !document.querySelector('#' + id + '_onOff > input').checked;\n }, 500);\n\n }\n\n\n else {\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.play();\n }\n\n }\n }\n\n\n\n /**\n * event listener for loopbuilder links\n * @listens click event of *_links \n * @param {event} e unused\n * @todo refactor this (and other button events and listeners) to the UIprep class\n */\n\n linkLoopOrChapter(e) {\n\n // 'this' is button so\n\n const id = this.id.replace('_links', '');\n\n\n console.log(\"Hey, I'll toggle off/on player: \" + id);\n\n\n // need helpers to convert seconds to time before sending to UI\n window.PractiseMaster[\"PM_\" + id].uiPrep.addHTMLlink();\n\n }\n\n\n\n /**\n * time validation for start and end\n * @returns {boolean} returns true if invalid, false if valid\n */\n\n redWarningValidation() {\n\n\n const startTimeControl = document.querySelector(\"#\" + this.id.split(\"_\")[0] + \"_timeStart\");\n\n\n const endTimeControl = document.querySelector(\"#\" + this.id.split(\"_\")[0] + \"_timeEnd\");\n\n\n const loop = window[\"PMinstance_\" + this.id.split(\"_\")[0]].loop;\n\n\n const conditionsArray = [\n (loop.startTimeSeconds < 0),\n (loop.endTimeSeconds < 0),\n (loop.startTimeSeconds > loop.videoDuration),\n (loop.endTimeSeconds > loop.videoDuration),\n\n ];\n\n\n // remove any invalid css class\n startTimeControl.classList.remove(\"invalid\");\n\n endTimeControl.classList.remove(\"invalid\");\n\n\n if (conditionsArray.includes(true)) {\n\n // ex device check\n\n if (true) {\n\n\n\n var cEa = document.querySelector(\"#\" + this.id).querySelectorAll(\".plyr__control\");\n\n\n Array.from(cEa).forEach(function (item) { item.classList.add(\"plyr__controlError\") });\n\n\n }\n else {}\n\n // since invalid\n return true;\n }\n\n // since valid\n return false;\n }\n\n\n\n /**\n * statements that run after plyr 'ready' event for audio \n * @listens plyr ready\n * @param {string} id player/plyr/div id\n */\n\n setAudioListeners(id) {\n\n var closure = this;\n\n // Audio ready listener (PM will be slightly different)\n // window[\"PlyrAudio_\" + id].on('ready', event => {\n this.plyrInstance.on('ready', event => {\n\n console.log(\"Plyr audio says it's ready!\");\n\n // need to 'add back' user's id to div because it's removed by plyr \n event.target.id = id;\n\n // also need to add back pm class because it is removed by plyr was: event.target.classList.add('pm');\n closure.CSSclasses.forEach(singleClass => event.target.classList.add(singleClass));\n\n\n // replaces old new PractiseMaster(), as that is already done:\n closure.HTMLControls(closure.id);\n closure.loop = new _loop_pm__WEBPACK_IMPORTED_MODULE_2__[\"default\"](closure.id);\n closure.chapter = new _chapter_pm__WEBPACK_IMPORTED_MODULE_3__[\"default\"](closure.id, 0, 0);\n\n console.log('duration at plyr ready: ' + closure.plyrInstance.duration);\n\n\n // set duration of loop \n\n // for html audio and video there can be lags between plyr ready and the video duration value being 'ready'\n // this promise on interval is based on https://stackoverflow.com/questions/17217736/while-loop-with-promises\n // and https://codepen.io/anon/pen/jzpZMa?editors=0011 \n\n\n const doSomething = value =>\n new Promise(resolve =>\n setTimeout(() => resolve(value >= 5 ? 'ok' : 'no'), 1000))\n\n const loop = async value => {\n let result = null\n while (result != 'ok') {\n console.log(value)\n result = await doSomething(value)\n value = closure.plyrInstance.duration\n }\n console.log('yay audio duration set')\n }\n\n loop(closure.plyrInstance.duration)\n .then(() => {\n window[\"PMinstance_\" + id].loop.videoDuration = closure.plyrInstance.duration;\n console.log('audio duration all done!');\n });\n\n\n\n\n\n\n\n // needs to be initialised first for duration promise in new Loop()\n window[\"PMinstance_\" + id];\n\n // make instance available as Global, needed for Loop and Chapter CSSclasses\n window[\"PMinstance_\" + id] = closure;\n\n this.uiPrep.addAudioStyle(id);\n\n });\n\n }\n\n\n\n /**\n * statements that run after plyr 'ready' event for audio \n * @listens plyr ready\n * @param {string} id player/plyr/div id\n */\n\n setVideoListeners(id) {\n\n\n var closure = this;\n\n\n this.plyrInstance.on('ready', event => {\n\n // need to be above the conditional duration blocks\n // needs to be initialised first for duration promise in new Loop()\n window[\"PMinstance_\" + id];\n\n // make instance available as Global, needed for Loop and Chapter CSSclasses\n window[\"PMinstance_\" + id] = closure;\n\n // need to 'add back' user's id to div because it's removed by plyr \n\n event.target.id = id;\n\n // also need to add back pm class because it is removed by plyr\n\n // event.target.classList.add('pm');\n\n closure.CSSclasses.forEach(singleClass => event.target.classList.add(singleClass));\n\n\n console.log(\"Plyr says it's ready!\");\n\n console.log(\"Player source is : \" + closure.plyrInstance.source);\n\n console.log(\"Player duration is : \" + closure.plyrInstance.duration);\n\n // replaces old new PractiseMaster(), as that is already done:\n closure.HTMLControls(id);\n closure.loop = new _loop_pm__WEBPACK_IMPORTED_MODULE_2__[\"default\"](closure.id);\n closure.chapter = new _chapter_pm__WEBPACK_IMPORTED_MODULE_3__[\"default\"](closure.id, 0, 0);\n\n\n\n // methods to set duration and css are different depending on Video type\n\n if (closure.plyrInstance.isVimeo) {\n\n\n closure.plyrInstance.embed.getDuration().then(function (duration) {\n // the player is ready\n\n console.log(\"This Vimeo getDuration: \" + duration + \" seconds long.\");\n\n closure.loop.videoDuration = duration;\n console.log('Vimeo player duration is ' + duration);\n\n // looks like this needs to go inside promise!\n\n console.log(\"going to call css FH w/in promise! \");\n\n });\n\n }\n\n else if (closure.plyrInstance.isHTML5) {\n\n\n // for html audio and video there can be lags between plyr ready and the video duration value being 'ready'\n // this promise on interval is based on https://stackoverflow.com/questions/17217736/while-loop-with-promises\n // and https://codepen.io/anon/pen/jzpZMa?editors=0011 \n\n\n const doSomething = value =>\n new Promise(resolve =>\n setTimeout(() => resolve(value >= 5 ? 'ok' : 'no'), 1000))\n\n const loop = async value => {\n let result = null\n while (result != 'ok') {\n console.log(value)\n result = await doSomething(value)\n value = closure.plyrInstance.duration\n }\n console.log('yay html video duration set')\n }\n\n loop(closure.plyrInstance.duration)\n .then(() => {\n window[\"PMinstance_\" + id].loop.videoDuration = closure.plyrInstance.duration;\n console.log('video duration all done!');\n });\n\n\n\n\n\n\n\n }\n else {\n\n // for YouTube \n\n closure.loop.videoDuration = closure.plyrInstance.duration;\n\n console.log('Youtube player duration is ' + closure.plyrInstance.duration);\n\n }\n\n // ///\n // /// This event listener drives the looping, on timeupdate event from plyr\n // /// \n\n\n // document.addEventListener('timeupdate', window.PractiseMaster.PageSupport.helpers.delegateByIDparams(window[\"PMinstance_\" + closure.id].loop.id, window[\"PMinstance_\" + closure.id].loop.startTimeSeconds, window[\"PMinstance_\" + closure.id].loop.endTimeSeconds, window[\"PMinstance_\" + closure.id].loop.playSegment));\n\n\n // document.addEventListener('timeupdate', window.PractiseMaster.PageSupport.helpers.delegateByIDparams(window[\"PMinstance_\" + closure.id].chapter.id, window[\"PMinstance_\" + closure.id].chapter.startTimeSeconds, window[\"PMinstance_\" + closure.id].chapter.endTimeSeconds, window[\"PMinstance_\" + closure.id].chapter.playSegment));\n\n\n\n });\n\n };\n\n\n\n /**\n * statments to run after PM fires ready and controls are in place\n * @listens PM ready event \n */\n\n addPMReadyListeners() {\n\n // closure\n var player = this;\n\n window.addEventListener('pmControlsReady', function (e) {\n\n console.log('custom event fired, process(detail): ' + e.detail + ' and listened !!!!');\n\n player.uiPrep.applyPMReadyCssHTMLSettings(player.id);\n\n\n\n // ChronlyHMS added to all players, inactive unless linkbuilder\n // the input-duration will be added in the HTML string literal\n\n\n // input-duration update\n\n player.uiPrep.styleInputDuration(player.id);\n\n\n // set up ChronlyHMS and link builder\n if (player.classList.contains('links')) {\n\n // this updates to LinkBuilder method\n player.uiPrep.addLinkButton(player.id);\n\n\n // audio links doesn't need off player controls\n // the rest of player types do\n\n if (player.plyrInstance.type === 'video') {\n\n player.uiPrep.offPlayerControls(player.id);\n\n }\n\n\n\n }\n else {\n\n // userChronly method in UIprep ChronlyHMS.disableInputs()\n\n // input-duration update, comment out:\n player.uiPrep.diableDurationInputs(player.id);\n\n }\n\n if (player.classList.contains('offScreen')) {\n\n // this updates to LinkBuilder method\n player.uiPrep.offPlayerControls(player.id);\n\n\n }\n\n console.log('plyr duration at PM ready: ' + player.plyrInstance.duration);\n // console.log('loop duration at e: ' + player.loop);\n\n // player.loop.videoDuration = player.plyrInstance.duration\n\n\n //\n // window[\"PMinstance_\" + player.id].loop.videoDuration = player.plyrInstance.duration;\n\n // assign methods to windows variables\n // so user can easily access\n\n window.PMloop = window.PractiseMaster.PageSupport.PMloop;\n\n window.PMchapter = window.PractiseMaster.PageSupport.PMchapter;\n\n\n\n\n\n\n\n },\n\n false);\n }\n\n}\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Player);\n\n//# sourceURL=webpack://practisemaster/./src/modules/player-pm.js?");
194
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var plyr__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! plyr */ \"./node_modules/plyr/dist/plyr.min.js\");\n/* harmony import */ var plyr__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(plyr__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var plyr_dist_plyr_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! plyr/dist/plyr.css */ \"./node_modules/plyr/dist/plyr.css\");\n/* harmony import */ var _loop_pm__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./loop-pm */ \"./src/modules/loop-pm.js\");\n/* harmony import */ var _chapter_pm__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./chapter-pm */ \"./src/modules/chapter-pm.js\");\n/* harmony import */ var _UIprep_pm__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./UIprep-pm */ \"./src/modules/UIprep-pm.js\");\n/**\n * an instance of Player is used for each video on the DOM\n * the Player class manages Plyr, Loop, Chapter, HTML and events.\n * the plyr ready event listener instantiats a global window[\"PMinstance_\" + id] that is used by loop and chapter CSS classes\n * that are injected later\n * @module Player Module\n * @requires Plyr Module\n * @requires Plyr CSS\n * @requires Loop Module\n * @requires Chapter Module\n * @requires UIprep Module\n */\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * adds PractiseMaster looping and chapter controls to Plyr\n * @class Player\n * @property {string} id from element\n * @property {class} plyrInstance from plyr module\n * @property {boolean} isStatic as marked by user\n * @property {obsolete} CSSclasses refactor to classList if possible and remove (used once)\n * @property {classlist} classList\n * @property {declaration} code block sets isStatic for given conditions\n * @property {declaration} code block creates audio or video plyr for given properties\n * @property {class} uiPrep a new uiPrep class\n * @property {class} loop a Loop class instance\n * @property {class} chapter a Chapter class instance\n * @property {method} addPMReadyListeners adds any listeners required (ex PMready)\n * \n * \n */\nclass Player {\n\n /**\n * class constructor\n * @param {element} el div with pm class and plyr data requirements \n */\n constructor(el) {\n\n this.id = el.id;\n\n // site (ex WordPress css) goes on page once with PageSupport\n\n \n\n this.plyrInstance;\n\n // note static is set when Plyr is instantiated\n // otherwise this would be in UIprep\n // can toggleControls vis/no vis while playing but not set property\n\n this.isStatic;\n\n // class list for element, CSSclasses added back after player created\n\n this.CSSclasses = el.className.split(' ');\n\n this.classList = el.classList;\n\n // classlist check for static (user implemented)\n\n if (el.classList.contains('static') || el.classList.contains('offScreen') || window.PMpageSupport.isSafari || el.classList.contains('links')) {\n\n this.isStatic = true; // create plyr with static controls\n\n } else {\n // create plyr with hover controls\n this.isStatic = false;\n }\n\n\n if (el.tagName === 'AUDIO') {\n\n this.newPlyrAudio(el);\n\n }\n else {\n\n this.newPlyrVideo(el);\n\n }\n\n\n this.uiPrep = new _UIprep_pm__WEBPACK_IMPORTED_MODULE_4__[\"default\"](el);\n\n this.loop;\n\n this.chapter;\n\n // this will fire after everything to set any universal style\n\n this.addPMReadyListeners();\n\n\n\n }\n\n\n\n /**\n * creates a new video Plyr with the pm element\n * @param {element} el - div with pm class \n */\n\n newPlyrVideo(el) {\n\n this.plyrInstance = new (plyr__WEBPACK_IMPORTED_MODULE_0___default())('#' + el.id, {\n controls: [\n 'play', // Play/pause playback\n 'progress', // The progress bar and scrubber for playback and buffering\n 'current-time', // The current time of playback\n 'duration', // The full duration of the media\n 'mute', // Toggle mute\n 'volume', // Volume control\n 'settings', // Settings menu\n 'fullscreen', // Toggle fullscreen\n ],\n\n hideControls: !this.isStatic\n\n });\n\n this.setVideoListeners(el.id);\n\n this.eventListeners();\n\n }\n\n\n\n /**\n * creates a new audio Plyr with the pm element\n * @param {element} el - div with pm class \n */\n\n newPlyrAudio(el) {\n\n this.plyrInstance = new (plyr__WEBPACK_IMPORTED_MODULE_0___default())('audio#' + el.id, {});\n\n this.setAudioListeners(el.id)\n\n this.eventListeners();\n\n }\n\n\n\n /**\n * called from the plyr ready event listener, this method places the HTML controls on the video player\n * @param {string} id player/plyr/div id\n * @emits {event} called 'pmControlsReady'\n */\n\n HTMLControls(id) {\n\n var loopDivsLiteral = `\n <div style=\"flex-basis: 100%; height: 0;\"></div>\n <div style=\"flex-grow: 0.25;\"></div>\n <button id=\"${this.id}_info\" class=\"infoButton plyr__controls__item plyr__control\" type=\"button\">\n <svg id=\"infoSVG\" class=\"icon--not-pressed\" aria-hidden=\"true\" focusable=\"false\" viewBox=\"0 0 18 18\" >\n <path xmlns=\"http://www.w3.org/2000/svg\" d=\"m9.0598 0.42333c-4.9453 0-8.9522 3.8514-8.9522 8.6049 0 4.7535 4.0068 8.6049 8.9522 8.6049 4.9453 0 8.9522-3.8514 8.9522-8.6049 0-4.7535-4.0068-8.6049-8.9522-8.6049zm0 15.544c-3.9924 0-7.2195-3.1019-7.2195-6.9394 0-3.8306 3.2271-6.9394 7.2195-6.9394 3.9852 0 7.2195 3.1019 7.2195 6.9394 0 3.8375-3.2271 6.9394-7.2195 6.9394zm0-11.728c0.83746 0 1.5161 0.65231 1.5161 1.4573 0 0.80498-0.67863 1.4573-1.5161 1.4573-0.83746 0-1.5161-0.65231-1.5161-1.4573 0-0.80498 0.67863-1.4573 1.5161-1.4573zm2.0215 8.8131c0 0.229-0.19493 0.41637-0.43317 0.41637h-3.1766c-0.23824 0-0.43317-0.18736-0.43317-0.41637v-0.83273c0-0.229 0.19493-0.41637 0.43317-0.41637h0.43317v-2.2206h-0.43317c-0.23824 0-0.43317-0.18736-0.43317-0.41637v-0.83273c0-0.229 0.19493-0.41637 0.43317-0.41637h2.3102c0.23824 0 0.43317 0.18737 0.43317 0.41637v3.4697h0.43317c0.23824 0 0.43317 0.18736 0.43317 0.41637z\"/>\n </svg>\n <span class=\"label--not-pressed plyr__sr-only\">Info</span>\n </button>\n <span class=\"PMlogo\" style=\"font-style: italic; font-size: smaller; line-height: 12px;\">Practise<br>Master</span>\n <div style=\"flex-grow: 1;\"></div>\n <button id=\"${this.id}_nowTimeStart\" class=\"plyr__controls__item plyr__control\" type=\"button\">\n <svg id=\"nowSVG\" class=\"icon--not-pressed\" aria-hidden=\"true\" focusable=\"false\" viewBox=\"0 0 18 18\" style=\"transform: scaleY(-1)\" >\n <path xmlns=\"http://www.w3.org/2000/svg\" d=\"m13.83 0.12947c-0.60243 0.001022-0.93199 0.76661-1.3344 1.2481-0.42034 0.6401-0.18152 1.5806 0.28874 2.0369 0.40781 0.38221 0.08162 0.35863-0.24583 0.33434-3.3737 0.011276-6.7487-0.022766-10.121 0.017257-1.3482 0.13812-2.4025 1.9022-2.2584 3.6894 0.006509 2.7641-0.011751 4.6472 0.01577 7.4105 0.10198 1.8037 1.4251 3.1952 2.7541 3.0023 2.1542-0.01129 3.1065 0.02276 5.26-0.01727 1.3476-0.13717 2.3846-1.9108 2.2409-3.6895-0.01218-1.3917 0.02481-2.7875-0.01954-4.1765-0.096853-0.79696-0.72647-1.1446-1.2687-1.0422-0.527-0.049194-1.1834 0.011045-1.4058 0.78294-0.16627 0.81285-0.048406 1.6792-0.083807 2.5159v1.9074h-4.7123c0.0021-2.5223-0.00462-4.1591-0.00294-6.6814h10.095c-0.3871 0.56351-1.025 1.085-0.87246 1.9767 0.12204 0.66517 0.59476 1.0425 0.92175 1.5235 0.48086 0.55576 1.1804 0.23938 1.5247-0.38686 1.0531-1.4245 2.1432-2.8048 3.1729-4.2573 0.34907-0.65253 0.093278-1.5004-0.34614-1.9384-1.0264-1.3413-2.0186-2.7349-3.0667-4.0431-0.15772-0.13891-0.34622-0.21302-0.53492-0.21263z\" style=\"stroke-width:.014514\"/>\n </svg>\n <span class=\"label--pressed plyr__sr-only\">Text for Label</span>\n <span class=\"label--not-pressed plyr__sr-only\">Text for Label</span>\n </button>\n <button id=\"${this.id}_subtrTimeStart\" class=\"plyr__controls__item plyr__control\" type=\"button\">\n <svg id=\"cheveronSVG\" class=\"icon--not-pressed\" aria-hidden=\"true\" focusable=\"false\" viewBox=\"0 0 18 18\" style=\"transform: scaleX(-1)\" >\n <g xmlns=\"http://www.w3.org/2000/svg\" transform=\"matrix(.036353 0 0 .036621 -3.4195 .1145)\" style=\"stroke-width:7.2515\"><g style=\"stroke-width:7.2515\"><g style=\"stroke-width:7.2515\"><path d=\"m382.68 226.8c-73.671-73.548-147.1-147.35-220.92-220.74-12.991-11.358-32.333-5.3965-41.748 7.4512-10.355 9.4864-22.632 21.691-17.227 37.166 6.041 14.425 20.131 23.247 30.207 34.805 53.47 53.47 106.94 106.94 160.41 160.41-61.919 62.042-124.09 123.84-185.85 186.04-11.359 12.99-5.3968 32.335 7.4522 41.748 9.5221 10.409 21.812 22.708 37.35 17.168 14.308-6.1241 23.115-20.108 34.623-30.154 65.802-65.925 131.86-131.6 197.5-197.68 8.6934-10.271 7.9092-26.86-1.7952-36.212z\" style=\"stroke-width:7.2515\"/></g></g></g>\n </svg>\n <span class=\"label--pressed plyr__sr-only\">Text for Label</span>\n <span class=\"label--not-pressed plyr__sr-only\">Text for Label</span>\n </button>\n <input-duration id=\"${this.id}_timeStart\"></input-duration>\n <button id=\"${this.id}_addTimeStart\" class=\"plyr__controls__item plyr__control\" type=\"button\">\n <svg id=\"cheveronRevSVG\" class=\"icon--not-pressed\" aria-hidden=\"true\" focusable=\"false\" viewBox=\"0 0 18 18\">\n <use xlink:href=\"#cheveronSVG\" />\n </svg>\n <span class=\"label--pressed plyr__sr-only\">Text for Label</span>\n <span class=\"label--not-pressed plyr__sr-only\">Text for Label</span>\n </button>\n <div style=\"flex-grow: 1;\"></div>\n <button id=\"${this.id}_nowTimeEnd\" class=\"plyr__controls__item plyr__control\" type=\"button\">\n <svg id=\"pointSVG\" class=\"icon--not-pressed\" aria-hidden=\"true\" focusable=\"false\" viewBox=\"0 0 18 18\" style=\"transform: scale(-1, -1)\" >\n <path xmlns=\"http://www.w3.org/2000/svg\" d=\"m13.83 0.12947c-0.60243 0.001022-0.93199 0.76661-1.3344 1.2481-0.42034 0.6401-0.18152 1.5806 0.28874 2.0369 0.40781 0.38221 0.08162 0.35863-0.24583 0.33434-3.3737 0.011276-6.7487-0.022766-10.121 0.017257-1.3482 0.13812-2.4025 1.9022-2.2584 3.6894 0.006509 2.7641-0.011751 4.6472 0.01577 7.4105 0.10198 1.8037 1.4251 3.1952 2.7541 3.0023 2.1542-0.01129 3.1065 0.02276 5.26-0.01727 1.3476-0.13717 2.3846-1.9108 2.2409-3.6895-0.01218-1.3917 0.02481-2.7875-0.01954-4.1765-0.096853-0.79696-0.72647-1.1446-1.2687-1.0422-0.527-0.049194-1.1834 0.011045-1.4058 0.78294-0.16627 0.81285-0.048406 1.6792-0.083807 2.5159v1.9074h-4.7123c0.0021-2.5223-0.00462-4.1591-0.00294-6.6814h10.095c-0.3871 0.56351-1.025 1.085-0.87246 1.9767 0.12204 0.66517 0.59476 1.0425 0.92175 1.5235 0.48086 0.55576 1.1804 0.23938 1.5247-0.38686 1.0531-1.4245 2.1432-2.8048 3.1729-4.2573 0.34907-0.65253 0.093278-1.5004-0.34614-1.9384-1.0264-1.3413-2.0186-2.7349-3.0667-4.0431-0.15772-0.13891-0.34622-0.21302-0.53492-0.21263z\" style=\"stroke-width:.014514\"/>\n </svg>\n <span class=\"label--pressed plyr__sr-only\">Text for Label</span>\n <span class=\"label--not-pressed plyr__sr-only\">Text for Label</span>\n </button>\n <button id=\"${this.id}_subtrTimeEnd\" class=\"plyr__controls__item plyr__control\" type=\"button\">\n <svg class=\"icon--not-pressed\" aria-hidden=\"true\" focusable=\"false\" viewBox=\"0 0 18 18\" style=\"transform: scaleX(-1)\" >\n <use xlink:href=\"#cheveronSVG\" />\n </svg>\n <span class=\"label--pressed plyr__sr-only\">Text for Label</span>\n <span class=\"label--not-pressed plyr__sr-only\">Text for Label</span>\n </button>\n <input-duration id=\"${this.id}_timeEnd\"></input-duration>\n <button id=\"${this.id}_addTimeEnd\" class=\"plyr__controls__item plyr__control\" type=\"button\">\n <svg class=\"icon--not-pressed\" aria-hidden=\"true\" focusable=\"false\" viewBox=\"0 0 18 18\">\n <use xlink:href=\"#cheveronSVG\" />\n </svg>\n <span class=\"label--pressed plyr__sr-only\">Text for Label</span>\n <span class=\"label--not-pressed plyr__sr-only\">Text for Label</span>\n </button>\n <div style=\"flex-grow: 2;\"></div>\n <div id=\"${this.id}_onOff\" class=\"onoffswitch onoffDiv\">\n <input type=\"checkbox\" name=\"onoffswitch\" class=\"onoffswitch-checkbox\" tabindex=\"0\">\n <label class=\"onoffswitch-label\" for=\"myonoffswitch\">\n <span class=\"onoffswitch-inner\"></span>\n <span class=\"onoffswitch-switch\"></span>\n </label>\n </div>\n <div style=\"flex-grow: 0.5;\"> &nbsp;</div>\n `;\n\n\n document.querySelector(\"#\" + id + \" > div.plyr__controls\").insertAdjacentHTML('beforeend', loopDivsLiteral);\n\n\n window.dispatchEvent(new CustomEvent('pmControlsReady', { detail: id }));\n\n }\n\n\n\n /**\n * this method places event listeners on page for PM controls buttons through a delegate in Helpers module \n */\n\n eventListeners() {\n\n // events these events need delegates to encapsulate id data as closures\n // https://stackoverflow.com/questions/46101024/add-event-listener-to-future-item-without-jquery\n\n // start time events \n\n document.addEventListener('click', window.PMpageSupport.helpers.delegate('#' + this.id + '_nowTimeStart', this.setTimeStart));\n\n document.addEventListener('click', window.PMpageSupport.helpers.delegate('#' + this.id + '_subtrTimeStart', this.subtrTimeStart));\n\n // event for input-duration \n document.addEventListener('keyup', window.PMpageSupport.helpers.delegate('#' + this.id + '_timeStart', this.timeStart));\n\n document.addEventListener('click', window.PMpageSupport.helpers.delegate('#' + this.id + '_addTimeStart', this.addTimeStart));\n\n\n // end time events (add return key for starting loop)\n\n document.addEventListener('click', window.PMpageSupport.helpers.delegate('#' + this.id + '_nowTimeEnd', this.setTimeEnd));\n\n document.addEventListener('click', window.PMpageSupport.helpers.delegate('#' + this.id + '_subtrTimeEnd', this.subtrTimeEnd));\n\n // event for input-duration\n document.addEventListener('keyup', window.PMpageSupport.helpers.delegate('#' + this.id + '_timeEnd', this.timeEnd));\n\n document.addEventListener('click', window.PMpageSupport.helpers.delegate('#' + this.id + '_addTimeEnd', this.addTimeEnd));\n\n // loop on / off button event\n\n document.addEventListener('click', window.PMpageSupport.helpers.delegate('#' + this.id + '_onOff', this.offToggle));\n\n\n // Loop and Chapter Link button event\n\n document.addEventListener('click', window.PMpageSupport.helpers.delegate('#' + this.id + '_links', this.linkLoopOrChapter));\n\n\n \n }\n\n\n // actual event listeners\n\n /**\n * event listener sets start time\n * @listens click event of *_nowTimeStart \n * @param {event} e unused\n */\n\n setTimeStart(e) {\n\n // 'this' is button so\n\n\n const id = this.id.replace('_nowTimeStart', '');\n\n\n\n console.log(\"Hey, I'll set the start time for player: \" + id);\n\n\n // Does: \n // set loop start\n\n const currentTime = window.PractiseMaster[\"PM_\" + id].plyrInstance.currentTime;\n window.PractiseMaster[\"PM_\" + id].loop.startTimeSeconds = currentTime;\n\n\n // trims string for mobile devices, where input time is updated to input string\n\n document.querySelector(\"#\" + id + \"_timeStart\").value = window.PMpageSupport.helpers.toStringTime(currentTime);\n\n\n // run warning validation\n\n window.PMpageSupport.helpers.redWarningValidation(id);\n\n }\n\n\n\n\n /**\n * event listener reduces start time\n * @listens click event of *_subtrTimeStart \n * @param {event} e unused\n */\n\n subtrTimeStart(e) {\n\n // 'this' is button so\n const id = this.id.replace('_subtrTimeStart', '');\n\n\n console.log(\"Hey, I'll subtract time start for player: \" + id);\n\n\n /// update loop object\n\n var inputTimeFloat = window.PractiseMaster[\"PM_\" + id].loop.startTimeSeconds / 10000 - 0.25 > 0 ? window.PractiseMaster[\"PM_\" + id].loop.startTimeSeconds / 10000 - 0.25 : 0;\n\n window.PractiseMaster[\"PM_\" + id].loop.startTimeSeconds = inputTimeFloat;\n\n\n /// video\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.pause();\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.currentTime = inputTimeFloat;\n\n\n\n document.querySelector(\"#\" + id + \"_timeStart\").value = window.PMpageSupport.helpers.toStringTime(inputTimeFloat);\n\n\n // run warning validation\n\n window.PMpageSupport.helpers.redWarningValidation(id);\n\n }\n\n\n\n /**\n * event listener increases start time\n * @listens click event of *_addTimeStart \n * @param {event} e unused\n */\n\n addTimeStart(e) {\n\n // 'this' is button so\n\n const id = this.id.replace('_addTimeStart', '');\n\n\n console.log(\"Hey, I'll add time end for player: \" + id);\n\n\n /// update loop object\n\n var inputTimeFloat = window.PractiseMaster[\"PM_\" + id].loop.startTimeSeconds / 10000 + 0.25;\n\n\n window.PractiseMaster[\"PM_\" + id].loop.startTimeSeconds = inputTimeFloat;\n\n\n /// video\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.pause();\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.currentTime = inputTimeFloat;\n\n\n document.querySelector(\"#\" + id + \"_timeStart\").value = window.PMpageSupport.helpers.toStringTime(inputTimeFloat);\n\n\n // run warning validation\n\n window.PMpageSupport.helpers.redWarningValidation(id);\n\n }\n\n\n\n\n /**\n * event listener for <input type=\"time\"> or chronlyHMS updating start time\n * @listens keyup event of *_timeStart\n * @param {e} event \n */\n\n timeStart(e) {\n\n // 'this' is button so\n\n const id = this.id.replace('_timeStart', '');\n\n console.log(\"Hey, I'll digit adjust the start time for player: \" + id);\n\n\n // update loop instance\n\n var startTimeString = this.value;\n\n\n // was toFloatSecs x2\n\n window.PractiseMaster[\"PM_\" + id].loop.startTimeSeconds = window.PMpageSupport.helpers.secondsNumber(startTimeString);\n\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.currentTime = window.PMpageSupport.helpers.secondsNumber(startTimeString);\n\n // run warning validation\n\n window.PMpageSupport.helpers.redWarningValidation(id);\n\n\n }\n\n\n\n /**\n * event listener sets end time\n * @listens click event of *_nowTimeEnd \n * @param {event} e unused\n */\n\n setTimeEnd(e) {\n\n // 'this' is button so\n\n const id = this.id.replace('_nowTimeEnd', '');\n\n\n console.log(\"Hey, I'll set the end time for player: \" + id);\n\n\n // get current time of plyr\n\n // set loop end\n\n var currentTime = window.PractiseMaster[\"PM_\" + id].plyrInstance.currentTime;\n\n\n window.PractiseMaster[\"PM_\" + id].loop.endTimeSeconds = currentTime;\n\n\n // trims string for mobile devices, where input time is updated to input string\n\n document.querySelector(\"#\" + id + \"_timeEnd\").value = window.PMpageSupport.helpers.toStringTime(currentTime);\n\n\n // run warning validation\n\n window.PMpageSupport.helpers.redWarningValidation(id);\n\n }\n\n\n\n\n /**\n * event listener reduces end time\n * @listens click event of *_subtrTimeEnd\n * @param {event} e unused\n */\n\n subtrTimeEnd(e) {\n\n // 'this' is button so\n\n const id = this.id.replace('_subtrTimeEnd', '');\n\n\n console.log(\"Hey, I'll subtract time end for player: \" + id);\n\n\n /// update loop object\n\n var inputTimeFloat = window.PractiseMaster[\"PM_\" + id].loop.endTimeSeconds / 10000 - 0.25 > 0 ? window.PractiseMaster[\"PM_\" + id].loop.endTimeSeconds / 10000 - 0.25 : 0;\n\n window.PractiseMaster[\"PM_\" + id].loop.endTimeSeconds = inputTimeFloat;\n\n\n /// video\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.pause();\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.currentTime = inputTimeFloat;\n\n\n // trims string for mobile devices, where input time is updated to input string\n document.querySelector(\"#\" + id + \"_timeEnd\").value = window.PMpageSupport.helpers.toStringTime(inputTimeFloat);\n\n\n // run warning validation\n\n window.PMpageSupport.helpers.redWarningValidation(id);\n\n }\n\n\n\n /**\n * event listener increases end time\n * @listens click event of *_addTimeEnd \n * @param {event} e unused\n */\n\n addTimeEnd(event) {\n\n // 'this' is button so\n\n const id = this.id.replace('_addTimeEnd', '');\n\n\n console.log(\"Hey, I'll add time end for player: \" + id);\n\n\n /// update loop object\n\n var inputTimeFloat = window.PractiseMaster[\"PM_\" + id].loop.endTimeSeconds / 10000 + 0.25;\n\n\n window.PractiseMaster[\"PM_\" + id].loop.endTimeSeconds = inputTimeFloat;\n\n\n /// video\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.pause();\n\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.currentTime = inputTimeFloat;\n\n\n document.querySelector(\"#\" + id + \"_timeEnd\").value = window.PMpageSupport.helpers.toStringTime(inputTimeFloat);\n\n\n //run warning validation\n\n window.PMpageSupport.helpers.redWarningValidation(id);\n\n }\n\n\n\n /**\n * event listener for <input type=\"time\"> or chronlyHMS updating end time\n * @listens keyup event of *_timeEnd\n * @param {event} e unused \n */\n\n timeEnd(e) {\n\n // 'this' is button so\n\n const id = this.id.replace('_timeEnd', '');\n\n\n console.log(\"Hey, I'll digit adjust the end time for player: \" + id);\n\n\n var endTimeString = this.value;\n\n\n window.PractiseMaster[\"PM_\" + id].loop.endTimeSeconds = window.PMpageSupport.helpers.secondsNumber(endTimeString);\n\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.currentTime = window.PMpageSupport.helpers.secondsNumber(endTimeString);\n\n\n //run warning validation\n\n window.PMpageSupport.helpers.redWarningValidation(id);\n\n }\n\n\n\n /**\n * event listener toggles on/off looping\n * @listens click event of *_onOff \n * @param {event} e unused\n */\n\n offToggle(e) {\n\n // 'this' is button so\n\n const id = this.id.replace('_onOff', '');\n\n\n console.log(\"Hey, I'll toggle off/on player: \" + id);\n\n\n // toggle the ui switch\n\n document.querySelector('#' + id + '_onOff > input').checked = !document.querySelector('#' + id + '_onOff > input').checked;\n\n // Get loop instance\n\n const loop = window.PractiseMaster[\"PM_\" + id].loop;\n\n\n // toggle the loop object instance \n\n loop.off = !loop.off;\n\n console.log(\"The loop is now switched off: \" + loop.off);\n\n\n\n // warning and invalid states check\n // and further in own method \n\n if (!loop.off) {\n\n // run validation \n\n console.log('asking to run validation for' + id);\n\n if (window.PMpageSupport.helpers.redWarningValidation(id)) {\n\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.pause();\n\n // turn looping off\n loop.off = !loop.off;\n\n // toggle switch back to off\n\n setTimeout(() => {\n document.querySelector('#' + id + '_onOff > input').checked = !document.querySelector('#' + id + '_onOff > input').checked;\n }, 500);\n\n }\n\n\n else {\n\n window.PractiseMaster[\"PM_\" + id].plyrInstance.play();\n }\n\n }\n }\n\n\n\n /**\n * event listener for loopbuilder links\n * @listens click event of *_links \n * @param {event} e unused\n * @todo refactor this (and other button events and listeners) to the UIprep class\n */\n\n linkLoopOrChapter(e) {\n\n // 'this' is button so\n\n const id = this.id.replace('_links', '');\n\n\n console.log(\"Hey, I'll toggle off/on player: \" + id);\n\n\n // need helpers to convert seconds to time before sending to UI\n window.PractiseMaster[\"PM_\" + id].uiPrep.addHTMLlink();\n\n }\n\n\n\n /**\n * time validation for start and end\n * @returns {boolean} returns true if invalid, false if valid\n */\n\n redWarningValidation() {\n\n\n const startTimeControl = document.querySelector(\"#\" + this.id.split(\"_\")[0] + \"_timeStart\");\n\n\n const endTimeControl = document.querySelector(\"#\" + this.id.split(\"_\")[0] + \"_timeEnd\");\n\n\n const loop = window[\"PMinstance_\" + this.id.split(\"_\")[0]].loop;\n\n\n const conditionsArray = [\n (loop.startTimeSeconds < 0),\n (loop.endTimeSeconds < 0),\n (loop.startTimeSeconds > loop.videoDuration),\n (loop.endTimeSeconds > loop.videoDuration),\n\n ];\n\n\n // remove any invalid css class\n startTimeControl.classList.remove(\"invalid\");\n\n endTimeControl.classList.remove(\"invalid\");\n\n\n if (conditionsArray.includes(true)) {\n\n // ex device check\n\n if (true) {\n\n\n\n var cEa = document.querySelector(\"#\" + this.id).querySelectorAll(\".plyr__control\");\n\n\n Array.from(cEa).forEach(function (item) { item.classList.add(\"plyr__controlError\") });\n\n\n }\n else {}\n\n // since invalid\n return true;\n }\n\n // since valid\n return false;\n }\n\n\n\n /**\n * statements that run after plyr 'ready' event for audio \n * @listens plyr ready\n * @param {string} id player/plyr/div id\n */\n\n setAudioListeners(id) {\n\n var closure = this;\n\n // Audio ready listener (PM will be slightly different)\n // window[\"PlyrAudio_\" + id].on('ready', event => {\n this.plyrInstance.on('ready', event => {\n\n console.log(\"Plyr audio says it's ready!\");\n\n // need to 'add back' user's id to div because it's removed by plyr \n event.target.id = id;\n\n // also need to add back pm class because it is removed by plyr was: event.target.classList.add('pm');\n closure.CSSclasses.forEach(singleClass => event.target.classList.add(singleClass));\n\n\n // replaces old new PractiseMaster(), as that is already done:\n closure.HTMLControls(closure.id);\n closure.loop = new _loop_pm__WEBPACK_IMPORTED_MODULE_2__[\"default\"](closure.id);\n closure.chapter = new _chapter_pm__WEBPACK_IMPORTED_MODULE_3__[\"default\"](closure.id, 0, 0);\n\n console.log('duration at plyr ready: ' + closure.plyrInstance.duration);\n\n\n // set duration of loop \n\n // for html audio and video there can be lags between plyr ready and the video duration value being 'ready'\n // this promise on interval is based on https://stackoverflow.com/questions/17217736/while-loop-with-promises\n // and https://codepen.io/anon/pen/jzpZMa?editors=0011 \n\n\n const doSomething = value =>\n new Promise(resolve =>\n setTimeout(() => resolve(value >= 5 ? 'ok' : 'no'), 1000))\n\n const loop = async value => {\n let result = null\n while (result != 'ok') {\n console.log(value)\n result = await doSomething(value)\n value = closure.plyrInstance.duration\n }\n console.log('yay audio duration set')\n }\n\n loop(closure.plyrInstance.duration)\n .then(() => {\n window[\"PMinstance_\" + id].loop.videoDuration = closure.plyrInstance.duration;\n console.log('audio duration all done!');\n });\n\n\n\n\n\n\n\n // needs to be initialised first for duration promise in new Loop()\n window[\"PMinstance_\" + id];\n\n // make instance available as Global, needed for Loop and Chapter CSSclasses\n window[\"PMinstance_\" + id] = closure;\n\n this.uiPrep.addAudioStyle(id);\n\n });\n\n }\n\n\n\n /**\n * statements that run after plyr 'ready' event for audio \n * @listens plyr ready\n * @param {string} id player/plyr/div id\n */\n\n setVideoListeners(id) {\n\n\n var closure = this;\n\n\n this.plyrInstance.on('ready', event => {\n\n // need to be above the conditional duration blocks\n // needs to be initialised first for duration promise in new Loop()\n window[\"PMinstance_\" + id];\n\n // make instance available as Global, needed for Loop and Chapter CSSclasses\n window[\"PMinstance_\" + id] = closure;\n\n // need to 'add back' user's id to div because it's removed by plyr \n\n event.target.id = id;\n\n // also need to add back pm class because it is removed by plyr\n\n // event.target.classList.add('pm');\n\n closure.CSSclasses.forEach(singleClass => event.target.classList.add(singleClass));\n\n\n console.log(\"Plyr says it's ready!\");\n\n console.log(\"Player source is : \" + closure.plyrInstance.source);\n\n console.log(\"Player duration is : \" + closure.plyrInstance.duration);\n\n // replaces old new PractiseMaster(), as that is already done:\n closure.HTMLControls(id);\n closure.loop = new _loop_pm__WEBPACK_IMPORTED_MODULE_2__[\"default\"](closure.id);\n closure.chapter = new _chapter_pm__WEBPACK_IMPORTED_MODULE_3__[\"default\"](closure.id, 0, 0);\n\n\n\n // methods to set duration and css are different depending on Video type\n\n if (closure.plyrInstance.isVimeo) {\n\n\n closure.plyrInstance.embed.getDuration().then(function (duration) {\n // the player is ready\n\n console.log(\"This Vimeo getDuration: \" + duration + \" seconds long.\");\n\n closure.loop.videoDuration = duration;\n console.log('Vimeo player duration is ' + duration);\n\n // looks like this needs to go inside promise!\n\n console.log(\"going to call css FH w/in promise! \");\n\n });\n\n }\n\n else if (closure.plyrInstance.isHTML5) {\n\n\n // for html audio and video there can be lags between plyr ready and the video duration value being 'ready'\n // this promise on interval is based on https://stackoverflow.com/questions/17217736/while-loop-with-promises\n // and https://codepen.io/anon/pen/jzpZMa?editors=0011 \n\n\n const doSomething = value =>\n new Promise(resolve =>\n setTimeout(() => resolve(value >= 5 ? 'ok' : 'no'), 1000))\n\n const loop = async value => {\n let result = null\n while (result != 'ok') {\n console.log(value)\n result = await doSomething(value)\n value = closure.plyrInstance.duration\n }\n console.log('yay html video duration set')\n }\n\n loop(closure.plyrInstance.duration)\n .then(() => {\n window[\"PMinstance_\" + id].loop.videoDuration = closure.plyrInstance.duration;\n console.log('video duration all done!');\n });\n\n\n\n\n\n\n\n }\n else {\n\n // for YouTube \n\n closure.loop.videoDuration = closure.plyrInstance.duration;\n\n console.log('Youtube player duration is ' + closure.plyrInstance.duration);\n\n }\n\n // ///\n // /// This event listener drives the looping, on timeupdate event from plyr\n // /// \n\n\n // document.addEventListener('timeupdate', window.PractiseMaster.PageSupport.helpers.delegateByIDparams(window[\"PMinstance_\" + closure.id].loop.id, window[\"PMinstance_\" + closure.id].loop.startTimeSeconds, window[\"PMinstance_\" + closure.id].loop.endTimeSeconds, window[\"PMinstance_\" + closure.id].loop.playSegment));\n\n\n // document.addEventListener('timeupdate', window.PractiseMaster.PageSupport.helpers.delegateByIDparams(window[\"PMinstance_\" + closure.id].chapter.id, window[\"PMinstance_\" + closure.id].chapter.startTimeSeconds, window[\"PMinstance_\" + closure.id].chapter.endTimeSeconds, window[\"PMinstance_\" + closure.id].chapter.playSegment));\n\n\n\n });\n\n };\n\n\n\n /**\n * statments to run after PM fires ready and controls are in place\n * @listens PM ready event \n */\n\n addPMReadyListeners() {\n\n // closure\n var player = this;\n\n window.addEventListener('pmControlsReady', function (e) {\n\n console.log('custom event fired, process(detail): ' + e.detail + ' and listened !!!!');\n\n player.uiPrep.applyPMReadyCssHTMLSettings(player.id);\n\n\n\n // ChronlyHMS added to all players, inactive unless linkbuilder\n // the input-duration will be added in the HTML string literal\n\n\n // input-duration update\n\n player.uiPrep.styleInputDuration(player.id);\n\n\n // set up ChronlyHMS and link builder\n if (player.classList.contains('links')) {\n\n // this updates to LinkBuilder method\n player.uiPrep.addLinkButton(player.id);\n\n\n // audio links doesn't need off player controls\n // the rest of player types do\n\n if (player.plyrInstance.type === 'video') {\n\n player.uiPrep.offPlayerControls(player.id);\n\n }\n\n\n\n }\n else {\n\n // userChronly method in UIprep ChronlyHMS.disableInputs()\n\n // input-duration update, comment out:\n player.uiPrep.diableDurationInputs(player.id);\n\n }\n\n if (player.classList.contains('offScreen')) {\n\n // this updates to LinkBuilder method\n player.uiPrep.offPlayerControls(player.id);\n\n\n }\n\n console.log('plyr duration at PM ready: ' + player.plyrInstance.duration);\n // console.log('loop duration at e: ' + player.loop);\n\n // player.loop.videoDuration = player.plyrInstance.duration\n\n\n //\n // window[\"PMinstance_\" + player.id].loop.videoDuration = player.plyrInstance.duration;\n\n // assign methods to windows variables\n // so user can easily access\n\n window.PMloop = window.PMpageSupport.PMloop;\n\n window.PMchapter = window.PMpageSupport.PMchapter;\n\n\n\n\n\n\n\n },\n\n false);\n }\n\n}\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Player);\n\n//# sourceURL=webpack://practisemaster/./src/modules/player-pm.js?");
195
195
 
196
196
  /***/ }),
197
197
 
@@ -202,7 +202,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
202
202
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
203
203
 
204
204
  "use strict";
205
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _player_pm__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./player-pm */ \"./src/modules/player-pm.js\");\n/* harmony import */ var _pageSupport_pm__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./pageSupport-pm */ \"./src/modules/pageSupport-pm.js\");\n/**\n * module allows for the newing of a PractiseMaster class \n * a global window.PractiseMaster is created\n * \n * @module PractiseMaster Module\n * @requires Player Module\n * @requires PageSupport Module\n */\n\n\n\n\n\n\n/**\n * entry point for PractiseMaster js plugin: new PractiseMaster();\n * @class PractiseMaster\n * @property {mehtod} globals() - returns window.PractiseMaster\n * @property {method} player() - news up a Player class for each pm class element\n * @property {declaration} getElementsByClassName(\"pm\") - Elements to update with a player \n * @property {declaration} getElementsByClassName(\"pmlinkbuilder\") - Elements to update with a player \n * @property {class} PageSupport(siteCSS) - news this up with any site specific css\n * @property {object} siteCSS - an object for css specific to the host site (ex WordPress)\n */\n\nclass PractiseMaster {\n\n constructor(siteCSS) {\n\n\n this.globals();\n\n\n // site (ex WordPress css) goes on page once with PageSupport\n this.PageSupport = new _pageSupport_pm__WEBPACK_IMPORTED_MODULE_1__[\"default\"](siteCSS);\n\n\n this.siteCSS = siteCSS;\n\n }\n\n\n\n /**\n * instantiates any global variables from the PractiseMaster class\n * @method\n */\n\n\n globals() {\n\n window.PractiseMaster = this;\n\n this.PMloop = function (id, startTime, endTime) { return window.PractiseMaster.PageSupport.PMloop(id, startTime, endTime) };\n this.PMchapter = function (id, startTime, endTime) { return window.PractiseMaster.PageSupport.PMloop(id, startTime, endTime) };\n\n }\n\n\n\n /**\n * news-up a Player class for each of [PMelements]\n * @method\n */\n\n\n player() {\n\n console.log(this.pmElements.length + \" 'pm' video or audio players created\");\n\n // this.pmElements.forEach((el) => {\n\n Array.from(this.pmElements).forEach((el) => {\n // Do stuff here\n console.log(el.tagName);\n\n this[\"PM_\" + el.id] = new _player_pm__WEBPACK_IMPORTED_MODULE_0__[\"default\"](el);\n\n });\n\n }\n\n}\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PractiseMaster);\n\n//# sourceURL=webpack://practisemaster/./src/modules/practiseMaster.js?");
205
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _player_pm__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./player-pm */ \"./src/modules/player-pm.js\");\n/**\n * module allows for the newing of a PractiseMaster class \n * a global window.PractiseMaster is created\n * \n * @module PractiseMaster Module\n * @requires Player Module\n * @requires PageSupport Module\n */\n\n\n\n\n\n\n/**\n * entry point for PractiseMaster js plugin: new PractiseMaster();\n * @class PractiseMaster\n * @property {mehtod} globals() - returns window.PractiseMaster\n * @property {method} player() - news up a Player class for each pm class element\n * @property {declaration} getElementsByClassName(\"pm\") - Elements to update with a player \n * @property {declaration} getElementsByClassName(\"pmlinkbuilder\") - Elements to update with a player \n * @property {class} PageSupport(siteCSS) - news this up with any site specific css\n * @property {object} siteCSS - an object for css specific to the host site (ex WordPress)\n */\n\nclass PractiseMaster {\n\n constructor() {\n\n\n\n\n\n\n\n\n\n // will try with pm-linkediter to override this setter with \n // document.querySelector('div.pm') or if can \n // document.querySelector('pm-linkeditor > div.pm')\n\n this.pmElements = document.querySelectorAll(\"practise-master > *.pm\");\n\n this.PMchapter;\n\n this.PMloop;\n\n\n this.player();\n\n this.globals();\n\n\n }\n\n\n\n /**\n * instantiates any global variables from the PractiseMaster class\n * @method\n */\n\n\n globals() {\n\n // window.PractiseMaster.PMloop = function (id, startTime, endTime) { return window.PractiseMaster.PageSupport.PMloop(id, startTime, endTime) };\n // window.PractiseMaster.PMchapter = function (id, startTime, endTime) { return window.PractiseMaster.PageSupport.PMloop(id, startTime, endTime) };\n\n }\n\n\n\n /**\n * news-up a Player class for each of [PMelements]\n * @method\n */\n\n\n player() {\n\n console.log(this.pmElements.length + \" 'pm' video or audio players created\");\n\n // this.pmElements.forEach((el) => {\n\n Array.from(this.pmElements).forEach((el) => {\n // Do stuff here\n console.log(el.tagName);\n\n this[\"PM_\" + el.id] = new _player_pm__WEBPACK_IMPORTED_MODULE_0__[\"default\"](el);\n\n });\n\n }\n\n}\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PractiseMaster);\n\n//# sourceURL=webpack://practisemaster/./src/modules/practiseMaster.js?");
206
206
 
207
207
  /***/ }),
208
208
 
@@ -213,7 +213,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
213
213
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
214
214
 
215
215
  "use strict";
216
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _practiseMaster__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./practiseMaster */ \"./src/modules/practiseMaster.js\");\n/**\n * module allows for the newing of a PractiseMaster class \n * a global window.PractiseMaster is created\n * \n * @module PractiseMaster Module\n * @requires Player Module\n * @requires PageSupport Module\n */\n\n\n\n\n\n/**\n * entry point for PractiseMaster js plugin: new PractiseMaster();\n * @class PractiseMaster\n * @property {mehtod} globals() - returns window.PractiseMaster\n * @property {method} player() - news up a Player class for each pm class element\n * @property {declaration} getElementsByClassName(\"pm\") - Elements to update with a player \n * @property {declaration} getElementsByClassName(\"pmlinkbuilder\") - Elements to update with a player \n * @property {class} PageSupport(siteCSS) - news this up with any site specific css\n * @property {object} siteCSS - an object for css specific to the host site (ex WordPress)\n */\n\nclass PractiseMasterWebComp extends HTMLElement {\n\n // static observedAttributes = [\"color\", \"size\"];\n\n\n constructor() {\n\n // Always call super first in constructor\n super();\n\n // to hold elements for player()\n this.pmElements = [];\n\n\n\n\n\n // only want one of these (per page) once init'd then pass array of elements then call PM.player()\n this.PM = new _practiseMaster__WEBPACK_IMPORTED_MODULE_0__[\"default\"]();\n\n\n }\n\n\n connectedCallback() {\n\n\n\n this.initialiseContainers();\n\n\n\n var siteCSS = 'toBeCreatedSiteCSS';\n\n // initialiseContainers should have popluated\n\n this.PM.pmElements = this.pmElements;\n this.PM.player(siteCSS);\n\n\n }\n\n\n\n /**\n * As a temp solution to Plyr not taking P-M custom elements\n * @method\n */\n\n initialiseContainers() {\n\n var that = this;\n\n\n const PMwebcomp = document.querySelectorAll(\"practise-master\");\n\n\n // check user has added data attributes\n\n [...PMwebcomp].forEach(wc => {\n if (wc.dataset.plyrProvider !== 'mp3' && wc.dataset.plyrProvider !== 'mp4' ) {\n if ((!wc.hasAttribute(\"data-plyr-embed-id\") || !wc.hasAttribute(\"data-plyr-provider\")) ) {\n // data attribute doesn't exist\n\n\n const errorText = `Error: each <practise-master> needs both 'data-plyr-embed-id' and 'data-plyr-provider' `;\n\n wc.textContent = errorText;\n\n throw new Error(errorText);\n\n }\n }\n });\n\n\n\n function cloneRemoveAttributes(target, source) {\n\n [...source.attributes].forEach(attr => { target.setAttribute(attr.nodeName, attr.nodeValue); source.removeAttribute(attr.name) });\n\n }\n\n\n function replaceWithDiv(node) {\n\n var pmdiv = document.createElement('div');\n\n cloneRemoveAttributes(pmdiv, node);\n\n node.classList.add('container');\n\n pmdiv.classList.add('pm');\n\n node.appendChild(pmdiv);\n\n that.pmElements.push(pmdiv);\n\n }\n\n\n function replaceWithVideo(node) {\n\n\n var pmdiv = document.createElement('video');\n\n cloneRemoveAttributes(pmdiv, node);\n\n node.classList.add('container');\n\n pmdiv.classList.add('pm');\n\n that.pmElements.push(pmdiv);\n\n // also need to copy all children to the new node\n // https://stackoverflow.com/a/56307130/2455159\n\n pmdiv.append(...node.childNodes);\n\n node.appendChild(pmdiv);\n\n }\n\n\n function replaceWithAudio(node) {\n\n\n var pmdiv = document.createElement('audio');\n\n cloneRemoveAttributes(pmdiv, node);\n\n node.classList.add('container');\n\n pmdiv.classList.add('pm');\n\n that.pmElements.push(pmdiv);\n\n // also need to copy all children to the new node\n // https://stackoverflow.com/a/56307130/2455159\n\n pmdiv.append(...node.childNodes);\n\n node.appendChild(pmdiv);\n\n }\n\n\n\n PMwebcomp.forEach(pmwc => {\n\n if (pmwc.dataset.plyrProvider === 'vimeo' || pmwc.dataset.plyrProvider === 'youtube') {\n\n replaceWithDiv(pmwc);\n\n } else if (pmwc.dataset.plyrProvider === 'mp4') {\n\n replaceWithVideo(pmwc);\n\n } else if (pmwc.dataset.plyrProvider === 'mp3') {\n\n replaceWithAudio(pmwc);\n\n }\n\n });\n\n }\n\n}\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PractiseMasterWebComp);\n\n//# sourceURL=webpack://practisemaster/./src/modules/practisemasterWebComponent.js?");
216
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _practiseMaster__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./practiseMaster */ \"./src/modules/practiseMaster.js\");\n/**\n * module allows for the newing of a PractiseMaster class \n * a global window.PractiseMaster is created\n * \n * @module PractiseMaster Module\n * @requires Player Module\n * @requires PageSupport Module\n */\n\n\n\n\n\n/**\n * entry point for PractiseMaster js plugin: new PractiseMaster();\n * @class PractiseMaster\n * @property {mehtod} globals() - returns window.PractiseMaster\n * @property {method} player() - news up a Player class for each pm class element\n * @property {declaration} getElementsByClassName(\"pm\") - Elements to update with a player \n * @property {declaration} getElementsByClassName(\"pmlinkbuilder\") - Elements to update with a player \n * @property {class} PageSupport(siteCSS) - news this up with any site specific css\n * @property {object} siteCSS - an object for css specific to the host site (ex WordPress)\n */\n\nclass PractiseMasterWebComp extends HTMLElement {\n\n // static observedAttributes = [\"color\", \"size\"];\n\n\n constructor() {\n\n // Always call super first in constructor\n super();\n\n // to hold elements for player()\n // with WebComponenet will only be one (no longer array)\n\n this.pmElement;\n\n\n }\n\n\n connectedCallback() {\n\n this.initialiseContainers();\n \n }\n\n\n\n /**\n * As a temp solution to Plyr not taking P-M custom elements\n * @method\n */\n\n initialiseContainers() {\n\n \n // const PMwebcomp = document.querySelectorAll(\"practise-master\");\n\n\n // // check user has added data attributes\n\n\n if (this.dataset.plyrProvider !== 'mp3' && this.dataset.plyrProvider !== 'mp4') {\n if ((!this.hasAttribute(\"data-plyr-embed-id\") || !this.hasAttribute(\"data-plyr-provider\"))) {\n // data attribute doesn't exist\n\n\n const errorText = `Error: each <practise-master> needs both 'data-plyr-embed-id' and 'data-plyr-provider' `;\n\n this.textContent = errorText;\n\n throw new Error(errorText);\n\n }\n }\n\n\n function cloneRemoveAttributes(target, source) {\n\n [...source.attributes].forEach(attr => { target.setAttribute(attr.nodeName, attr.nodeValue); source.removeAttribute(attr.name) });\n\n }\n\n\n function replaceWithDiv(node) {\n\n var pmdiv = document.createElement('div');\n\n cloneRemoveAttributes(pmdiv, node);\n\n node.classList.add('container');\n\n pmdiv.classList.add('pm');\n\n node.appendChild(pmdiv);\n\n }\n\n\n function replaceWithVideo(node) {\n\n\n var pmdiv = document.createElement('video');\n\n cloneRemoveAttributes(pmdiv, node);\n\n node.classList.add('container');\n\n pmdiv.classList.add('pm');\n\n // also need to copy all children to the new node\n // https://stackoverflow.com/a/56307130/2455159\n\n pmdiv.append(...node.childNodes);\n\n node.appendChild(pmdiv);\n\n }\n\n\n function replaceWithAudio(node) {\n\n\n var pmdiv = document.createElement('audio');\n\n cloneRemoveAttributes(pmdiv, node);\n\n node.classList.add('container');\n\n pmdiv.classList.add('pm');\n\n // also need to copy all children to the new node\n // https://stackoverflow.com/a/56307130/2455159\n\n pmdiv.append(...node.childNodes);\n\n node.appendChild(pmdiv);\n\n }\n\n\n\n \n\n if (this.dataset.plyrProvider === 'vimeo' || this.dataset.plyrProvider === 'youtube') {\n\n replaceWithDiv(this);\n\n } else if (this.dataset.plyrProvider === 'mp4') {\n\n replaceWithVideo(this);\n\n } else if (this.dataset.plyrProvider === 'mp3') {\n\n replaceWithAudio(this);\n\n }\n\n }\n\n}\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PractiseMasterWebComp);\n\n//# sourceURL=webpack://practisemaster/./src/modules/practisemasterWebComponent.js?");
217
217
 
218
218
  /***/ }),
219
219
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "practisemaster",
3
- "version": "1.0.9",
3
+ "version": "1.0.14",
4
4
  "description": "This is the PractiseMaster repo, treat it with respect! [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/StephanLuis/PractiseMaster)",
5
5
  "dependencies": {
6
6
  "input-duration": "^2.2.3",