1
0
mirror of https://github.com/videojs/video.js.git synced 2025-01-02 06:32:07 +02:00

feat: update exposed utility functions and deprecate several top-level methods of the videojs global (#7761)

This commit is contained in:
Pat O'Neill 2022-05-23 16:23:13 -04:00
parent bd8aebb827
commit 28029d93f4
63 changed files with 1096 additions and 861 deletions

150
package-lock.json generated
View File

@ -834,12 +834,20 @@
}
},
"@babel/plugin-transform-object-assign": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.12.13.tgz",
"integrity": "sha512-4QxDMc0lAOkIBSfCrnSGbAJ+4epDBF2XXwcLXuBcG1xl9u7LrktNVD4+LwhL47XuKVPQ7R25e/WdcV+h97HyZA==",
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.18.6.tgz",
"integrity": "sha512-mQisZ3JfqWh2gVXvfqYCAAyRs6+7oev+myBsTwW5RnPhYXOTuCEw2oe3YgxlXMViXUS53lG8koulI7mJ+8JE+A==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.12.13"
"@babel/helper-plugin-utils": "^7.18.6"
},
"dependencies": {
"@babel/helper-plugin-utils": {
"version": "7.20.2",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz",
"integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==",
"dev": true
}
}
},
"@babel/plugin-transform-object-super": {
@ -1404,7 +1412,7 @@
"abbrev": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz",
"integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==",
"integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=",
"dev": true
},
"accepts": {
@ -2168,7 +2176,7 @@
"binary": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz",
"integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==",
"integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=",
"dev": true,
"requires": {
"buffers": "~0.1.1",
@ -2617,7 +2625,7 @@
"buffers": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz",
"integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==",
"integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=",
"dev": true
},
"builtin-modules": {
@ -2764,7 +2772,7 @@
"chainsaw": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz",
"integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==",
"integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=",
"dev": true,
"requires": {
"traverse": ">=0.3.0 <0.4"
@ -4507,7 +4515,7 @@
"es6-promisify": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
"integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==",
"integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
"dev": true,
"requires": {
"es6-promise": "^4.0.3"
@ -5011,7 +5019,7 @@
"etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
"dev": true
},
"eventemitter3": {
@ -5642,7 +5650,7 @@
"fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
"dev": true
},
"fs-constants": {
@ -7739,7 +7747,7 @@
"istanbul": {
"version": "0.4.5",
"resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz",
"integrity": "sha512-nMtdn4hvK0HjUlzr1DrKSUY8ychprt8dzHOgY2KXsIhHu5PuQQEOTM27gV9Xblyon7aUH/TSFIjRHEODF/FRPg==",
"integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=",
"dev": true,
"requires": {
"abbrev": "1.0.x",
@ -7761,13 +7769,13 @@
"async": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
"integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==",
"integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
"dev": true
},
"escodegen": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz",
"integrity": "sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==",
"integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=",
"dev": true,
"requires": {
"esprima": "^2.7.1",
@ -7780,19 +7788,19 @@
"esprima": {
"version": "2.7.3",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
"integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==",
"integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
"dev": true
},
"estraverse": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz",
"integrity": "sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==",
"integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=",
"dev": true
},
"glob": {
"version": "5.0.15",
"resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
"integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==",
"integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
"dev": true,
"requires": {
"inflight": "^1.0.4",
@ -7805,19 +7813,19 @@
"has-flag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
"integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==",
"integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
"dev": true
},
"resolve": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
"integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==",
"integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
"dev": true
},
"source-map": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz",
"integrity": "sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==",
"integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=",
"dev": true,
"optional": true,
"requires": {
@ -7827,7 +7835,7 @@
"supports-color": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
"integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==",
"integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
"dev": true,
"requires": {
"has-flag": "^1.0.0"
@ -8194,13 +8202,13 @@
"camelcase": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
"integrity": "sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==",
"integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
"dev": true
},
"camelcase-keys": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
"integrity": "sha512-bA/Z/DERHKqoEOrp+qeGKw1QlvEQkGZSc0XaY6VnTxZr+Kv1G5zFwttpjv8qxZ/sBPT4nthwZaAcsAZTJlSKXQ==",
"integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
"dev": true,
"requires": {
"camelcase": "^2.0.0",
@ -8210,7 +8218,7 @@
"dateformat": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz",
"integrity": "sha512-5sFRfAAmbHdIts+eKjR9kYJoF0ViCMVX9yqLu5A7S/v+nd077KgCITOMiirmyCBiZpKLDXbBOkYm6tu7rX/TKg==",
"integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=",
"dev": true,
"requires": {
"get-stdin": "^4.0.1",
@ -8220,7 +8228,7 @@
"find-up": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
"integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==",
"integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
"dev": true,
"requires": {
"path-exists": "^2.0.0",
@ -8236,7 +8244,7 @@
"indent-string": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
"integrity": "sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg==",
"integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
"dev": true,
"requires": {
"repeating": "^2.0.0"
@ -8245,13 +8253,13 @@
"map-obj": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
"integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==",
"integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
"dev": true
},
"meow": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
"integrity": "sha512-TNdwZs0skRlpPpCUK25StC4VH+tP5GgeY1HQOOGP+lQ2xtdkN2VtT/5tiX9k3IWpkBPV9b3LsAWXn4GGi/PrSA==",
"integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
"dev": true,
"requires": {
"camelcase-keys": "^2.0.0",
@ -8281,7 +8289,7 @@
"path-exists": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
"integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==",
"integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
"dev": true,
"requires": {
"pinkie-promise": "^2.0.0"
@ -8290,7 +8298,7 @@
"read-pkg": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
"integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==",
"integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
"dev": true,
"requires": {
"load-json-file": "^1.0.0",
@ -8301,7 +8309,7 @@
"read-pkg-up": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
"integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==",
"integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
"dev": true,
"requires": {
"find-up": "^1.0.0",
@ -8311,7 +8319,7 @@
"redent": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
"integrity": "sha512-qtW5hKzGQZqKoh6JNSD+4lfitfPKGz42e6QwiRmPM5mmKtR0N41AbJRYu0xJi7nhOJ4WDgRkKvAk6tw4WIwR4g==",
"integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
"dev": true,
"requires": {
"indent-string": "^2.1.0",
@ -8321,7 +8329,7 @@
"strip-indent": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
"integrity": "sha512-I5iQq6aFMM62fBEAIB/hXzwJD6EEZ0xEGCX2t7oXqaKPIRgt4WruAQ285BISgdkP+HLGWyeGmNJcpIwFeRYRUA==",
"integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
"dev": true,
"requires": {
"get-stdin": "^4.0.1"
@ -8330,7 +8338,7 @@
"trim-newlines": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
"integrity": "sha512-Nm4cF79FhSTzrLKGDMi3I4utBtFv8qKy4sq1enftf2gMdpqI8oVQTAfySkTz5r49giVzDj88SVZXP4CeYQwjaw==",
"integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
"dev": true
}
}
@ -8368,7 +8376,7 @@
"karma-ie-launcher": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/karma-ie-launcher/-/karma-ie-launcher-1.0.0.tgz",
"integrity": "sha512-ts71ke8pHvw6qdRtq0+7VY3ANLoZuUNNkA8abRaWV13QRPNm7TtSOqyszjHUtuwOWKcsSz4tbUtrNICrQC+SXQ==",
"integrity": "sha1-SXmGhCxJAZA0bNifVJTKmDDG1Zw=",
"dev": true,
"requires": {
"lodash": "^4.6.1"
@ -8682,7 +8690,7 @@
"listenercount": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz",
"integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==",
"integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=",
"dev": true
},
"listr2": {
@ -10008,7 +10016,7 @@
"nopt": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
"integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==",
"integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
"dev": true,
"requires": {
"abbrev": "1"
@ -12234,19 +12242,19 @@
"get-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
"integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==",
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
"dev": true
},
"path-key": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
"integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
"integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
"dev": true
},
"shebang-command": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
"integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
"integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
"dev": true,
"requires": {
"shebang-regex": "^1.0.0"
@ -12255,7 +12263,7 @@
"shebang-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
"integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
"dev": true
}
}
@ -13647,7 +13655,7 @@
"traverse": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz",
"integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==",
"integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=",
"dev": true
},
"trim": {
@ -14348,7 +14356,7 @@
"bluebird": {
"version": "3.4.7",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz",
"integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==",
"integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=",
"dev": true
}
}
@ -14742,32 +14750,62 @@
"integrity": "sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA=="
},
"videojs-generate-karma-config": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/videojs-generate-karma-config/-/videojs-generate-karma-config-7.1.0.tgz",
"integrity": "sha512-j3ed19T+Aidjho+KmzMNKc0k8ySXW45vX+ON3YWR0HOxRFF5VATokIyZv3z0Z/aR5ImoiQAANDs8/zuRafC/mw==",
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/videojs-generate-karma-config/-/videojs-generate-karma-config-8.0.1.tgz",
"integrity": "sha512-IzTUMElW8rUlCu23x3nqofPZpmtfbkaQV2w2cqBNy1H++PXkVgqAqhFJn9F9Tf+0Uhs5EYmYnk0JTpl24rSHGQ==",
"dev": true,
"requires": {
"is-ci": "^2.0.0",
"is-ci": "^3.0.0",
"karma-browserstack-launcher": "~1.4.0",
"karma-chrome-launcher": "^3.1.0",
"karma-coverage": "^1.1.2",
"karma-detect-browsers": "^2.2.6",
"karma-firefox-launcher": "^2.1.0",
"karma-detect-browsers": "^2.3.3",
"karma-firefox-launcher": "^2.1.1",
"karma-ie-launcher": "^1.0.0",
"karma-qunit": "^4.1.1",
"karma-qunit": "^4.1.2",
"karma-safari-applescript-launcher": "~0.1.0",
"karma-static-server": "^1.0.0",
"karma-teamcity-reporter": "^1.1.0",
"qunit": "~2.13.0"
"qunit": "~2.16.0"
},
"dependencies": {
"is-ci": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
"integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
"commander": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.1.0.tgz",
"integrity": "sha512-pRxBna3MJe6HKnBGsDyMv8ETbptw3axEdYHoqNh7gu5oDcew8fs0xnivZGm06Ogk8zGAJ9VX+OPEr2GXEQK4dg==",
"dev": true
},
"globalyzer": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz",
"integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==",
"dev": true
},
"node-watch": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.1.tgz",
"integrity": "sha512-UWblPYuZYrkCQCW5PxAwYSxaELNBLUckrTBBk8xr1/bUgyOkYYTsUcV4e3ytcazFEOyiRyiUrsG37pu6I0I05g==",
"dev": true
},
"qunit": {
"version": "2.16.0",
"resolved": "https://registry.npmjs.org/qunit/-/qunit-2.16.0.tgz",
"integrity": "sha512-88x9t+rRMbB6IrCIUZvYU4pJy7NiBEv7SX8jD4LZAsIj+dV+kwGnFStOmPNvqa6HM96VZMD8CIIFKH2+3qvluA==",
"dev": true,
"requires": {
"ci-info": "^2.0.0"
"commander": "7.1.0",
"node-watch": "0.7.1",
"tiny-glob": "0.2.8"
}
},
"tiny-glob": {
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.8.tgz",
"integrity": "sha512-vkQP7qOslq63XRX9kMswlby99kyO5OvKptw7AMwBVMjXEI7Tb61eoI5DydyEMOseyGS5anDN1VPoVxEvH01q8w==",
"dev": true,
"requires": {
"globalyzer": "0.1.0",
"globrex": "^0.1.2"
}
}
}

View File

@ -99,7 +99,6 @@
},
"devDependencies": {
"@babel/core": "^7.9.0",
"@babel/plugin-transform-object-assign": "^7.8.3",
"@babel/plugin-transform-runtime": "^7.9.0",
"@babel/preset-env": "^7.9.0",
"@rollup/plugin-replace": "^2.4.1",

View File

@ -77,7 +77,6 @@ const primedBabel = babel({
}]
],
plugins: [
'@babel/plugin-transform-object-assign',
['@babel/plugin-transform-runtime', {regenerator: false}]
]
});

View File

@ -4,7 +4,6 @@
import ClickableComponent from './clickable-component.js';
import Component from './component';
import log from './utils/log.js';
import {assign} from './utils/obj';
import keycode from 'keycode';
import {createEl} from './utils/dom.js';
@ -34,12 +33,12 @@ class Button extends ClickableComponent {
createEl(tag, props = {}, attributes = {}) {
tag = 'button';
props = assign({
props = Object.assign({
className: this.buildCSSClass()
}, props);
// Add attributes for button element
attributes = assign({
attributes = Object.assign({
// Necessary since the default button type is "submit"
type: 'button'

View File

@ -4,7 +4,6 @@
import Component from './component';
import * as Dom from './utils/dom.js';
import log from './utils/log.js';
import {assign} from './utils/obj';
import keycode from 'keycode';
/**
@ -68,7 +67,7 @@ class ClickableComponent extends Component {
* The element that gets created.
*/
createEl(tag = 'div', props = {}, attributes = {}) {
props = assign({
props = Object.assign({
className: this.buildCSSClass(),
tabIndex: 0
}, props);
@ -78,7 +77,7 @@ class ClickableComponent extends Component {
}
// Add ARIA attributes for clickable element which is not a native HTML button
attributes = assign({
attributes = Object.assign({
role: 'button'
}, attributes);

View File

@ -9,9 +9,8 @@ import stateful from './mixins/stateful';
import * as Dom from './utils/dom.js';
import * as Fn from './utils/fn.js';
import * as Guid from './utils/guid.js';
import {toTitleCase, toLowerCase} from './utils/string-cases.js';
import mergeOptions from './utils/merge-options.js';
import computedStyle from './utils/computed-style';
import {toTitleCase, toLowerCase} from './utils/str.js';
import {merge} from './utils/obj.js';
import Map from './utils/map.js';
import Set from './utils/set.js';
import keycode from 'keycode';
@ -69,10 +68,10 @@ class Component {
this.parentComponent_ = null;
// Make a copy of prototype.options_ to protect against overriding defaults
this.options_ = mergeOptions({}, this.options_);
this.options_ = merge({}, this.options_);
// Updated options with supplied options
options = this.options_ = mergeOptions(this.options_, options);
options = this.options_ = merge(this.options_, options);
// Get ID from options or options element if one is supplied
this.id_ = options.id || (options.el && options.el.id);
@ -222,7 +221,7 @@ class Component {
/**
* Deep merge of options objects with new options.
* > Note: When both `obj` and `options` contain properties whose values are objects.
* The two properties get merged using {@link module:mergeOptions}
* The two properties get merged using {@link module:obj.merge}
*
* @param {Object} obj
* The object that contains new options.
@ -235,7 +234,7 @@ class Component {
return this.options_;
}
this.options_ = mergeOptions(this.options_, obj);
this.options_ = merge(this.options_, obj);
return this.options_;
}
@ -1081,7 +1080,7 @@ class Component {
throw new Error('currentDimension only accepts width or height value');
}
computedWidthOrHeight = computedStyle(this.el_, widthOrHeight);
computedWidthOrHeight = Dom.computedStyle(this.el_, widthOrHeight);
// remove 'px' from variable and parse as integer
computedWidthOrHeight = parseFloat(computedWidthOrHeight);

View File

@ -3,7 +3,7 @@
*/
import Component from '../../component.js';
import * as Dom from '../../utils/dom.js';
import clamp from '../../utils/clamp';
import {clamp} from '../../utils/num';
import document from 'global/document';
// get the percent width of a time compared to the total end

View File

@ -3,7 +3,7 @@
*/
import Component from '../../component.js';
import * as Dom from '../../utils/dom.js';
import clamp from '../../utils/clamp.js';
import {clamp} from '../../utils/num.js';
import {bind, throttle, UPDATE_REFRESH_INTERVAL} from '../../utils/fn.js';
import {silencePromise} from '../../utils/promise';

View File

@ -6,7 +6,7 @@ import Component from '../../component.js';
import {IS_IOS, IS_ANDROID} from '../../utils/browser.js';
import * as Dom from '../../utils/dom.js';
import * as Fn from '../../utils/fn.js';
import formatTime from '../../utils/format-time.js';
import {formatTime} from '../../utils/time.js';
import {silencePromise} from '../../utils/promise';
import keycode from 'keycode';
import document from 'global/document';

View File

@ -3,7 +3,7 @@
*/
import Component from '../../component';
import * as Dom from '../../utils/dom.js';
import formatTime from '../../utils/format-time.js';
import {formatTime} from '../../utils/time.js';
import * as Fn from '../../utils/fn.js';
/**

View File

@ -4,7 +4,7 @@
import TextTrackButton from './text-track-button.js';
import Component from '../../component.js';
import ChaptersTrackMenuItem from './chapters-track-menu-item.js';
import {toTitleCase} from '../../utils/string-cases.js';
import {toTitleCase} from '../../utils/str.js';
/**
* The button component for toggling and selecting chapters

View File

@ -5,7 +5,7 @@ import TextTrackButton from './text-track-button.js';
import Component from '../../component.js';
import CaptionSettingsMenuItem from './caption-settings-menu-item.js';
import SubsCapsMenuItem from './subs-caps-menu-item.js';
import {toTitleCase} from '../../utils/string-cases.js';
import {toTitleCase} from '../../utils/str.js';
/**
* The button component for toggling and selecting captions and/or subtitles
*

View File

@ -4,7 +4,7 @@
import document from 'global/document';
import Component from '../../component.js';
import * as Dom from '../../utils/dom.js';
import formatTime from '../../utils/format-time.js';
import {formatTime} from '../../utils/time.js';
import log from '../../utils/log.js';
/**

View File

@ -4,7 +4,7 @@
import Slider from '../../slider/slider.js';
import Component from '../../component.js';
import * as Dom from '../../utils/dom.js';
import clamp from '../../utils/clamp.js';
import {clamp} from '../../utils/num.js';
import {IS_IOS, IS_ANDROID} from '../../utils/browser.js';
// Required children

View File

@ -1,5 +1,5 @@
import Component from './component.js';
import mergeOptions from './utils/merge-options.js';
import {merge} from './utils/obj.js';
import window from 'global/window';
import * as Fn from './utils/fn.js';
@ -38,7 +38,7 @@ class LiveTracker extends Component {
*/
constructor(player, options) {
// LiveTracker does not need an element
const options_ = mergeOptions(defaults, options, {createEl: false});
const options_ = merge(defaults, options, {createEl: false});
super(player, options_);

View File

@ -2,7 +2,7 @@
* @file loading-spinner.js
*/
import Component from './component';
import * as dom from './utils/dom';
import * as Dom from './utils/dom';
/**
* A loading spinner for use during waiting/loading events.
@ -20,7 +20,7 @@ class LoadingSpinner extends Component {
createEl() {
const isAudio = this.player_.isAudio();
const playerType = this.localize(isAudio ? 'Audio Player' : 'Video Player');
const controlText = dom.createEl('span', {
const controlText = Dom.createEl('span', {
className: 'vjs-control-text',
textContent: this.localize('{1} is loading.', [playerType])
});

View File

@ -1,7 +1,7 @@
/**
* @file media-error.js
*/
import {assign, isObject} from './utils/obj';
import {isObject} from './utils/obj';
/**
* A Custom `MediaError` class which mimics the standard HTML5 `MediaError` class.
@ -41,7 +41,7 @@ function MediaError(value) {
this.code = value.code;
}
assign(this, value);
Object.assign(this, value);
}
if (!this.message) {

View File

@ -6,7 +6,7 @@ import Component from '../component.js';
import Menu from './menu.js';
import * as Dom from '../utils/dom.js';
import * as Events from '../utils/events.js';
import {toTitleCase} from '../utils/string-cases.js';
import {toTitleCase} from '../utils/str.js';
import { IS_IOS } from '../utils/browser.js';
import document from 'global/document';
import keycode from 'keycode';

View File

@ -3,7 +3,6 @@
*/
import ClickableComponent from '../clickable-component.js';
import Component from '../component.js';
import {assign} from '../utils/obj';
import {MenuKeys} from './menu-keys.js';
import keycode from 'keycode';
import {createEl} from '../utils/dom.js';
@ -64,7 +63,7 @@ class MenuItem extends ClickableComponent {
// The control is textual, not just an icon
this.nonIconControl = true;
const el = super.createEl('li', assign({
const el = super.createEl('li', Object.assign({
className: 'vjs-menu-item',
tabIndex: -1
}, props), attrs);

View File

@ -6,7 +6,6 @@ import window from 'global/window';
import * as Dom from '../utils/dom';
import * as Events from '../utils/events';
import * as Fn from '../utils/fn';
import * as Obj from '../utils/obj';
import EventTarget from '../event-target';
import DomData from '../utils/dom-data';
@ -482,7 +481,7 @@ function evented(target, options = {}) {
target.eventBusEl_ = Dom.createEl('span', {className: 'vjs-event-bus'});
}
Obj.assign(target, EventedMixin);
Object.assign(target, EventedMixin);
if (target.eventedCallbacks) {
target.eventedCallbacks.forEach((callback) => {

View File

@ -103,11 +103,11 @@ const StatefulMixin = {
* Returns the `target`.
*/
function stateful(target, defaultState) {
Obj.assign(target, StatefulMixin);
Object.assign(target, StatefulMixin);
// This happens after the mixing-in because we need to replace the `state`
// added in that step.
target.state = Obj.assign({}, target.state, defaultState);
target.state = Object.assign({}, target.state, defaultState);
// Auto-bind the `handleStateChanged` method of the target object if it exists.
if (typeof target.handleStateChanged === 'function' && isEvented(target)) {

View File

@ -16,15 +16,14 @@ import * as Guid from './utils/guid.js';
import * as browser from './utils/browser.js';
import {IS_CHROME, IS_WINDOWS} from './utils/browser.js';
import log, { createLogger } from './utils/log.js';
import {toTitleCase, titleCaseEquals} from './utils/string-cases.js';
import { createTimeRange } from './utils/time-ranges.js';
import {toTitleCase, titleCaseEquals} from './utils/str.js';
import { createTimeRange } from './utils/time.js';
import { bufferedPercent } from './utils/buffer.js';
import * as stylesheet from './utils/stylesheet.js';
import FullscreenApi from './fullscreen-api.js';
import MediaError from './media-error.js';
import safeParseTuple from 'safe-json-parse/tuple';
import {assign} from './utils/obj';
import mergeOptions from './utils/merge-options.js';
import {merge} from './utils/obj';
import {silencePromise, isPromise} from './utils/promise';
import textTrackConverter from './tracks/text-track-list-converter.js';
import ModalDialog from './modal-dialog';
@ -312,7 +311,7 @@ class Player extends Component {
// which overrides globally set options.
// This latter part coincides with the load order
// (tag must exist before Player)
options = assign(Player.getTagSettings(tag), options);
options = Object.assign(Player.getTagSettings(tag), options);
// Delay the initialization of children because we need to set up
// player properties first, and can't use `this` before `super()`
@ -504,7 +503,7 @@ class Player extends Component {
// as well so they don't need to reach back into the player for options later.
// We also need to do another copy of this.options_ so we don't end up with
// an infinite loop.
const playerOptionsCopy = mergeOptions(this.options_);
const playerOptionsCopy = merge(this.options_);
// Load plugins
if (options.plugins) {
@ -1185,9 +1184,9 @@ class Player extends Component {
techOptions[props.getterName] = this[props.privateName];
});
assign(techOptions, this.options_[titleTechName]);
assign(techOptions, this.options_[camelTechName]);
assign(techOptions, this.options_[techName.toLowerCase()]);
Object.assign(techOptions, this.options_[titleTechName]);
Object.assign(techOptions, this.options_[camelTechName]);
Object.assign(techOptions, this.options_[techName.toLowerCase()]);
if (this.tag) {
techOptions.tag = this.tag;
@ -1525,7 +1524,7 @@ class Player extends Component {
}
// update `currentSource` cache always
this.cache_.source = mergeOptions({}, srcObj, {src, type});
this.cache_.source = merge({}, srcObj, {src, type});
const matchingSources = this.cache_.sources.filter((s) => s.src && s.src === src);
const sourceElSources = [];
@ -4588,7 +4587,7 @@ class Player extends Component {
* An array of of supported languages
*/
languages() {
return mergeOptions(Player.prototype.options_.languages, this.languages_);
return merge(Player.prototype.options_.languages, this.languages_);
}
/**
@ -4599,7 +4598,7 @@ class Player extends Component {
* Object representing the current of track info
*/
toJSON() {
const options = mergeOptions(this.options_);
const options = merge(this.options_);
const tracks = options.tracks;
options.tracks = [];
@ -4608,7 +4607,7 @@ class Player extends Component {
let track = tracks[i];
// deep merge tracks and null out player so no circular references
track = mergeOptions(track);
track = merge(track);
track.player = undefined;
options.tracks[i] = track;
}
@ -4738,18 +4737,18 @@ class Player extends Component {
// Used as a getter.
if (breakpoints === undefined) {
return assign(this.breakpoints_);
return Object.assign(this.breakpoints_);
}
this.breakpoint_ = '';
this.breakpoints_ = assign({}, DEFAULT_BREAKPOINTS, breakpoints);
this.breakpoints_ = Object.assign({}, DEFAULT_BREAKPOINTS, breakpoints);
// When breakpoint definitions change, we need to update the currently
// selected breakpoint.
this.updateCurrentBreakpoint_();
// Clone the breakpoints before returning.
return assign(this.breakpoints_);
return Object.assign(this.breakpoints_);
}
/**
@ -4882,7 +4881,7 @@ class Player extends Component {
this.reset();
// Clone the media object so it cannot be mutated from outside.
this.cache_.media = mergeOptions(media);
this.cache_.media = merge(media);
const {artwork, poster, src, textTracks} = this.cache_.media;
@ -4941,7 +4940,7 @@ class Player extends Component {
return media;
}
return mergeOptions(this.cache_.media);
return merge(this.cache_.media);
}
/**
@ -4979,10 +4978,10 @@ class Player extends Component {
if (err) {
log.error(err);
}
assign(tagOptions, data);
Object.assign(tagOptions, data);
}
assign(baseOptions, tagOptions);
Object.assign(baseOptions, tagOptions);
// Get tag children settings
if (tag.hasChildNodes()) {

View File

@ -4,7 +4,7 @@
import window from 'global/window';
import { debounce } from './utils/fn.js';
import * as Events from './utils/events.js';
import mergeOptions from './utils/merge-options.js';
import { merge } from './utils/obj.js';
import Component from './component.js';
/**
@ -47,7 +47,7 @@ class ResizeManager extends Component {
}
// Only create an element when ResizeObserver isn't available
const options_ = mergeOptions({
const options_ = merge({
createEl: !RESIZE_OBSERVER_AVAILABLE,
reportTouchActivity: false
}, options);

View File

@ -3,9 +3,8 @@
*/
import Component from '../component.js';
import * as Dom from '../utils/dom.js';
import {assign} from '../utils/obj';
import {IS_CHROME} from '../utils/browser.js';
import clamp from '../utils/clamp.js';
import {clamp} from '../utils/num.js';
import keycode from 'keycode';
/**
@ -126,11 +125,11 @@ class Slider extends Component {
createEl(type, props = {}, attributes = {}) {
// Add the slider element class to all sub classes
props.className = props.className + ' vjs-slider';
props = assign({
props = Object.assign({
tabIndex: 0
}, props);
attributes = assign({
attributes = Object.assign({
'role': 'slider',
'aria-valuenow': 0,
'aria-valuemin': 0,

View File

@ -8,12 +8,10 @@ import log from '../utils/log.js';
import * as browser from '../utils/browser.js';
import document from 'global/document';
import window from 'global/window';
import {assign} from '../utils/obj';
import mergeOptions from '../utils/merge-options.js';
import {toTitleCase} from '../utils/string-cases.js';
import {defineLazyProperty, merge} from '../utils/obj';
import {toTitleCase} from '../utils/str.js';
import {NORMAL as TRACK_TYPES, REMOTE} from '../tracks/track-types';
import setupSourceset from './setup-sourceset';
import defineLazyProperty from '../utils/define-lazy-property.js';
import {silencePromise} from '../utils/promise';
/**
@ -387,7 +385,7 @@ class Html5 extends Tech {
// determine if native controls should be used
const tagAttributes = this.options_.tag && Dom.getAttributes(this.options_.tag);
const attributes = mergeOptions({}, tagAttributes);
const attributes = merge({}, tagAttributes);
if (!browser.TOUCH_ENABLED || this.options_.nativeControlsForTouch !== true) {
delete attributes.controls;
@ -395,7 +393,7 @@ class Html5 extends Tech {
Dom.setAttributes(
el,
assign(attributes, {
Object.assign(attributes, {
id: this.options_.techId,
class: 'vjs-tech'
})

View File

@ -3,8 +3,8 @@
*/
import Component from '../component.js';
import Tech from './tech.js';
import {toTitleCase} from '../utils/string-cases.js';
import mergeOptions from '../utils/merge-options.js';
import {toTitleCase} from '../utils/str.js';
import {merge} from '../utils/obj.js';
/**
* The `MediaLoader` is the `Component` that decides which playback technology to load
@ -28,7 +28,7 @@ class MediaLoader extends Component {
*/
constructor(player, options, ready) {
// MediaLoader has no element
const options_ = mergeOptions({createEl: false}, options);
const options_ = merge({createEl: false}, options);
super(player, options_, ready);

View File

@ -2,8 +2,7 @@
* @file middleware.js
* @module middleware
*/
import { assign } from '../utils/obj.js';
import {toTitleCase} from '../utils/string-cases.js';
import {toTitleCase} from '../utils/str.js';
const middlewares = {};
const middlewareInstances = {};
@ -301,7 +300,7 @@ function setSourceHelper(src = {}, middleware = [], next, player, acc = [], last
return setSourceHelper(src, mwrest, next, player, acc, lastRun);
}
mw.setSource(assign({}, src), function(err, _src) {
mw.setSource(Object.assign({}, src), function(err, _src) {
// something happened, try the next middleware on the current level
// make sure to use the old src

View File

@ -1,6 +1,6 @@
import window from 'global/window';
import document from 'global/document';
import mergeOptions from '../utils/merge-options';
import {merge} from '../utils/obj';
import {getAbsoluteURL} from '../utils/url';
/**
@ -183,7 +183,7 @@ const firstSourceWatch = function(tech) {
el[k] = appendWrapper(old[k]);
});
Object.defineProperty(el, 'innerHTML', mergeOptions(innerDescriptor, {
Object.defineProperty(el, 'innerHTML', merge(innerDescriptor, {
set: appendWrapper(innerDescriptor.set)
}));
@ -252,7 +252,7 @@ const setupSourceset = function(tech) {
const oldSetAttribute = el.setAttribute;
const oldLoad = el.load;
Object.defineProperty(el, 'src', mergeOptions(srcDescriptor, {
Object.defineProperty(el, 'src', merge(srcDescriptor, {
set: (v) => {
const retval = srcDescriptor.set.call(el, v);

View File

@ -3,17 +3,16 @@
*/
import Component from '../component';
import mergeOptions from '../utils/merge-options.js';
import * as Fn from '../utils/fn.js';
import log from '../utils/log.js';
import { createTimeRange } from '../utils/time-ranges.js';
import { createTimeRange } from '../utils/time.js';
import { bufferedPercent } from '../utils/buffer.js';
import MediaError from '../media-error.js';
import window from 'global/window';
import document from 'global/document';
import {isPlain} from '../utils/obj';
import {isPlain, merge} from '../utils/obj';
import * as TRACK_TYPES from '../tracks/track-types';
import {toTitleCase, toLowerCase} from '../utils/string-cases.js';
import {toTitleCase, toLowerCase} from '../utils/str.js';
import vtt from 'videojs-vtt.js';
import * as Guid from '../utils/guid.js';
@ -743,7 +742,7 @@ class Tech extends Component {
* The track element that gets created.
*/
createRemoteTextTrack(options) {
const track = mergeOptions(options, {
const track = merge(options, {
tech: this
});

View File

@ -1,6 +1,6 @@
import {AudioTrackKind} from './track-enums';
import Track from './track';
import merge from '../utils/merge-options';
import {merge} from '../utils/obj';
/**
* A representation of a single `AudioTrack`. If it is part of an {@link AudioTrackList}

View File

@ -9,7 +9,7 @@ import window from 'global/window';
import Track from './track.js';
import { isCrossOrigin } from '../utils/url.js';
import XHR from '@videojs/xhr';
import merge from '../utils/merge-options';
import {merge} from '../utils/obj';
/**
* Takes a webvtt file contents and parses it into cues

View File

@ -1,6 +1,6 @@
import {VideoTrackKind} from './track-enums';
import Track from './track';
import merge from '../utils/merge-options';
import {merge} from '../utils/obj';
/**
* A representation of a single `VideoTrack`.

View File

@ -2,7 +2,7 @@
* @file buffer.js
* @module buffer
*/
import { createTimeRange } from './time-ranges.js';
import { createTimeRange } from './time.js';
/**
* Compute the percentage of the media that has been buffered.

View File

@ -1,43 +0,0 @@
/**
* @file computed-style.js
* @module computed-style
*/
import window from 'global/window';
/**
* A safe getComputedStyle.
*
* This is needed because in Firefox, if the player is loaded in an iframe with
* `display:none`, then `getComputedStyle` returns `null`, so, we do a
* null-check to make sure that the player doesn't break in these cases.
*
* @function
* @param {Element} el
* The element you want the computed style of
*
* @param {string} prop
* The property name you want
*
* @see https://bugzilla.mozilla.org/show_bug.cgi?id=548397
*/
function computedStyle(el, prop) {
if (!el || !prop) {
return '';
}
if (typeof window.getComputedStyle === 'function') {
let computedStyleValue;
try {
computedStyleValue = window.getComputedStyle(el);
} catch (e) {
return '';
}
return computedStyleValue ? computedStyleValue.getPropertyValue(prop) || computedStyleValue[prop] : '';
}
return '';
}
export default computedStyle;

View File

@ -1,33 +0,0 @@
/**
* Object.defineProperty but "lazy", which means that the value is only set after
* it retrieved the first time, rather than being set right away.
*
* @param {Object} obj the object to set the property on
* @param {string} key the key for the property to set
* @param {Function} getValue the function used to get the value when it is needed.
* @param {boolean} setter wether a setter shoould be allowed or not
*/
const defineLazyProperty = function(obj, key, getValue, setter = true) {
const set = (value) =>
Object.defineProperty(obj, key, {value, enumerable: true, writable: true});
const options = {
configurable: true,
enumerable: true,
get() {
const value = getValue();
set(value);
return value;
}
};
if (setter) {
options.set = set;
}
return Object.defineProperty(obj, key, options);
};
export default defineLazyProperty;

48
src/js/utils/deprecate.js Normal file
View File

@ -0,0 +1,48 @@
/**
* @file deprecate.js
* @module deprecate
*/
import log from './log.js';
/**
* Decorate a function with a deprecation message the first time it is called.
*
* @param {string} message
* A deprecation message to log the first time the returned function
* is called.
*
* @param {Function} fn
* The function to be deprecated.
*
* @return {Function}
* A wrapper function that will log a deprecation warning the first
* time it is called. The return value will be the return value of
* the wrapped function.
*/
export function deprecate(message, fn) {
let warned = false;
return function(...args) {
if (!warned) {
log.warn(message);
}
warned = true;
return fn.apply(this, args);
};
}
/**
* Internal function used to mark a function as deprecated in the next major
* version with consistent messaging.
*
* @param {number} major The major version where it will be removed
* @param {string} oldName The old function name
* @param {string} newName The new function name
* @param {Function} fn The function to deprecate
* @return {Function} The decorated function
*/
export function deprecateForMajor(major, oldName, newName, fn) {
return deprecate(`${oldName} is deprecated and will be removed in ${major}.0; please use ${newName} instead.`, fn);
}

View File

@ -7,7 +7,6 @@ import window from 'global/window';
import fs from '../fullscreen-api';
import log from './log.js';
import {isObject} from './obj';
import computedStyle from './computed-style';
import * as browser from './browser';
/**
@ -879,3 +878,38 @@ export const $ = createQuerier('querySelector');
*
*/
export const $$ = createQuerier('querySelectorAll');
/**
* A safe getComputedStyle.
*
* This is needed because in Firefox, if the player is loaded in an iframe with
* `display:none`, then `getComputedStyle` returns `null`, so, we do a
* null-check to make sure that the player doesn't break in these cases.
*
* @param {Element} el
* The element you want the computed style of
*
* @param {string} prop
* The property name you want
*
* @see https://bugzilla.mozilla.org/show_bug.cgi?id=548397
*/
export function computedStyle(el, prop) {
if (!el || !prop) {
return '';
}
if (typeof window.getComputedStyle === 'function') {
let computedStyleValue;
try {
computedStyleValue = window.getComputedStyle(el);
} catch (e) {
return '';
}
return computedStyleValue ? computedStyleValue.getPropertyValue(prop) || computedStyleValue[prop] : '';
}
return '';
}

View File

@ -1,94 +0,0 @@
/**
* @file format-time.js
* @module format-time
*/
/**
* Format seconds as a time string, H:MM:SS or M:SS. Supplying a guide (in
* seconds) will force a number of leading zeros to cover the length of the
* guide.
*
* @private
* @param {number} seconds
* Number of seconds to be turned into a string
*
* @param {number} guide
* Number (in seconds) to model the string after
*
* @return {string}
* Time formatted as H:MM:SS or M:SS
*/
const defaultImplementation = function(seconds, guide) {
seconds = seconds < 0 ? 0 : seconds;
let s = Math.floor(seconds % 60);
let m = Math.floor(seconds / 60 % 60);
let h = Math.floor(seconds / 3600);
const gm = Math.floor(guide / 60 % 60);
const gh = Math.floor(guide / 3600);
// handle invalid times
if (isNaN(seconds) || seconds === Infinity) {
// '-' is false for all relational operators (e.g. <, >=) so this setting
// will add the minimum number of fields specified by the guide
h = m = s = '-';
}
// Check if we need to show hours
h = (h > 0 || gh > 0) ? h + ':' : '';
// If hours are showing, we may need to add a leading zero.
// Always show at least one digit of minutes.
m = (((h || gm >= 10) && m < 10) ? '0' + m : m) + ':';
// Check if leading zero is need for seconds
s = (s < 10) ? '0' + s : s;
return h + m + s;
};
// Internal pointer to the current implementation.
let implementation = defaultImplementation;
/**
* Replaces the default formatTime implementation with a custom implementation.
*
* @param {Function} customImplementation
* A function which will be used in place of the default formatTime
* implementation. Will receive the current time in seconds and the
* guide (in seconds) as arguments.
*/
export function setFormatTime(customImplementation) {
implementation = customImplementation;
}
/**
* Resets formatTime to the default implementation.
*/
export function resetFormatTime() {
implementation = defaultImplementation;
}
/**
* Delegates to either the default time formatting function or a custom
* function supplied via `setFormatTime`.
*
* Formats seconds as a time string (H:MM:SS or M:SS). Supplying a
* guide (in seconds) will force a number of leading zeros to cover the
* length of the guide.
*
* @static
* @example formatTime(125, 600) === "02:05"
* @param {number} seconds
* Number of seconds to be turned into a string
*
* @param {number} guide
* Number (in seconds) to model the string after
*
* @return {string}
* Time formatted as H:MM:SS or M:SS
*/
function formatTime(seconds, guide = seconds) {
return implementation(seconds, guide);
}
export default formatTime;

View File

@ -1,49 +0,0 @@
/**
* @file merge-options.js
* @module merge-options
*/
import {each, isPlain} from './obj';
/**
* Merge two objects recursively.
*
* Performs a deep merge like
* {@link https://lodash.com/docs/4.17.10#merge|lodash.merge}, but only merges
* plain objects (not arrays, elements, or anything else).
*
* Non-plain object values will be copied directly from the right-most
* argument.
*
* @static
* @param {Object[]} sources
* One or more objects to merge into a new object.
*
* @return {Object}
* A new object that is the merged result of all sources.
*/
function mergeOptions(...sources) {
const result = {};
sources.forEach(source => {
if (!source) {
return;
}
each(source, (value, key) => {
if (!isPlain(value)) {
result[key] = value;
return;
}
if (!isPlain(result[key])) {
result[key] = {};
}
result[key] = mergeOptions(result[key], value);
});
});
return result;
}
export default mergeOptions;

View File

@ -1,3 +1,8 @@
/**
* @file num.js
* @module num
*/
/**
* Keep a number between a min and a max value
*
@ -12,10 +17,8 @@
* @return {number}
* the clamped number
*/
const clamp = function(number, min, max) {
export function clamp(number, min, max) {
number = Number(number);
return Math.min(max, Math.max(min, isNaN(number) ? min : number));
};
export default clamp;
}

View File

@ -80,31 +80,6 @@ export function reduce(object, fn, initial = 0) {
return keys(object).reduce((accum, key) => fn(accum, object[key], key), initial);
}
/**
* Object.assign-style object shallow merge/extend.
*
* @param {Object} target
* @param {Object} ...sources
* @return {Object}
*/
export function assign(target, ...sources) {
if (Object.assign) {
return Object.assign(target, ...sources);
}
sources.forEach(source => {
if (!source) {
return;
}
each(source, (value, key) => {
target[key] = value;
});
});
return target;
}
/**
* Returns whether a value is an object of any kind - including DOM nodes,
* arrays, regular expressions, etc. Not functions, though.
@ -131,3 +106,76 @@ export function isPlain(value) {
toString.call(value) === '[object Object]' &&
value.constructor === Object;
}
/**
* Merge two objects recursively.
*
* Performs a deep merge like
* {@link https://lodash.com/docs/4.17.10#merge|lodash.merge}, but only merges
* plain objects (not arrays, elements, or anything else).
*
* Non-plain object values will be copied directly from the right-most
* argument.
*
* @param {Object[]} sources
* One or more objects to merge into a new object.
*
* @return {Object}
* A new object that is the merged result of all sources.
*/
export function merge(...sources) {
const result = {};
sources.forEach(source => {
if (!source) {
return;
}
each(source, (value, key) => {
if (!isPlain(value)) {
result[key] = value;
return;
}
if (!isPlain(result[key])) {
result[key] = {};
}
result[key] = merge(result[key], value);
});
});
return result;
}
/**
* Object.defineProperty but "lazy", which means that the value is only set after
* it is retrieved the first time, rather than being set right away.
*
* @param {Object} obj the object to set the property on
* @param {string} key the key for the property to set
* @param {Function} getValue the function used to get the value when it is needed.
* @param {boolean} setter whether a setter should be allowed or not
*/
export function defineLazyProperty(obj, key, getValue, setter = true) {
const set = (value) =>
Object.defineProperty(obj, key, {value, enumerable: true, writable: true});
const options = {
configurable: true,
enumerable: true,
get() {
const value = getValue();
set(value);
return value;
}
};
if (setter) {
options.set = set;
}
return Object.defineProperty(obj, key, options);
}

View File

@ -1,5 +1,5 @@
/**
* @file string-cases.js
* @file str.js
* @module to-lower-case
*/

View File

@ -1,6 +1,6 @@
/**
* @file time-ranges.js
* @module time-ranges
* @file time.js
* @module time
*/
import window from 'global/window';
@ -28,10 +28,10 @@ import window from 'global/window';
* @property {number} length
* The number of time ranges represented by this object.
*
* @property {module:time-ranges~TimeRangeIndex} start
* @property {module:time~TimeRangeIndex} start
* Returns the time offset at which a specified time range begins.
*
* @property {module:time-ranges~TimeRangeIndex} end
* @property {module:time~TimeRangeIndex} end
* Returns the time offset at which a specified time range ends.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/TimeRanges
@ -144,3 +144,90 @@ export function createTimeRanges(start, end) {
}
export { createTimeRanges as createTimeRange };
/**
* Format seconds as a time string, H:MM:SS or M:SS. Supplying a guide (in
* seconds) will force a number of leading zeros to cover the length of the
* guide.
*
* @private
* @param {number} seconds
* Number of seconds to be turned into a string
*
* @param {number} guide
* Number (in seconds) to model the string after
*
* @return {string}
* Time formatted as H:MM:SS or M:SS
*/
const defaultImplementation = function(seconds, guide) {
seconds = seconds < 0 ? 0 : seconds;
let s = Math.floor(seconds % 60);
let m = Math.floor(seconds / 60 % 60);
let h = Math.floor(seconds / 3600);
const gm = Math.floor(guide / 60 % 60);
const gh = Math.floor(guide / 3600);
// handle invalid times
if (isNaN(seconds) || seconds === Infinity) {
// '-' is false for all relational operators (e.g. <, >=) so this setting
// will add the minimum number of fields specified by the guide
h = m = s = '-';
}
// Check if we need to show hours
h = (h > 0 || gh > 0) ? h + ':' : '';
// If hours are showing, we may need to add a leading zero.
// Always show at least one digit of minutes.
m = (((h || gm >= 10) && m < 10) ? '0' + m : m) + ':';
// Check if leading zero is need for seconds
s = (s < 10) ? '0' + s : s;
return h + m + s;
};
// Internal pointer to the current implementation.
let implementation = defaultImplementation;
/**
* Replaces the default formatTime implementation with a custom implementation.
*
* @param {Function} customImplementation
* A function which will be used in place of the default formatTime
* implementation. Will receive the current time in seconds and the
* guide (in seconds) as arguments.
*/
export function setFormatTime(customImplementation) {
implementation = customImplementation;
}
/**
* Resets formatTime to the default implementation.
*/
export function resetFormatTime() {
implementation = defaultImplementation;
}
/**
* Delegates to either the default time formatting function or a custom
* function supplied via `setFormatTime`.
*
* Formats seconds as a time string (H:MM:SS or M:SS). Supplying a
* guide (in seconds) will force a number of leading zeros to cover the
* length of the guide.
*
* @example formatTime(125, 600) === "02:05"
* @param {number} seconds
* Number of seconds to be turned into a string
*
* @param {number} guide
* Number (in seconds) to model the string after
*
* @return {string}
* Time formatted as H:MM:SS or M:SS
*/
export function formatTime(seconds, guide = seconds) {
return implementation(seconds, guide);
}

View File

@ -18,29 +18,25 @@ import EventTarget from './event-target';
import * as Events from './utils/events.js';
import Player from './player';
import Plugin from './plugin';
import mergeOptions from './utils/merge-options.js';
import * as Fn from './utils/fn.js';
import * as Num from './utils/num.js';
import * as Str from './utils/str.js';
import TextTrack from './tracks/text-track.js';
import AudioTrack from './tracks/audio-track.js';
import VideoTrack from './tracks/video-track.js';
import { createTimeRanges } from './utils/time-ranges.js';
import formatTime, { setFormatTime, resetFormatTime } from './utils/format-time.js';
import { deprecateForMajor } from './utils/deprecate';
import * as Time from './utils/time.js';
import log, { createLogger } from './utils/log.js';
import * as Dom from './utils/dom.js';
import * as browser from './utils/browser.js';
import * as Url from './utils/url.js';
import * as Obj from './utils/obj';
import clamp from './utils/clamp';
import { isPromise, silencePromise } from './utils/promise';
import * as StringCases from './utils/string-cases';
import computedStyle from './utils/computed-style.js';
import extend from './extend.js';
import xhr from '@videojs/xhr';
// Include the built-in techs
import Tech from './tech/tech.js';
import { use as middlewareUse, TERMINATOR } from './tech/middleware.js';
import defineLazyProperty from './utils/define-lazy-property.js';
/**
* Normalize an `id` value by trimming off a leading `#`
@ -91,18 +87,11 @@ const normalizeId = (id) => id.indexOf('#') === 0 ? id.slice(1) : id;
*
* @borrows AudioTrack as AudioTrack
* @borrows Component.getComponent as getComponent
* @borrows module:computed-style~computedStyle as computedStyle
* @borrows module:events.on as on
* @borrows module:events.one as one
* @borrows module:events.off as off
* @borrows module:events.trigger as trigger
* @borrows EventTarget as EventTarget
* @borrows module:extend~extend as extend
* @borrows module:fn.bind as bind
* @borrows module:format-time.formatTime as formatTime
* @borrows module:format-time.resetFormatTime as resetFormatTime
* @borrows module:format-time.setFormatTime as setFormatTime
* @borrows module:merge-options.mergeOptions as mergeOptions
* @borrows module:middleware.use as use
* @borrows Player.players as players
* @borrows Plugin.registerPlugin as registerPlugin
@ -113,10 +102,6 @@ const normalizeId = (id) => id.indexOf('#') === 0 ? id.slice(1) : id;
* @borrows Tech.getTech as getTech
* @borrows Tech.registerTech as registerTech
* @borrows TextTrack as TextTrack
* @borrows module:time-ranges.createTimeRanges as createTimeRange
* @borrows module:time-ranges.createTimeRanges as createTimeRanges
* @borrows module:url.isCrossOrigin as isCrossOrigin
* @borrows module:url.parseUrl as parseUrl
* @borrows VideoTrack as VideoTrack
*
* @param {string|Element} id
@ -171,14 +156,14 @@ function videojs(id, options, ready) {
}
hooks('beforesetup').forEach((hookFunction) => {
const opts = hookFunction(el, mergeOptions(options));
const opts = hookFunction(el, Obj.merge(options));
if (!Obj.isObject(opts) || Array.isArray(opts)) {
log.error('please return an object in beforesetup hooks');
return;
}
options = mergeOptions(options, opts);
options = Obj.merge(options, opts);
});
// We get the current "Player" component here in case an integration has
@ -367,24 +352,56 @@ Object.defineProperty(videojs.middleware, 'TERMINATOR', {
videojs.browser = browser;
/**
* Use {@link module:browser.TOUCH_ENABLED|browser.TOUCH_ENABLED} instead; only
* included for backward-compatibility with 4.x.
* A reference to the {@link module:obj|obj utility module} as an object.
*
* @deprecated Since version 5.0, use {@link module:browser.TOUCH_ENABLED|browser.TOUCH_ENABLED instead.
* @type {boolean}
* @type {Object}
* @see {@link module:obj|obj}
*/
videojs.TOUCH_ENABLED = browser.TOUCH_ENABLED;
videojs.obj = Obj;
/**
* Deprecated reference to the {@link module:extend~extend|extend function}
*
* @type {Function}
* @see {@link module:extend~extend|extend}
* @deprecated Deprecated and will be removed in 9.0. Please use native ES6 classes instead.
*/
videojs.extend = deprecateForMajor(9, 'videojs.extend', 'native ES6 classes', extend);
/**
* Deprecated reference to the {@link module:obj.merge|merge function}
*
* @type {Function}
* @see {@link module:obj.merge|merge}
* @deprecated Deprecated and will be removed in 9.0. Please use videojs.obj.merge instead.
*/
videojs.mergeOptions = deprecateForMajor(9, 'videojs.mergeOptions', 'videojs.obj.merge', Obj.merge);
/**
* Deprecated reference to the {@link module:obj.defineLazyProperty|defineLazyProperty function}
*
* @type {Function}
* @see {@link module:obj.defineLazyProperty|defineLazyProperty}
* @deprecated Deprecated and will be removed in 9.0. Please use videojs.obj.defineLazyProperty instead.
*/
videojs.defineLazyProperty = deprecateForMajor(9, 'videojs.defineLazyProperty', 'videojs.obj.defineLazyProperty', Obj.defineLazyProperty);
/**
* Deprecated reference to the {@link module:fn.bind|fn.bind function}
*
* @type {Function}
* @see {@link module:fn.bind|fn.bind}
* @deprecated Deprecated and will be removed in 9.0. Please use native Function.prototype.bind instead.
*/
videojs.bind = deprecateForMajor(9, 'videojs.bind', 'native Function.prototype.bind', Fn.bind);
videojs.extend = extend;
videojs.mergeOptions = mergeOptions;
videojs.bind = Fn.bind;
videojs.registerPlugin = Plugin.registerPlugin;
videojs.deregisterPlugin = Plugin.deregisterPlugin;
/**
* Deprecated method to register a plugin with Video.js
*
* @deprecated videojs.plugin() is deprecated; use videojs.registerPlugin() instead
* @deprecated Deprecated and will be removed in 9.0. Use videojs.registerPlugin() instead.
*
* @param {string} name
* The plugin name
@ -417,7 +434,7 @@ videojs.getPluginVersion = Plugin.getPluginVersion;
videojs.addLanguage = function(code, data) {
code = ('' + code).toLowerCase();
videojs.options.languages = mergeOptions(
videojs.options.languages = Obj.merge(
videojs.options.languages,
{[code]: data}
);
@ -434,13 +451,80 @@ videojs.addLanguage = function(code, data) {
videojs.log = log;
videojs.createLogger = createLogger;
videojs.createTimeRange = videojs.createTimeRanges = createTimeRanges;
videojs.formatTime = formatTime;
videojs.setFormatTime = setFormatTime;
videojs.resetFormatTime = resetFormatTime;
videojs.parseUrl = Url.parseUrl;
videojs.isCrossOrigin = Url.isCrossOrigin;
/**
* A reference to the {@link module:time|time utility module} as an object.
*
* @type {Object}
* @see {@link module:time|time}
*/
videojs.time = Time;
/**
* Deprecated reference to the {@link module:time.createTimeRanges|createTimeRanges function}
*
* @type {Function}
* @see {@link module:time.createTimeRanges|createTimeRanges}
* @deprecated Deprecated and will be removed in 9.0. Please use videojs.time.createTimeRanges instead.
*/
videojs.createTimeRange = deprecateForMajor(9, 'videojs.createTimeRange', 'videojs.time.createTimeRanges', Time.createTimeRanges);
/**
* Deprecated reference to the {@link module:time.createTimeRanges|createTimeRanges function}
*
* @type {Function}
* @see {@link module:time.createTimeRanges|createTimeRanges}
* @deprecated Deprecated and will be removed in 9.0. Please use videojs.time.createTimeRanges instead.
*/
videojs.createTimeRanges = deprecateForMajor(9, 'videojs.createTimeRanges', 'videojs.time.createTimeRanges', Time.createTimeRanges);
/**
* Deprecated reference to the {@link module:time.formatTime|formatTime function}
*
* @type {Function}
* @see {@link module:time.formatTime|formatTime}
* @deprecated Deprecated and will be removed in 9.0. Please use videojs.time.format instead.
*/
videojs.formatTime = deprecateForMajor(9, 'videojs.formatTime', 'videojs.time.formatTime', Time.formatTime);
/**
* Deprecated reference to the {@link module:time.setFormatTime|setFormatTime function}
*
* @type {Function}
* @see {@link module:time.setFormatTime|setFormatTime}
* @deprecated Deprecated and will be removed in 9.0. Please use videojs.time.setFormat instead.
*/
videojs.setFormatTime = deprecateForMajor(9, 'videojs.setFormatTime', 'videojs.time.setFormatTime', Time.setFormatTime);
/**
* Deprecated reference to the {@link module:time.resetFormatTime|resetFormatTime function}
*
* @type {Function}
* @see {@link module:time.resetFormatTime|resetFormatTime}
* @deprecated Deprecated and will be removed in 9.0. Please use videojs.time.resetFormat instead.
*/
videojs.resetFormatTime = deprecateForMajor(9, 'videojs.resetFormatTime', 'videojs.time.resetFormatTime', Time.resetFormatTime);
/**
* Deprecated reference to the {@link module:url.parseUrl|Url.parseUrl function}
*
* @type {Function}
* @see {@link module:url.parseUrl|parseUrl}
* @deprecated Deprecated and will be removed in 9.0. Please use videojs.url.parseUrl instead.
*/
videojs.parseUrl = deprecateForMajor(9, 'videojs.parseUrl', 'videojs.url.parseUrl', Url.parseUrl);
/**
* Deprecated reference to the {@link module:url.isCrossOrigin|Url.isCrossOrigin function}
*
* @type {Function}
* @see {@link module:url.isCrossOrigin|isCrossOrigin}
* @deprecated Deprecated and will be removed in 9.0. Please use videojs.url.isCrossOrigin instead.
*/
videojs.isCrossOrigin = deprecateForMajor(9, 'videojs.isCrossOrigin', 'videojs.url.isCrossOrigin', Url.isCrossOrigin);
videojs.EventTarget = EventTarget;
videojs.any = Events.any;
videojs.on = Events.on;
videojs.one = Events.one;
videojs.off = Events.off;
@ -484,36 +568,50 @@ videojs.VideoTrack = VideoTrack;
};
});
videojs.computedStyle = computedStyle;
videojs.computedStyle = deprecateForMajor(9, 'videojs.computedStyle', 'videojs.dom.computedStyle', Dom.computedStyle);
/**
* A reference to the {@link module:dom|DOM utility module} as an object.
*
* @type {Object}
* @see {@link module:dom|dom}
* @see {@link module:dom|dom}
*/
videojs.dom = Dom;
/**
* A reference to the {@link module:fn|fn utility module} as an object.
*
* @type {Object}
* @see {@link module:fn|fn}
*/
videojs.fn = Fn;
/**
* A reference to the {@link module:num|num utility module} as an object.
*
* @type {Object}
* @see {@link module:num|num}
*/
videojs.num = Num;
/**
* A reference to the {@link module:str|str utility module} as an object.
*
* @type {Object}
* @see {@link module:str|str}
*/
videojs.str = Str;
/**
* A reference to the {@link module:url|URL utility module} as an object.
*
* @type {Object}
* @see {@link module:url|url}
* @see {@link module:url|url}
*/
videojs.url = Url;
videojs.defineLazyProperty = defineLazyProperty;
// Adding less ambiguous text for fullscreen button.
// In a major update this could become the default text and key.
videojs.addLanguage('en', {'Non-Fullscreen': 'Exit Fullscreen'});
videojs.clamp = clamp;
videojs.fn = Fn;
videojs.obj = Obj;
videojs.isPromise = isPromise;
videojs.silencePromise = silencePromise;
videojs.strings = StringCases;
export default videojs;

View File

@ -1,6 +1,7 @@
/* eslint-env qunit */
import Player from '../../src/js/player.js';
import videojs from '../../src/js/video.js';
import {merge} from '../../src/js/utils/obj';
import TestHelpers from './test-helpers.js';
import document from 'global/document';
import window from 'global/window';
@ -63,7 +64,7 @@ QUnit.module('autoplay', {
videoTag.setAttribute(a, attributes[a]);
});
this.player = videojs(videoTag.id, videojs.mergeOptions({techOrder: ['techFaker']}, options));
this.player = videojs(videoTag.id, merge({techOrder: ['techFaker']}, options));
const oldMuted = this.player.muted;
this.player.play = () => {

View File

@ -1,6 +1,6 @@
/* eslint-env qunit */
import TestHelpers from './test-helpers.js';
import {createTimeRanges} from '../../src/js/utils/time-ranges.js';
import {createTimeRanges} from '../../src/js/utils/time.js';
import sinon from 'sinon';
QUnit.module('LiveTracker', () => {

View File

@ -3,7 +3,7 @@ import TestHelpers from './test-helpers.js';
import sinon from 'sinon';
import window from 'global/window';
import * as middleware from '../../src/js/tech/middleware.js';
import videojs from '../../src/js/video.js';
import {merge} from '../../src/js/utils/obj';
const middleWareTerminations = ['terminates', 'does not-terminate'];
const playReturnValues = ['non-promise', 'promise'];
@ -51,7 +51,7 @@ const mainModule = function(playReturnValue, middlewareTermination, subhooks) {
};
this.checkState = (assertName, options = {}) => {
const expectedState = videojs.mergeOptions({
const expectedState = merge({
playCalls: 0,
techLoaded: false,
techReady: false,

View File

@ -1,9 +1,8 @@
/* eslint-env qunit */
import sinon from 'sinon';
import TestHelpers from './test-helpers';
import {assign} from '../../src/js/utils/obj';
const getExpectedBreakpoints = (o) => assign({}, {
const getExpectedBreakpoints = (o) => Object.assign({}, {
tiny: 210,
xsmall: 320,
small: 425,

View File

@ -1,8 +1,8 @@
/* eslint-env qunit */
import TestHelpers from './test-helpers.js';
import sinon from 'sinon';
import computedStyle from '../../src/js/utils/computed-style.js';
import { createTimeRange } from '../../src/js/utils/time-ranges.js';
import { computedStyle } from '../../src/js/utils/dom.js';
import { createTimeRange } from '../../src/js/utils/time.js';
QUnit.module('SeekToLive', {
beforeEach() {

View File

@ -1,7 +1,7 @@
// Fake a media playback tech controller so that player tests
// can run without HTML5 which PhantomJS does not support.
import Tech from '../../../src/js/tech/tech.js';
import {createTimeRanges} from '../../../src/js/utils/time-ranges.js';
import {createTimeRanges} from '../../../src/js/utils/time.js';
/**
* @class
*/

View File

@ -2,7 +2,7 @@
import Tech from '../../../src/js/tech/tech.js';
import Html5 from '../../../src/js/tech/html5.js';
import Button from '../../../src/js/button.js';
import { createTimeRange } from '../../../src/js/utils/time-ranges.js';
import { createTimeRange } from '../../../src/js/utils/time.js';
import extend from '../../../src/js/extend.js';
import MediaError from '../../../src/js/media-error.js';
import AudioTrack from '../../../src/js/tracks/audio-track';

View File

@ -0,0 +1,105 @@
/* eslint-env qunit */
import window from 'global/window';
import sinon from 'sinon';
import {deprecate, deprecateForMajor} from '../../../src/js/utils/deprecate.js';
QUnit.module('utils/deprecate', {
beforeEach() {
// Back up the original console.
this.originalConsole = window.console;
// Replace the native console for testing. In IE8 `console.log` is not a
// 'function' so sinon chokes on it when trying to spy:
// https://github.com/cjohansen/Sinon.JS/issues/386
//
// Instead we'll temporarily replace them with no-op functions
window.console = {
debug: sinon.spy(),
info: sinon.spy(),
log: sinon.spy(),
warn: sinon.spy(),
error: sinon.spy()
};
},
afterEach() {
// Restore the native/original console.
window.console = this.originalConsole;
}
}, function() {
QUnit.module('deprecate');
QUnit.test('should pass through arguments to a function and return expected value', function(assert) {
assert.expect(1);
const test = deprecate('test', (...args) => args);
const result = test(1, 2, 3);
assert.deepEqual(result, [1, 2, 3]);
});
QUnit.test('should maintain the correct "this" value', function(assert) {
assert.expect(1);
const that = {};
const test = deprecate('test', function() {
return this;
}.bind(that));
const result = test();
assert.strictEqual(result, that, 'the "this" value was returned as the expected object');
});
QUnit.test('should log the specified message only once', function(assert) {
assert.expect(2);
const test = deprecate('test', function() {});
test();
test();
test();
assert.ok(window.console.warn.calledOnce);
assert.deepEqual(window.console.warn.firstCall.args, ['VIDEOJS:', 'WARN:', 'test']);
});
QUnit.module('deprecateForMajor');
QUnit.test('should pass through arguments to a function and return expected value', function(assert) {
assert.expect(1);
const test = deprecateForMajor(1, 'A', 'B', (...args) => args);
const result = test(1, 2, 3);
assert.deepEqual(result, [1, 2, 3]);
});
QUnit.test('should maintain the correct "this" value', function(assert) {
assert.expect(1);
const that = {};
const test = deprecateForMajor(1, 'A', 'B', function() {
return this;
}.bind(that));
const result = test();
assert.strictEqual(result, that, 'the "this" value was returned as the expected object');
});
QUnit.test('should log the expected message only once', function(assert) {
assert.expect(2);
const test = deprecateForMajor(1, 'A', 'B', function() {});
test();
test();
test();
assert.ok(window.console.warn.calledOnce);
assert.deepEqual(window.console.warn.firstCall.args, ['VIDEOJS:', 'WARN:', 'A is deprecated and will be removed in 1.0; please use B instead.']);
});
});

View File

@ -4,7 +4,7 @@ import sinon from 'sinon';
import * as Dom from '../../../src/js/utils/dom.js';
import TestHelpers from '../test-helpers.js';
QUnit.module('dom');
QUnit.module('utils/dom');
QUnit.test('should create an element', function(assert) {
const div = Dom.createEl();

View File

@ -1,8 +1,8 @@
/* eslint-env qunit */
import sinon from 'sinon';
import * as Fn from '../../../src/js/utils/fn.js';
import * as Fn from '../../../src/js/utils/fn';
QUnit.module('fn', {
QUnit.module('utils/fn', {
beforeEach() {
this.clock = sinon.useFakeTimers();
},
@ -12,6 +12,8 @@ QUnit.module('fn', {
});
QUnit.test('should add context to a function', function(assert) {
assert.expect(1);
const newContext = { test: 'obj'};
const asdf = function() {
assert.ok(this === newContext);
@ -22,6 +24,8 @@ QUnit.test('should add context to a function', function(assert) {
});
QUnit.test('should throttle functions properly', function(assert) {
assert.expect(3);
const tester = sinon.spy();
const throttled = Fn.throttle(tester, 100);
@ -45,3 +49,65 @@ QUnit.test('should throttle functions properly', function(assert) {
assert.strictEqual(tester.callCount, 3, 'the throttled function has been called the correct number of times');
});
QUnit.test('should debounce functions properly', function(assert) {
assert.expect(6);
const tester = sinon.spy();
const debounced = Fn.debounce(tester, 100);
// Called twice on each assertion to ensure that multiple calls only result
// in a call to the inner function.
debounced();
debounced();
assert.strictEqual(tester.callCount, 0, 'the debounced function was NOT called because no time has elapsed');
this.clock.tick(100);
assert.strictEqual(tester.callCount, 1, 'the debounced function was called because enough time elapsed');
this.clock.tick(100);
assert.strictEqual(tester.callCount, 1, 'the debounced function was NOT called again even though time elapsed');
debounced();
debounced();
assert.strictEqual(tester.callCount, 1, 'the debounced function was NOT called because no time has elapsed since invocation');
this.clock.tick(50);
assert.strictEqual(tester.callCount, 1, 'the debounced function was NOT called because the clock has NOT ticket forward enough');
this.clock.tick(50);
assert.strictEqual(tester.callCount, 2, 'the debounced function was called because the clock ticked forward enough');
});
QUnit.test('may immediately invoke debounced functions', function(assert) {
assert.expect(2);
const tester = sinon.spy();
const debounced = Fn.debounce(tester, 100, true);
// Called twice on each assertion to ensure that multiple calls only result
// in a call to the inner function.
debounced();
debounced();
assert.strictEqual(tester.callCount, 1, 'the debounced function was called because true was passed');
this.clock.tick(100);
assert.strictEqual(tester.callCount, 1, 'the debounced function was NOT called because it has only been invoked once');
});
QUnit.test('may cancel debounced functions', function(assert) {
assert.expect(2);
const tester = sinon.spy();
const debounced = Fn.debounce(tester, 100);
debounced();
this.clock.tick(50);
debounced.cancel();
this.clock.tick(50);
assert.strictEqual(tester.callCount, 0, 'the debounced function was NOT called because it was cancelled');
debounced();
this.clock.tick(100);
assert.strictEqual(tester.callCount, 1, 'the debounced function was called because it was NOT cancelled');
});

View File

@ -1,50 +0,0 @@
/* eslint-env qunit */
import formatTime, { setFormatTime, resetFormatTime } from '../../../src/js/utils/format-time.js';
QUnit.module('format-time standard implementation', {
afterEach: resetFormatTime()
});
QUnit.test('should format time as a string', function(assert) {
assert.ok(formatTime(1) === '0:01');
assert.ok(formatTime(10) === '0:10');
assert.ok(formatTime(60) === '1:00');
assert.ok(formatTime(600) === '10:00');
assert.ok(formatTime(3600) === '1:00:00');
assert.ok(formatTime(36000) === '10:00:00');
assert.ok(formatTime(360000) === '100:00:00');
// Using guide should provide extra leading zeros
assert.ok(formatTime(1, 1) === '0:01');
assert.ok(formatTime(1, 10) === '0:01');
assert.ok(formatTime(1, 60) === '0:01');
assert.ok(formatTime(1, 600) === '00:01');
assert.ok(formatTime(1, 3600) === '0:00:01');
// Don't do extra leading zeros for hours
assert.ok(formatTime(1, 36000) === '0:00:01');
assert.ok(formatTime(1, 360000) === '0:00:01');
// Do not display negative time
assert.ok(formatTime(-1) === '0:00');
assert.ok(formatTime(-1, 3600) === '0:00:00');
});
QUnit.test('should format invalid times as dashes', function(assert) {
assert.equal(formatTime(Infinity, 90), '-:-');
assert.equal(formatTime(NaN), '-:-');
assert.equal(formatTime(10, Infinity), '0:00:10');
assert.equal(formatTime(90, NaN), '1:30');
});
QUnit.test('setFormatTime', function(assert) {
setFormatTime((seconds, guide) => `custom:${seconds}:${guide}`);
assert.equal(formatTime(1, 2), 'custom:1:2', 'it should replace the default formatTime implementation');
});
QUnit.test('resetFormatTime ', function(assert) {
setFormatTime((seconds, guide) => `custom:${seconds}:${guide}`);
assert.equal(formatTime(1, 2), 'custom:1:2');
resetFormatTime();
assert.equal(formatTime(1), '0:01', 'it should reset formatTime to the default implementation');
});

View File

@ -1,36 +0,0 @@
/* eslint-env qunit */
import mergeOptions from '../../../src/js/utils/merge-options.js';
QUnit.module('merge-options');
QUnit.test('should merge options objects', function(assert) {
const ob1 = {
a: true,
b: { b1: true, b2: true, b3: true },
c: true
};
const ob2 = {
// override value
a: false,
// merge sub-option values
b: { b1: true, b2: false, b4: true },
// add new option
d: true
};
const ob3 = mergeOptions(ob1, ob2);
assert.deepEqual(ob3, {
a: false,
b: { b1: true, b2: false, b3: true, b4: true },
c: true,
d: true
}, 'options objects merged correctly');
});
QUnit.test('should ignore non-objects', function(assert) {
const obj = { a: 1 };
assert.deepEqual(mergeOptions(obj, true), obj, 'ignored non-object input');
});

View File

@ -0,0 +1,16 @@
/* eslint-env qunit */
import * as Num from '../../../src/js/utils/num';
QUnit.module('utils/num', function() {
QUnit.module('clamp');
QUnit.test('keep a number between min/max values', function(assert) {
assert.expect(5);
assert.strictEqual(Num.clamp(5, 1, 10), 5);
assert.strictEqual(Num.clamp(5, 1, 5), 5);
assert.strictEqual(Num.clamp(5, 1, 2), 2);
assert.strictEqual(Num.clamp(-1, 1, 10), 1);
assert.strictEqual(Num.clamp(NaN, 1, 10), 1);
});
});

View File

@ -2,8 +2,6 @@
import sinon from 'sinon';
import * as Obj from '../../../src/js/utils/obj';
QUnit.module('utils/obj');
class Foo {
constructor() {}
toString() {
@ -21,201 +19,161 @@ const passFail = (assert, fn, descriptor, passes, failures) => {
});
};
QUnit.test('each', function(assert) {
const spy = sinon.spy();
QUnit.module('utils/obj', function() {
Obj.each({
a: 1,
b: 'foo',
c: null
}, spy);
QUnit.test('each', function(assert) {
const spy = sinon.spy();
assert.strictEqual(spy.callCount, 3);
assert.ok(spy.calledWith(1, 'a'));
assert.ok(spy.calledWith('foo', 'b'));
assert.ok(spy.calledWith(null, 'c'));
Obj.each({
a: 1,
b: 'foo',
c: null
}, spy);
Obj.each({}, spy);
assert.strictEqual(spy.callCount, 3, 'an empty object was not iterated over');
});
assert.strictEqual(spy.callCount, 3);
assert.ok(spy.calledWith(1, 'a'));
assert.ok(spy.calledWith('foo', 'b'));
assert.ok(spy.calledWith(null, 'c'));
QUnit.test('reduce', function(assert) {
const first = Obj.reduce({
a: 1,
b: 2,
c: 3,
d: 4
}, (accum, value) => accum + value);
assert.strictEqual(first, 10);
const second = Obj.reduce({
a: 1,
b: 2,
c: 3,
d: 4
}, (accum, value) => accum + value, 10);
assert.strictEqual(second, 20);
const third = Obj.reduce({
a: 1,
b: 2,
c: 3,
d: 4
}, (accum, value, key) => {
accum[key] = 0 - value;
return accum;
}, {});
assert.strictEqual(third.a, -1);
assert.strictEqual(third.b, -2);
assert.strictEqual(third.c, -3);
assert.strictEqual(third.d, -4);
});
QUnit.test('isObject', function(assert) {
passFail(assert, Obj.isObject, 'an object', {
'plain object': {},
'constructed object': new Foo(),
'array': [],
'regex': new RegExp('.'),
'date': new Date()
}, {
null: null,
function() {},
boolean: true,
number: 1,
string: 'xyz'
Obj.each({}, spy);
assert.strictEqual(spy.callCount, 3, 'an empty object was not iterated over');
});
});
QUnit.test('isPlain', function(assert) {
passFail(assert, Obj.isPlain, 'a plain object', {
'plain object': {}
}, {
'constructed object': new Foo(),
'null': null,
'array': [],
'function'() {},
'regex': new RegExp('.'),
'date': new Date(),
'boolean': true,
'number': 1,
'string': 'xyz'
QUnit.test('reduce', function(assert) {
const first = Obj.reduce({
a: 1,
b: 2,
c: 3,
d: 4
}, (accum, value) => accum + value);
assert.strictEqual(first, 10);
const second = Obj.reduce({
a: 1,
b: 2,
c: 3,
d: 4
}, (accum, value) => accum + value, 10);
assert.strictEqual(second, 20);
const third = Obj.reduce({
a: 1,
b: 2,
c: 3,
d: 4
}, (accum, value, key) => {
accum[key] = 0 - value;
return accum;
}, {});
assert.strictEqual(third.a, -1);
assert.strictEqual(third.b, -2);
assert.strictEqual(third.c, -3);
assert.strictEqual(third.d, -4);
});
});
QUnit.module('utils/obj.assign', function() {
const assignTests = ['mocked'];
// we only run "normal" tests where Object.assign is used when
// Object.assign is supported
if (Object.assign) {
assignTests.push('unmocked');
}
assignTests.forEach(function(k) {
QUnit.module(`with ${k} Object.assign`, {
before() {
if (k === 'mocked') {
this.oldObjectAssign = Object.assign;
Object.assign = null;
}
},
after() {
if (this.oldObjectAssign) {
Object.assign = this.oldObjectAssign;
}
this.oldObjectAssign = null;
}
});
QUnit.test('override object', function(assert) {
const foo = {foo: 'yellow'};
assert.deepEqual(Obj.assign(foo, {foo: 'blue'}), {foo: 'blue'}, 'Obj.assign should return overriden result');
assert.deepEqual(foo, {foo: 'blue'}, 'foo should be modified directly');
});
QUnit.test('new object', function(assert) {
const foo = {foo: 'yellow'};
assert.deepEqual(Obj.assign({}, foo, {foo: 'blue'}), {foo: 'blue'}, 'Obj.assign should return result');
assert.deepEqual(foo, {foo: 'yellow'}, 'foo should not be modified');
});
QUnit.test('empty override', function(assert) {
const foo = {foo: 'yellow'};
assert.deepEqual(Obj.assign(foo, {}), {foo: 'yellow'}, 'Obj.assign should return result');
assert.deepEqual(foo, {foo: 'yellow'}, 'foo should not be modified');
});
QUnit.test('multiple override object', function(assert) {
const foo = {foo: 'foo'};
const bar = {foo: 'bar'};
const baz = {foo: 'baz'};
assert.deepEqual(Obj.assign(foo, bar, baz), baz, 'Obj.assign should return result');
assert.deepEqual(foo, baz, 'foo should be overridden');
});
QUnit.test('additive properties', function(assert) {
const foo = {};
const expected = {one: 1, two: 2, three: 3};
assert.deepEqual(Obj.assign(foo, {one: 1}, {two: 2}, {three: 3}), expected, 'Obj.assign should return result');
assert.deepEqual(foo, expected, 'foo should be equal to result');
});
QUnit.test('deep override', function(assert) {
const foo = {
foo: {
bar: {
baz: 'buzz'
}
},
blue: [55, 56],
red: 'nope'
};
const baz = {
foo: {
bar: {
baz: 'red'
}
},
blue: [57]
};
const expected = {
foo: {
bar: {
baz: 'red'
}
},
blue: [57],
red: 'nope'
};
assert.deepEqual(Obj.assign(foo, baz), expected, 'Obj.assign should return result');
assert.deepEqual(foo, expected, 'foo is overridden');
});
QUnit.test('negative tests', function(assert) {
const expected = {foo: 11};
assert.deepEqual(Obj.assign({}, expected, undefined), expected, 'assign should undefined');
assert.deepEqual(Obj.assign({}, expected, null), expected, 'assign should ignore null');
assert.deepEqual(Obj.assign({}, expected, []), expected, 'assign should ignore Array');
assert.deepEqual(Obj.assign({}, expected, ''), expected, 'assign should ignore string');
assert.deepEqual(Obj.assign({}, expected, 11), expected, 'assign should ignore number');
assert.deepEqual(Obj.assign({}, expected, new RegExp()), expected, 'assign should ignore RegExp');
assert.deepEqual(Obj.assign({}, expected, new Date()), expected, 'assign should ignore Date');
assert.deepEqual(Obj.assign({}, expected, true), expected, 'assign should ignore boolean');
assert.deepEqual(Obj.assign({}, expected, () => {}), expected, 'assign should ignore function');
QUnit.test('isObject', function(assert) {
passFail(assert, Obj.isObject, 'an object', {
'plain object': {},
'constructed object': new Foo(),
'array': [],
'regex': new RegExp('.'),
'date': new Date()
}, {
null: null,
function() {},
boolean: true,
number: 1,
string: 'xyz'
});
});
});
QUnit.test('isPlain', function(assert) {
passFail(assert, Obj.isPlain, 'a plain object', {
'plain object': {}
}, {
'constructed object': new Foo(),
'null': null,
'array': [],
'function'() {},
'regex': new RegExp('.'),
'date': new Date(),
'boolean': true,
'number': 1,
'string': 'xyz'
});
});
QUnit.module('merge');
QUnit.test('should merge objects', function(assert) {
const ob1 = {
a: true,
b: { b1: true, b2: true, b3: true },
c: true
};
const ob2 = {
// override value
a: false,
// merge sub-option values
b: { b1: true, b2: false, b4: true },
// add new option
d: true
};
const ob3 = Obj.merge(ob1, ob2);
assert.deepEqual(ob3, {
a: false,
b: { b1: true, b2: false, b3: true, b4: true },
c: true,
d: true
}, 'options objects merged correctly');
});
QUnit.test('should ignore non-objects', function(assert) {
const obj = { a: 1 };
assert.deepEqual(Obj.merge(obj, true), obj, 'ignored non-object input');
});
QUnit.module('defineLazyProperty');
QUnit.test('should define a "lazy" property', function(assert) {
assert.expect(12);
const obj = {a: 1};
const getValue = sinon.spy(() => {
return 2;
});
Obj.defineLazyProperty(obj, 'b', getValue);
let descriptor = Object.getOwnPropertyDescriptor(obj, 'b');
assert.ok(getValue.notCalled, 'getValue function was not called');
assert.strictEqual(typeof descriptor.get, 'function', 'descriptor has a getter');
assert.strictEqual(typeof descriptor.set, 'function', 'descriptor has a setter');
assert.strictEqual(typeof descriptor.value, 'undefined', 'descriptor has no value');
let b = obj.b;
descriptor = Object.getOwnPropertyDescriptor(obj, 'b');
assert.ok(getValue.calledOnce, 'getValue function was not called');
assert.strictEqual(b, 2, 'the value was retrieved correctly');
assert.strictEqual(typeof descriptor.get, 'undefined', 'descriptor has no getter');
assert.strictEqual(typeof descriptor.set, 'undefined', 'descriptor has no setter');
assert.strictEqual(descriptor.value, 2, 'descriptor has a value');
b = obj.b;
descriptor = Object.getOwnPropertyDescriptor(obj, 'b');
assert.ok(getValue.calledOnce, 'getValue function was still only called once');
assert.strictEqual(b, 2, 'the value was retrieved correctly');
assert.strictEqual(descriptor.value, 2, 'descriptor has a value');
});
});

View File

@ -0,0 +1,28 @@
/* eslint-env qunit */
import * as Str from '../../../src/js/utils/str.js';
QUnit.module('utils/str');
QUnit.test('toTitleCase should make a string start with an uppercase letter', function(assert) {
const foo = Str.toTitleCase('bar');
assert.ok(foo === 'Bar');
});
QUnit.test('titleCaseEquals compares whether the TitleCase of two strings is equal', function(assert) {
assert.ok(Str.titleCaseEquals('foo', 'foo'), 'foo equals foo');
assert.ok(Str.titleCaseEquals('foo', 'Foo'), 'foo equals Foo');
assert.ok(Str.titleCaseEquals('Foo', 'foo'), 'Foo equals foo');
assert.ok(Str.titleCaseEquals('Foo', 'Foo'), 'Foo equals Foo');
assert.ok(Str.titleCaseEquals('fooBar', 'fooBar'), 'fooBar equals fooBar');
assert.notOk(Str.titleCaseEquals('fooBAR', 'fooBar'), 'fooBAR does not equal fooBar');
assert.notOk(Str.titleCaseEquals('foobar', 'fooBar'), 'foobar does not equal fooBar');
assert.notOk(Str.titleCaseEquals('fooBar', 'FOOBAR'), 'fooBar does not equal fooBAR');
});
QUnit.test('toLowerCase should make a string start with a lowercase letter', function(assert) {
const foo = Str.toLowerCase('BAR');
assert.ok(foo === 'bAR');
});

View File

@ -1,28 +0,0 @@
/* eslint-env qunit */
import {toLowerCase, toTitleCase, titleCaseEquals} from '../../../src/js/utils/string-cases.js';
QUnit.module('string-cases');
QUnit.test('toTitleCase should make a string start with an uppercase letter', function(assert) {
const foo = toTitleCase('bar');
assert.ok(foo === 'Bar');
});
QUnit.test('titleCaseEquals compares whether the TitleCase of two strings is equal', function(assert) {
assert.ok(titleCaseEquals('foo', 'foo'), 'foo equals foo');
assert.ok(titleCaseEquals('foo', 'Foo'), 'foo equals Foo');
assert.ok(titleCaseEquals('Foo', 'foo'), 'Foo equals foo');
assert.ok(titleCaseEquals('Foo', 'Foo'), 'Foo equals Foo');
assert.ok(titleCaseEquals('fooBar', 'fooBar'), 'fooBar equals fooBar');
assert.notOk(titleCaseEquals('fooBAR', 'fooBar'), 'fooBAR does not equal fooBar');
assert.notOk(titleCaseEquals('foobar', 'fooBar'), 'foobar does not equal fooBar');
assert.notOk(titleCaseEquals('fooBar', 'FOOBAR'), 'fooBar does not equal fooBAR');
});
QUnit.test('toLowerCase should make a string start with a lowercase letter', function(assert) {
const foo = toLowerCase('BAR');
assert.ok(foo === 'bAR');
});

View File

@ -1,97 +0,0 @@
/* eslint-env qunit */
import { createTimeRanges, createTimeRange } from '../../../src/js/utils/time-ranges.js';
import window from 'global/window';
QUnit.module('time-ranges');
QUnit.test('should export the deprecated createTimeRange function', function(assert) {
assert.equal(
createTimeRange,
createTimeRanges,
'createTimeRange is an alias to createTimeRanges'
);
});
QUnit.test('should create a fake single timerange', function(assert) {
const tr = createTimeRanges(0, 10);
assert.equal(tr.length, 1, 'length should be 1');
assert.equal(
tr.start(0),
0,
'works if start is called with valid index'
);
assert.equal(
tr.end(0),
10,
'works if end is called with with valid index'
);
assert.throws(
()=>tr.start(1),
/Failed to execute 'start'/,
'fails if start is called with an invalid index'
);
assert.throws(
()=>tr.end(1),
/Failed to execute 'end'/,
'fails if end is called with with an invalid index'
);
});
QUnit.test('should create a fake multiple timerange', function(assert) {
const tr = createTimeRanges([
[0, 10],
[11, 20]
]);
assert.equal(tr.length, 2, 'length should equal 2');
assert.equal(tr.start(1), 11, 'works if start is called with valid index');
assert.equal(tr.end(1), 20, 'works if end is called with with valid index');
assert.throws(
()=>tr.start(-1),
/Failed to execute 'start'/,
'fails if start is called with an invalid index'
);
assert.throws(
()=>tr.end(-1),
/Failed to execute 'end'/,
'fails if end is called with with an invalid index'
);
});
QUnit.test('should throw without being given an index', function(assert) {
const tr = createTimeRanges([
[0, 10],
[11, 20]
]);
assert.throws(
() => tr.start(),
/Failed to execute 'start'/,
'start throws if no index is given'
);
assert.throws(
() => tr.end(),
/Failed to execute 'end'/,
'end throws if no index is given'
);
});
let testOrSkip = 'skip';
if (window.Symbol && window.Symbol.iterator) {
testOrSkip = 'test';
}
QUnit[testOrSkip]('Array.from works on our time ranges object', function(assert) {
const trRepresentation = [
[0, 10],
[20, 30]
];
let tr = createTimeRanges(trRepresentation);
assert.deepEqual(Array.from(tr), trRepresentation, 'we got back what we put in');
tr = createTimeRanges(0, 10);
assert.deepEqual(Array.from(tr), [[0, 10]], 'we got back a ranges representation');
});

View File

@ -0,0 +1,148 @@
/* eslint-env qunit */
import { formatTime, setFormatTime, resetFormatTime, createTimeRanges, createTimeRange } from '../../../src/js/utils/time.js';
import window from 'global/window';
QUnit.module('utils/time', function() {
QUnit.module('TimeRanges');
QUnit.test('should export the deprecated createTimeRange function', function(assert) {
assert.equal(
createTimeRange,
createTimeRanges,
'createTimeRange is an alias to createTimeRanges'
);
});
QUnit.test('should create a fake single TimeRanges object', function(assert) {
const tr = createTimeRanges(0, 10);
assert.equal(tr.length, 1, 'length should be 1');
assert.equal(
tr.start(0),
0,
'works if start is called with valid index'
);
assert.equal(
tr.end(0),
10,
'works if end is called with with valid index'
);
assert.throws(
()=>tr.start(1),
/Failed to execute 'start'/,
'fails if start is called with an invalid index'
);
assert.throws(
()=>tr.end(1),
/Failed to execute 'end'/,
'fails if end is called with with an invalid index'
);
});
QUnit.test('should create a fake multiple TimeRanges object', function(assert) {
const tr = createTimeRanges([
[0, 10],
[11, 20]
]);
assert.equal(tr.length, 2, 'length should equal 2');
assert.equal(tr.start(1), 11, 'works if start is called with valid index');
assert.equal(tr.end(1), 20, 'works if end is called with with valid index');
assert.throws(
()=>tr.start(-1),
/Failed to execute 'start'/,
'fails if start is called with an invalid index'
);
assert.throws(
()=>tr.end(-1),
/Failed to execute 'end'/,
'fails if end is called with with an invalid index'
);
});
QUnit.test('should throw without being given an index', function(assert) {
const tr = createTimeRanges([
[0, 10],
[11, 20]
]);
assert.throws(
() => tr.start(),
/Failed to execute 'start'/,
'start throws if no index is given'
);
assert.throws(
() => tr.end(),
/Failed to execute 'end'/,
'end throws if no index is given'
);
});
let testOrSkip = 'skip';
if (window.Symbol && window.Symbol.iterator) {
testOrSkip = 'test';
}
QUnit[testOrSkip]('Array.from works on our TimeRanges object', function(assert) {
const trRepresentation = [
[0, 10],
[20, 30]
];
let tr = createTimeRanges(trRepresentation);
assert.deepEqual(Array.from(tr), trRepresentation, 'we got back what we put in');
tr = createTimeRanges(0, 10);
assert.deepEqual(Array.from(tr), [[0, 10]], 'we got back a ranges representation');
});
QUnit.module('formatTime', {
afterEach: resetFormatTime()
});
QUnit.test('should format time as a string', function(assert) {
assert.ok(formatTime(1) === '0:01');
assert.ok(formatTime(10) === '0:10');
assert.ok(formatTime(60) === '1:00');
assert.ok(formatTime(600) === '10:00');
assert.ok(formatTime(3600) === '1:00:00');
assert.ok(formatTime(36000) === '10:00:00');
assert.ok(formatTime(360000) === '100:00:00');
// Using guide should provide extra leading zeros
assert.ok(formatTime(1, 1) === '0:01');
assert.ok(formatTime(1, 10) === '0:01');
assert.ok(formatTime(1, 60) === '0:01');
assert.ok(formatTime(1, 600) === '00:01');
assert.ok(formatTime(1, 3600) === '0:00:01');
// Don't do extra leading zeros for hours
assert.ok(formatTime(1, 36000) === '0:00:01');
assert.ok(formatTime(1, 360000) === '0:00:01');
// Do not display negative time
assert.ok(formatTime(-1) === '0:00');
assert.ok(formatTime(-1, 3600) === '0:00:00');
});
QUnit.test('should format invalid times as dashes', function(assert) {
assert.equal(formatTime(Infinity, 90), '-:-');
assert.equal(formatTime(NaN), '-:-');
assert.equal(formatTime(10, Infinity), '0:00:10');
assert.equal(formatTime(90, NaN), '1:30');
});
QUnit.test('setFormatTime', function(assert) {
setFormatTime((seconds, guide) => `custom:${seconds}:${guide}`);
assert.equal(formatTime(1, 2), 'custom:1:2', 'it should replace the default formatTime implementation');
});
QUnit.test('resetFormatTime', function(assert) {
setFormatTime((seconds, guide) => `custom:${seconds}:${guide}`);
assert.equal(formatTime(1, 2), 'custom:1:2');
resetFormatTime();
assert.equal(formatTime(1), '0:01', 'it should reset formatTime to the default implementation');
});
});

View File

@ -3,7 +3,8 @@ import document from 'global/document';
import window from 'global/window';
import * as Url from '../../../src/js/utils/url.js';
QUnit.module('url');
QUnit.module('utils/url');
QUnit.test('should parse the details of a url correctly', function(assert) {
assert.equal(Url.parseUrl('#').protocol, window.location.protocol, 'parsed relative url protocol');
assert.equal(Url.parseUrl('#').host, window.location.host, 'parsed relative url host');