diff --git a/public/s/font-awesome-4.7.0/css/font-awesome.css b/public/s/font-awesome-4.7.0/css/font-awesome.css deleted file mode 100644 index ee906a8..0000000 --- a/public/s/font-awesome-4.7.0/css/font-awesome.css +++ /dev/null @@ -1,2337 +0,0 @@ -/*! - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */ -/* FONT PATH - * -------------------------- */ -@font-face { - font-family: 'FontAwesome'; - src: url('../fonts/fontawesome-webfont.eot?v=4.7.0'); - src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg'); - font-weight: normal; - font-style: normal; -} -.fa { - display: inline-block; - font: normal normal normal 14px/1 FontAwesome; - font-size: inherit; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -/* makes the font 33% larger relative to the icon container */ -.fa-lg { - font-size: 1.33333333em; - line-height: 0.75em; - vertical-align: -15%; -} -.fa-2x { - font-size: 2em; -} -.fa-3x { - font-size: 3em; -} -.fa-4x { - font-size: 4em; -} -.fa-5x { - font-size: 5em; -} -.fa-fw { - width: 1.28571429em; - text-align: center; -} -.fa-ul { - padding-left: 0; - margin-left: 2.14285714em; - list-style-type: none; -} -.fa-ul > li { - position: relative; -} -.fa-li { - position: absolute; - left: -2.14285714em; - width: 2.14285714em; - top: 0.14285714em; - text-align: center; -} -.fa-li.fa-lg { - left: -1.85714286em; -} -.fa-border { - padding: .2em .25em .15em; - border: solid 0.08em #eeeeee; - border-radius: .1em; -} -.fa-pull-left { - float: left; -} -.fa-pull-right { - float: right; -} -.fa.fa-pull-left { - margin-right: .3em; -} -.fa.fa-pull-right { - margin-left: .3em; -} -/* Deprecated as of 4.4.0 */ -.pull-right { - float: right; -} -.pull-left { - float: left; -} -.fa.pull-left { - margin-right: .3em; -} -.fa.pull-right { - margin-left: .3em; -} -.fa-spin { - -webkit-animation: fa-spin 2s infinite linear; - animation: fa-spin 2s infinite linear; -} -.fa-pulse { - -webkit-animation: fa-spin 1s infinite steps(8); - animation: fa-spin 1s infinite steps(8); -} -@-webkit-keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -@keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -.fa-rotate-90 { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; - -webkit-transform: rotate(90deg); - -ms-transform: rotate(90deg); - transform: rotate(90deg); -} -.fa-rotate-180 { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; - -webkit-transform: rotate(180deg); - -ms-transform: rotate(180deg); - transform: rotate(180deg); -} -.fa-rotate-270 { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; - -webkit-transform: rotate(270deg); - -ms-transform: rotate(270deg); - transform: rotate(270deg); -} -.fa-flip-horizontal { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; - -webkit-transform: scale(-1, 1); - -ms-transform: scale(-1, 1); - transform: scale(-1, 1); -} -.fa-flip-vertical { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; - -webkit-transform: scale(1, -1); - -ms-transform: scale(1, -1); - transform: scale(1, -1); -} -:root .fa-rotate-90, -:root .fa-rotate-180, -:root .fa-rotate-270, -:root .fa-flip-horizontal, -:root .fa-flip-vertical { - filter: none; -} -.fa-stack { - position: relative; - display: inline-block; - width: 2em; - height: 2em; - line-height: 2em; - vertical-align: middle; -} -.fa-stack-1x, -.fa-stack-2x { - position: absolute; - left: 0; - width: 100%; - text-align: center; -} -.fa-stack-1x { - line-height: inherit; -} -.fa-stack-2x { - font-size: 2em; -} -.fa-inverse { - color: #ffffff; -} -/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen - readers do not read off random characters that represent icons */ -.fa-glass:before { - content: "\f000"; -} -.fa-music:before { - content: "\f001"; -} -.fa-search:before { - content: "\f002"; -} -.fa-envelope-o:before { - content: "\f003"; -} -.fa-heart:before { - content: "\f004"; -} -.fa-star:before { - content: "\f005"; -} -.fa-star-o:before { - content: "\f006"; -} -.fa-user:before { - content: "\f007"; -} -.fa-film:before { - content: "\f008"; -} -.fa-th-large:before { - content: "\f009"; -} -.fa-th:before { - content: "\f00a"; -} -.fa-th-list:before { - content: "\f00b"; -} -.fa-check:before { - content: "\f00c"; -} -.fa-remove:before, -.fa-close:before, -.fa-times:before { - content: "\f00d"; -} -.fa-search-plus:before { - content: "\f00e"; -} -.fa-search-minus:before { - content: "\f010"; -} -.fa-power-off:before { - content: "\f011"; -} -.fa-signal:before { - content: "\f012"; -} -.fa-gear:before, -.fa-cog:before { - content: "\f013"; -} -.fa-trash-o:before { - content: "\f014"; -} -.fa-home:before { - content: "\f015"; -} -.fa-file-o:before { - content: "\f016"; -} -.fa-clock-o:before { - content: "\f017"; -} -.fa-road:before { - content: "\f018"; -} -.fa-download:before { - content: "\f019"; -} -.fa-arrow-circle-o-down:before { - content: "\f01a"; -} -.fa-arrow-circle-o-up:before { - content: "\f01b"; -} -.fa-inbox:before { - content: "\f01c"; -} -.fa-play-circle-o:before { - content: "\f01d"; -} -.fa-rotate-right:before, -.fa-repeat:before { - content: "\f01e"; -} -.fa-refresh:before { - content: "\f021"; -} -.fa-list-alt:before { - content: "\f022"; -} -.fa-lock:before { - content: "\f023"; -} -.fa-flag:before { - content: "\f024"; -} -.fa-headphones:before { - content: "\f025"; -} -.fa-volume-off:before { - content: "\f026"; -} -.fa-volume-down:before { - content: "\f027"; -} -.fa-volume-up:before { - content: "\f028"; -} -.fa-qrcode:before { - content: "\f029"; -} -.fa-barcode:before { - content: "\f02a"; -} -.fa-tag:before { - content: "\f02b"; -} -.fa-tags:before { - content: "\f02c"; -} -.fa-book:before { - content: "\f02d"; -} -.fa-bookmark:before { - content: "\f02e"; -} -.fa-print:before { - content: "\f02f"; -} -.fa-camera:before { - content: "\f030"; -} -.fa-font:before { - content: "\f031"; -} -.fa-bold:before { - content: "\f032"; -} -.fa-italic:before { - content: "\f033"; -} -.fa-text-height:before { - content: "\f034"; -} -.fa-text-width:before { - content: "\f035"; -} -.fa-align-left:before { - content: "\f036"; -} -.fa-align-center:before { - content: "\f037"; -} -.fa-align-right:before { - content: "\f038"; -} -.fa-align-justify:before { - content: "\f039"; -} -.fa-list:before { - content: "\f03a"; -} -.fa-dedent:before, -.fa-outdent:before { - content: "\f03b"; -} -.fa-indent:before { - content: "\f03c"; -} -.fa-video-camera:before { - content: "\f03d"; -} -.fa-photo:before, -.fa-image:before, -.fa-picture-o:before { - content: "\f03e"; -} -.fa-pencil:before { - content: "\f040"; -} -.fa-map-marker:before { - content: "\f041"; -} -.fa-adjust:before { - content: "\f042"; -} -.fa-tint:before { - content: "\f043"; -} -.fa-edit:before, -.fa-pencil-square-o:before { - content: "\f044"; -} -.fa-share-square-o:before { - content: "\f045"; -} -.fa-check-square-o:before { - content: "\f046"; -} -.fa-arrows:before { - content: "\f047"; -} -.fa-step-backward:before { - content: "\f048"; -} -.fa-fast-backward:before { - content: "\f049"; -} -.fa-backward:before { - content: "\f04a"; -} -.fa-play:before { - content: "\f04b"; -} -.fa-pause:before { - content: "\f04c"; -} -.fa-stop:before { - content: "\f04d"; -} -.fa-forward:before { - content: "\f04e"; -} -.fa-fast-forward:before { - content: "\f050"; -} -.fa-step-forward:before { - content: "\f051"; -} -.fa-eject:before { - content: "\f052"; -} -.fa-chevron-left:before { - content: "\f053"; -} -.fa-chevron-right:before { - content: "\f054"; -} -.fa-plus-circle:before { - content: "\f055"; -} -.fa-minus-circle:before { - content: "\f056"; -} -.fa-times-circle:before { - content: "\f057"; -} -.fa-check-circle:before { - content: "\f058"; -} -.fa-question-circle:before { - content: "\f059"; -} -.fa-info-circle:before { - content: "\f05a"; -} -.fa-crosshairs:before { - content: "\f05b"; -} -.fa-times-circle-o:before { - content: "\f05c"; -} -.fa-check-circle-o:before { - content: "\f05d"; -} -.fa-ban:before { - content: "\f05e"; -} -.fa-arrow-left:before { - content: "\f060"; -} -.fa-arrow-right:before { - content: "\f061"; -} -.fa-arrow-up:before { - content: "\f062"; -} -.fa-arrow-down:before { - content: "\f063"; -} -.fa-mail-forward:before, -.fa-share:before { - content: "\f064"; -} -.fa-expand:before { - content: "\f065"; -} -.fa-compress:before { - content: "\f066"; -} -.fa-plus:before { - content: "\f067"; -} -.fa-minus:before { - content: "\f068"; -} -.fa-asterisk:before { - content: "\f069"; -} -.fa-exclamation-circle:before { - content: "\f06a"; -} -.fa-gift:before { - content: "\f06b"; -} -.fa-leaf:before { - content: "\f06c"; -} -.fa-fire:before { - content: "\f06d"; -} -.fa-eye:before { - content: "\f06e"; -} -.fa-eye-slash:before { - content: "\f070"; -} -.fa-warning:before, -.fa-exclamation-triangle:before { - content: "\f071"; -} -.fa-plane:before { - content: "\f072"; -} -.fa-calendar:before { - content: "\f073"; -} -.fa-random:before { - content: "\f074"; -} -.fa-comment:before { - content: "\f075"; -} -.fa-magnet:before { - content: "\f076"; -} -.fa-chevron-up:before { - content: "\f077"; -} -.fa-chevron-down:before { - content: "\f078"; -} -.fa-retweet:before { - content: "\f079"; -} -.fa-shopping-cart:before { - content: "\f07a"; -} -.fa-folder:before { - content: "\f07b"; -} -.fa-folder-open:before { - content: "\f07c"; -} -.fa-arrows-v:before { - content: "\f07d"; -} -.fa-arrows-h:before { - content: "\f07e"; -} -.fa-bar-chart-o:before, -.fa-bar-chart:before { - content: "\f080"; -} -.fa-twitter-square:before { - content: "\f081"; -} -.fa-facebook-square:before { - content: "\f082"; -} -.fa-camera-retro:before { - content: "\f083"; -} -.fa-key:before { - content: "\f084"; -} -.fa-gears:before, -.fa-cogs:before { - content: "\f085"; -} -.fa-comments:before { - content: "\f086"; -} -.fa-thumbs-o-up:before { - content: "\f087"; -} -.fa-thumbs-o-down:before { - content: "\f088"; -} -.fa-star-half:before { - content: "\f089"; -} -.fa-heart-o:before { - content: "\f08a"; -} -.fa-sign-out:before { - content: "\f08b"; -} -.fa-linkedin-square:before { - content: "\f08c"; -} -.fa-thumb-tack:before { - content: "\f08d"; -} -.fa-external-link:before { - content: "\f08e"; -} -.fa-sign-in:before { - content: "\f090"; -} -.fa-trophy:before { - content: "\f091"; -} -.fa-github-square:before { - content: "\f092"; -} -.fa-upload:before { - content: "\f093"; -} -.fa-lemon-o:before { - content: "\f094"; -} -.fa-phone:before { - content: "\f095"; -} -.fa-square-o:before { - content: "\f096"; -} -.fa-bookmark-o:before { - content: "\f097"; -} -.fa-phone-square:before { - content: "\f098"; -} -.fa-twitter:before { - content: "\f099"; -} -.fa-facebook-f:before, -.fa-facebook:before { - content: "\f09a"; -} -.fa-github:before { - content: "\f09b"; -} -.fa-unlock:before { - content: "\f09c"; -} -.fa-credit-card:before { - content: "\f09d"; -} -.fa-feed:before, -.fa-rss:before { - content: "\f09e"; -} -.fa-hdd-o:before { - content: "\f0a0"; -} -.fa-bullhorn:before { - content: "\f0a1"; -} -.fa-bell:before { - content: "\f0f3"; -} -.fa-certificate:before { - content: "\f0a3"; -} -.fa-hand-o-right:before { - content: "\f0a4"; -} -.fa-hand-o-left:before { - content: "\f0a5"; -} -.fa-hand-o-up:before { - content: "\f0a6"; -} -.fa-hand-o-down:before { - content: "\f0a7"; -} -.fa-arrow-circle-left:before { - content: "\f0a8"; -} -.fa-arrow-circle-right:before { - content: "\f0a9"; -} -.fa-arrow-circle-up:before { - content: "\f0aa"; -} -.fa-arrow-circle-down:before { - content: "\f0ab"; -} -.fa-globe:before { - content: "\f0ac"; -} -.fa-wrench:before { - content: "\f0ad"; -} -.fa-tasks:before { - content: "\f0ae"; -} -.fa-filter:before { - content: "\f0b0"; -} -.fa-briefcase:before { - content: "\f0b1"; -} -.fa-arrows-alt:before { - content: "\f0b2"; -} -.fa-group:before, -.fa-users:before { - content: "\f0c0"; -} -.fa-chain:before, -.fa-link:before { - content: "\f0c1"; -} -.fa-cloud:before { - content: "\f0c2"; -} -.fa-flask:before { - content: "\f0c3"; -} -.fa-cut:before, -.fa-scissors:before { - content: "\f0c4"; -} -.fa-copy:before, -.fa-files-o:before { - content: "\f0c5"; -} -.fa-paperclip:before { - content: "\f0c6"; -} -.fa-save:before, -.fa-floppy-o:before { - content: "\f0c7"; -} -.fa-square:before { - content: "\f0c8"; -} -.fa-navicon:before, -.fa-reorder:before, -.fa-bars:before { - content: "\f0c9"; -} -.fa-list-ul:before { - content: "\f0ca"; -} -.fa-list-ol:before { - content: "\f0cb"; -} -.fa-strikethrough:before { - content: "\f0cc"; -} -.fa-underline:before { - content: "\f0cd"; -} -.fa-table:before { - content: "\f0ce"; -} -.fa-magic:before { - content: "\f0d0"; -} -.fa-truck:before { - content: "\f0d1"; -} -.fa-pinterest:before { - content: "\f0d2"; -} -.fa-pinterest-square:before { - content: "\f0d3"; -} -.fa-google-plus-square:before { - content: "\f0d4"; -} -.fa-google-plus:before { - content: "\f0d5"; -} -.fa-money:before { - content: "\f0d6"; -} -.fa-caret-down:before { - content: "\f0d7"; -} -.fa-caret-up:before { - content: "\f0d8"; -} -.fa-caret-left:before { - content: "\f0d9"; -} -.fa-caret-right:before { - content: "\f0da"; -} -.fa-columns:before { - content: "\f0db"; -} -.fa-unsorted:before, -.fa-sort:before { - content: "\f0dc"; -} -.fa-sort-down:before, -.fa-sort-desc:before { - content: "\f0dd"; -} -.fa-sort-up:before, -.fa-sort-asc:before { - content: "\f0de"; -} -.fa-envelope:before { - content: "\f0e0"; -} -.fa-linkedin:before { - content: "\f0e1"; -} -.fa-rotate-left:before, -.fa-undo:before { - content: "\f0e2"; -} -.fa-legal:before, -.fa-gavel:before { - content: "\f0e3"; -} -.fa-dashboard:before, -.fa-tachometer:before { - content: "\f0e4"; -} -.fa-comment-o:before { - content: "\f0e5"; -} -.fa-comments-o:before { - content: "\f0e6"; -} -.fa-flash:before, -.fa-bolt:before { - content: "\f0e7"; -} -.fa-sitemap:before { - content: "\f0e8"; -} -.fa-umbrella:before { - content: "\f0e9"; -} -.fa-paste:before, -.fa-clipboard:before { - content: "\f0ea"; -} -.fa-lightbulb-o:before { - content: "\f0eb"; -} -.fa-exchange:before { - content: "\f0ec"; -} -.fa-cloud-download:before { - content: "\f0ed"; -} -.fa-cloud-upload:before { - content: "\f0ee"; -} -.fa-user-md:before { - content: "\f0f0"; -} -.fa-stethoscope:before { - content: "\f0f1"; -} -.fa-suitcase:before { - content: "\f0f2"; -} -.fa-bell-o:before { - content: "\f0a2"; -} -.fa-coffee:before { - content: "\f0f4"; -} -.fa-cutlery:before { - content: "\f0f5"; -} -.fa-file-text-o:before { - content: "\f0f6"; -} -.fa-building-o:before { - content: "\f0f7"; -} -.fa-hospital-o:before { - content: "\f0f8"; -} -.fa-ambulance:before { - content: "\f0f9"; -} -.fa-medkit:before { - content: "\f0fa"; -} -.fa-fighter-jet:before { - content: "\f0fb"; -} -.fa-beer:before { - content: "\f0fc"; -} -.fa-h-square:before { - content: "\f0fd"; -} -.fa-plus-square:before { - content: "\f0fe"; -} -.fa-angle-double-left:before { - content: "\f100"; -} -.fa-angle-double-right:before { - content: "\f101"; -} -.fa-angle-double-up:before { - content: "\f102"; -} -.fa-angle-double-down:before { - content: "\f103"; -} -.fa-angle-left:before { - content: "\f104"; -} -.fa-angle-right:before { - content: "\f105"; -} -.fa-angle-up:before { - content: "\f106"; -} -.fa-angle-down:before { - content: "\f107"; -} -.fa-desktop:before { - content: "\f108"; -} -.fa-laptop:before { - content: "\f109"; -} -.fa-tablet:before { - content: "\f10a"; -} -.fa-mobile-phone:before, -.fa-mobile:before { - content: "\f10b"; -} -.fa-circle-o:before { - content: "\f10c"; -} -.fa-quote-left:before { - content: "\f10d"; -} -.fa-quote-right:before { - content: "\f10e"; -} -.fa-spinner:before { - content: "\f110"; -} -.fa-circle:before { - content: "\f111"; -} -.fa-mail-reply:before, -.fa-reply:before { - content: "\f112"; -} -.fa-github-alt:before { - content: "\f113"; -} -.fa-folder-o:before { - content: "\f114"; -} -.fa-folder-open-o:before { - content: "\f115"; -} -.fa-smile-o:before { - content: "\f118"; -} -.fa-frown-o:before { - content: "\f119"; -} -.fa-meh-o:before { - content: "\f11a"; -} -.fa-gamepad:before { - content: "\f11b"; -} -.fa-keyboard-o:before { - content: "\f11c"; -} -.fa-flag-o:before { - content: "\f11d"; -} -.fa-flag-checkered:before { - content: "\f11e"; -} -.fa-terminal:before { - content: "\f120"; -} -.fa-code:before { - content: "\f121"; -} -.fa-mail-reply-all:before, -.fa-reply-all:before { - content: "\f122"; -} -.fa-star-half-empty:before, -.fa-star-half-full:before, -.fa-star-half-o:before { - content: "\f123"; -} -.fa-location-arrow:before { - content: "\f124"; -} -.fa-crop:before { - content: "\f125"; -} -.fa-code-fork:before { - content: "\f126"; -} -.fa-unlink:before, -.fa-chain-broken:before { - content: "\f127"; -} -.fa-question:before { - content: "\f128"; -} -.fa-info:before { - content: "\f129"; -} -.fa-exclamation:before { - content: "\f12a"; -} -.fa-superscript:before { - content: "\f12b"; -} -.fa-subscript:before { - content: "\f12c"; -} -.fa-eraser:before { - content: "\f12d"; -} -.fa-puzzle-piece:before { - content: "\f12e"; -} -.fa-microphone:before { - content: "\f130"; -} -.fa-microphone-slash:before { - content: "\f131"; -} -.fa-shield:before { - content: "\f132"; -} -.fa-calendar-o:before { - content: "\f133"; -} -.fa-fire-extinguisher:before { - content: "\f134"; -} -.fa-rocket:before { - content: "\f135"; -} -.fa-maxcdn:before { - content: "\f136"; -} -.fa-chevron-circle-left:before { - content: "\f137"; -} -.fa-chevron-circle-right:before { - content: "\f138"; -} -.fa-chevron-circle-up:before { - content: "\f139"; -} -.fa-chevron-circle-down:before { - content: "\f13a"; -} -.fa-html5:before { - content: "\f13b"; -} -.fa-css3:before { - content: "\f13c"; -} -.fa-anchor:before { - content: "\f13d"; -} -.fa-unlock-alt:before { - content: "\f13e"; -} -.fa-bullseye:before { - content: "\f140"; -} -.fa-ellipsis-h:before { - content: "\f141"; -} -.fa-ellipsis-v:before { - content: "\f142"; -} -.fa-rss-square:before { - content: "\f143"; -} -.fa-play-circle:before { - content: "\f144"; -} -.fa-ticket:before { - content: "\f145"; -} -.fa-minus-square:before { - content: "\f146"; -} -.fa-minus-square-o:before { - content: "\f147"; -} -.fa-level-up:before { - content: "\f148"; -} -.fa-level-down:before { - content: "\f149"; -} -.fa-check-square:before { - content: "\f14a"; -} -.fa-pencil-square:before { - content: "\f14b"; -} -.fa-external-link-square:before { - content: "\f14c"; -} -.fa-share-square:before { - content: "\f14d"; -} -.fa-compass:before { - content: "\f14e"; -} -.fa-toggle-down:before, -.fa-caret-square-o-down:before { - content: "\f150"; -} -.fa-toggle-up:before, -.fa-caret-square-o-up:before { - content: "\f151"; -} -.fa-toggle-right:before, -.fa-caret-square-o-right:before { - content: "\f152"; -} -.fa-euro:before, -.fa-eur:before { - content: "\f153"; -} -.fa-gbp:before { - content: "\f154"; -} -.fa-dollar:before, -.fa-usd:before { - content: "\f155"; -} -.fa-rupee:before, -.fa-inr:before { - content: "\f156"; -} -.fa-cny:before, -.fa-rmb:before, -.fa-yen:before, -.fa-jpy:before { - content: "\f157"; -} -.fa-ruble:before, -.fa-rouble:before, -.fa-rub:before { - content: "\f158"; -} -.fa-won:before, -.fa-krw:before { - content: "\f159"; -} -.fa-bitcoin:before, -.fa-btc:before { - content: "\f15a"; -} -.fa-file:before { - content: "\f15b"; -} -.fa-file-text:before { - content: "\f15c"; -} -.fa-sort-alpha-asc:before { - content: "\f15d"; -} -.fa-sort-alpha-desc:before { - content: "\f15e"; -} -.fa-sort-amount-asc:before { - content: "\f160"; -} -.fa-sort-amount-desc:before { - content: "\f161"; -} -.fa-sort-numeric-asc:before { - content: "\f162"; -} -.fa-sort-numeric-desc:before { - content: "\f163"; -} -.fa-thumbs-up:before { - content: "\f164"; -} -.fa-thumbs-down:before { - content: "\f165"; -} -.fa-youtube-square:before { - content: "\f166"; -} -.fa-youtube:before { - content: "\f167"; -} -.fa-xing:before { - content: "\f168"; -} -.fa-xing-square:before { - content: "\f169"; -} -.fa-youtube-play:before { - content: "\f16a"; -} -.fa-dropbox:before { - content: "\f16b"; -} -.fa-stack-overflow:before { - content: "\f16c"; -} -.fa-instagram:before { - content: "\f16d"; -} -.fa-flickr:before { - content: "\f16e"; -} -.fa-adn:before { - content: "\f170"; -} -.fa-bitbucket:before { - content: "\f171"; -} -.fa-bitbucket-square:before { - content: "\f172"; -} -.fa-tumblr:before { - content: "\f173"; -} -.fa-tumblr-square:before { - content: "\f174"; -} -.fa-long-arrow-down:before { - content: "\f175"; -} -.fa-long-arrow-up:before { - content: "\f176"; -} -.fa-long-arrow-left:before { - content: "\f177"; -} -.fa-long-arrow-right:before { - content: "\f178"; -} -.fa-apple:before { - content: "\f179"; -} -.fa-windows:before { - content: "\f17a"; -} -.fa-android:before { - content: "\f17b"; -} -.fa-linux:before { - content: "\f17c"; -} -.fa-dribbble:before { - content: "\f17d"; -} -.fa-skype:before { - content: "\f17e"; -} -.fa-foursquare:before { - content: "\f180"; -} -.fa-trello:before { - content: "\f181"; -} -.fa-female:before { - content: "\f182"; -} -.fa-male:before { - content: "\f183"; -} -.fa-gittip:before, -.fa-gratipay:before { - content: "\f184"; -} -.fa-sun-o:before { - content: "\f185"; -} -.fa-moon-o:before { - content: "\f186"; -} -.fa-archive:before { - content: "\f187"; -} -.fa-bug:before { - content: "\f188"; -} -.fa-vk:before { - content: "\f189"; -} -.fa-weibo:before { - content: "\f18a"; -} -.fa-renren:before { - content: "\f18b"; -} -.fa-pagelines:before { - content: "\f18c"; -} -.fa-stack-exchange:before { - content: "\f18d"; -} -.fa-arrow-circle-o-right:before { - content: "\f18e"; -} -.fa-arrow-circle-o-left:before { - content: "\f190"; -} -.fa-toggle-left:before, -.fa-caret-square-o-left:before { - content: "\f191"; -} -.fa-dot-circle-o:before { - content: "\f192"; -} -.fa-wheelchair:before { - content: "\f193"; -} -.fa-vimeo-square:before { - content: "\f194"; -} -.fa-turkish-lira:before, -.fa-try:before { - content: "\f195"; -} -.fa-plus-square-o:before { - content: "\f196"; -} -.fa-space-shuttle:before { - content: "\f197"; -} -.fa-slack:before { - content: "\f198"; -} -.fa-envelope-square:before { - content: "\f199"; -} -.fa-wordpress:before { - content: "\f19a"; -} -.fa-openid:before { - content: "\f19b"; -} -.fa-institution:before, -.fa-bank:before, -.fa-university:before { - content: "\f19c"; -} -.fa-mortar-board:before, -.fa-graduation-cap:before { - content: "\f19d"; -} -.fa-yahoo:before { - content: "\f19e"; -} -.fa-google:before { - content: "\f1a0"; -} -.fa-reddit:before { - content: "\f1a1"; -} -.fa-reddit-square:before { - content: "\f1a2"; -} -.fa-stumbleupon-circle:before { - content: "\f1a3"; -} -.fa-stumbleupon:before { - content: "\f1a4"; -} -.fa-delicious:before { - content: "\f1a5"; -} -.fa-digg:before { - content: "\f1a6"; -} -.fa-pied-piper-pp:before { - content: "\f1a7"; -} -.fa-pied-piper-alt:before { - content: "\f1a8"; -} -.fa-drupal:before { - content: "\f1a9"; -} -.fa-joomla:before { - content: "\f1aa"; -} -.fa-language:before { - content: "\f1ab"; -} -.fa-fax:before { - content: "\f1ac"; -} -.fa-building:before { - content: "\f1ad"; -} -.fa-child:before { - content: "\f1ae"; -} -.fa-paw:before { - content: "\f1b0"; -} -.fa-spoon:before { - content: "\f1b1"; -} -.fa-cube:before { - content: "\f1b2"; -} -.fa-cubes:before { - content: "\f1b3"; -} -.fa-behance:before { - content: "\f1b4"; -} -.fa-behance-square:before { - content: "\f1b5"; -} -.fa-steam:before { - content: "\f1b6"; -} -.fa-steam-square:before { - content: "\f1b7"; -} -.fa-recycle:before { - content: "\f1b8"; -} -.fa-automobile:before, -.fa-car:before { - content: "\f1b9"; -} -.fa-cab:before, -.fa-taxi:before { - content: "\f1ba"; -} -.fa-tree:before { - content: "\f1bb"; -} -.fa-spotify:before { - content: "\f1bc"; -} -.fa-deviantart:before { - content: "\f1bd"; -} -.fa-soundcloud:before { - content: "\f1be"; -} -.fa-database:before { - content: "\f1c0"; -} -.fa-file-pdf-o:before { - content: "\f1c1"; -} -.fa-file-word-o:before { - content: "\f1c2"; -} -.fa-file-excel-o:before { - content: "\f1c3"; -} -.fa-file-powerpoint-o:before { - content: "\f1c4"; -} -.fa-file-photo-o:before, -.fa-file-picture-o:before, -.fa-file-image-o:before { - content: "\f1c5"; -} -.fa-file-zip-o:before, -.fa-file-archive-o:before { - content: "\f1c6"; -} -.fa-file-sound-o:before, -.fa-file-audio-o:before { - content: "\f1c7"; -} -.fa-file-movie-o:before, -.fa-file-video-o:before { - content: "\f1c8"; -} -.fa-file-code-o:before { - content: "\f1c9"; -} -.fa-vine:before { - content: "\f1ca"; -} -.fa-codepen:before { - content: "\f1cb"; -} -.fa-jsfiddle:before { - content: "\f1cc"; -} -.fa-life-bouy:before, -.fa-life-buoy:before, -.fa-life-saver:before, -.fa-support:before, -.fa-life-ring:before { - content: "\f1cd"; -} -.fa-circle-o-notch:before { - content: "\f1ce"; -} -.fa-ra:before, -.fa-resistance:before, -.fa-rebel:before { - content: "\f1d0"; -} -.fa-ge:before, -.fa-empire:before { - content: "\f1d1"; -} -.fa-git-square:before { - content: "\f1d2"; -} -.fa-git:before { - content: "\f1d3"; -} -.fa-y-combinator-square:before, -.fa-yc-square:before, -.fa-hacker-news:before { - content: "\f1d4"; -} -.fa-tencent-weibo:before { - content: "\f1d5"; -} -.fa-qq:before { - content: "\f1d6"; -} -.fa-wechat:before, -.fa-weixin:before { - content: "\f1d7"; -} -.fa-send:before, -.fa-paper-plane:before { - content: "\f1d8"; -} -.fa-send-o:before, -.fa-paper-plane-o:before { - content: "\f1d9"; -} -.fa-history:before { - content: "\f1da"; -} -.fa-circle-thin:before { - content: "\f1db"; -} -.fa-header:before { - content: "\f1dc"; -} -.fa-paragraph:before { - content: "\f1dd"; -} -.fa-sliders:before { - content: "\f1de"; -} -.fa-share-alt:before { - content: "\f1e0"; -} -.fa-share-alt-square:before { - content: "\f1e1"; -} -.fa-bomb:before { - content: "\f1e2"; -} -.fa-soccer-ball-o:before, -.fa-futbol-o:before { - content: "\f1e3"; -} -.fa-tty:before { - content: "\f1e4"; -} -.fa-binoculars:before { - content: "\f1e5"; -} -.fa-plug:before { - content: "\f1e6"; -} -.fa-slideshare:before { - content: "\f1e7"; -} -.fa-twitch:before { - content: "\f1e8"; -} -.fa-yelp:before { - content: "\f1e9"; -} -.fa-newspaper-o:before { - content: "\f1ea"; -} -.fa-wifi:before { - content: "\f1eb"; -} -.fa-calculator:before { - content: "\f1ec"; -} -.fa-paypal:before { - content: "\f1ed"; -} -.fa-google-wallet:before { - content: "\f1ee"; -} -.fa-cc-visa:before { - content: "\f1f0"; -} -.fa-cc-mastercard:before { - content: "\f1f1"; -} -.fa-cc-discover:before { - content: "\f1f2"; -} -.fa-cc-amex:before { - content: "\f1f3"; -} -.fa-cc-paypal:before { - content: "\f1f4"; -} -.fa-cc-stripe:before { - content: "\f1f5"; -} -.fa-bell-slash:before { - content: "\f1f6"; -} -.fa-bell-slash-o:before { - content: "\f1f7"; -} -.fa-trash:before { - content: "\f1f8"; -} -.fa-copyright:before { - content: "\f1f9"; -} -.fa-at:before { - content: "\f1fa"; -} -.fa-eyedropper:before { - content: "\f1fb"; -} -.fa-paint-brush:before { - content: "\f1fc"; -} -.fa-birthday-cake:before { - content: "\f1fd"; -} -.fa-area-chart:before { - content: "\f1fe"; -} -.fa-pie-chart:before { - content: "\f200"; -} -.fa-line-chart:before { - content: "\f201"; -} -.fa-lastfm:before { - content: "\f202"; -} -.fa-lastfm-square:before { - content: "\f203"; -} -.fa-toggle-off:before { - content: "\f204"; -} -.fa-toggle-on:before { - content: "\f205"; -} -.fa-bicycle:before { - content: "\f206"; -} -.fa-bus:before { - content: "\f207"; -} -.fa-ioxhost:before { - content: "\f208"; -} -.fa-angellist:before { - content: "\f209"; -} -.fa-cc:before { - content: "\f20a"; -} -.fa-shekel:before, -.fa-sheqel:before, -.fa-ils:before { - content: "\f20b"; -} -.fa-meanpath:before { - content: "\f20c"; -} -.fa-buysellads:before { - content: "\f20d"; -} -.fa-connectdevelop:before { - content: "\f20e"; -} -.fa-dashcube:before { - content: "\f210"; -} -.fa-forumbee:before { - content: "\f211"; -} -.fa-leanpub:before { - content: "\f212"; -} -.fa-sellsy:before { - content: "\f213"; -} -.fa-shirtsinbulk:before { - content: "\f214"; -} -.fa-simplybuilt:before { - content: "\f215"; -} -.fa-skyatlas:before { - content: "\f216"; -} -.fa-cart-plus:before { - content: "\f217"; -} -.fa-cart-arrow-down:before { - content: "\f218"; -} -.fa-diamond:before { - content: "\f219"; -} -.fa-ship:before { - content: "\f21a"; -} -.fa-user-secret:before { - content: "\f21b"; -} -.fa-motorcycle:before { - content: "\f21c"; -} -.fa-street-view:before { - content: "\f21d"; -} -.fa-heartbeat:before { - content: "\f21e"; -} -.fa-venus:before { - content: "\f221"; -} -.fa-mars:before { - content: "\f222"; -} -.fa-mercury:before { - content: "\f223"; -} -.fa-intersex:before, -.fa-transgender:before { - content: "\f224"; -} -.fa-transgender-alt:before { - content: "\f225"; -} -.fa-venus-double:before { - content: "\f226"; -} -.fa-mars-double:before { - content: "\f227"; -} -.fa-venus-mars:before { - content: "\f228"; -} -.fa-mars-stroke:before { - content: "\f229"; -} -.fa-mars-stroke-v:before { - content: "\f22a"; -} -.fa-mars-stroke-h:before { - content: "\f22b"; -} -.fa-neuter:before { - content: "\f22c"; -} -.fa-genderless:before { - content: "\f22d"; -} -.fa-facebook-official:before { - content: "\f230"; -} -.fa-pinterest-p:before { - content: "\f231"; -} -.fa-whatsapp:before { - content: "\f232"; -} -.fa-server:before { - content: "\f233"; -} -.fa-user-plus:before { - content: "\f234"; -} -.fa-user-times:before { - content: "\f235"; -} -.fa-hotel:before, -.fa-bed:before { - content: "\f236"; -} -.fa-viacoin:before { - content: "\f237"; -} -.fa-train:before { - content: "\f238"; -} -.fa-subway:before { - content: "\f239"; -} -.fa-medium:before { - content: "\f23a"; -} -.fa-yc:before, -.fa-y-combinator:before { - content: "\f23b"; -} -.fa-optin-monster:before { - content: "\f23c"; -} -.fa-opencart:before { - content: "\f23d"; -} -.fa-expeditedssl:before { - content: "\f23e"; -} -.fa-battery-4:before, -.fa-battery:before, -.fa-battery-full:before { - content: "\f240"; -} -.fa-battery-3:before, -.fa-battery-three-quarters:before { - content: "\f241"; -} -.fa-battery-2:before, -.fa-battery-half:before { - content: "\f242"; -} -.fa-battery-1:before, -.fa-battery-quarter:before { - content: "\f243"; -} -.fa-battery-0:before, -.fa-battery-empty:before { - content: "\f244"; -} -.fa-mouse-pointer:before { - content: "\f245"; -} -.fa-i-cursor:before { - content: "\f246"; -} -.fa-object-group:before { - content: "\f247"; -} -.fa-object-ungroup:before { - content: "\f248"; -} -.fa-sticky-note:before { - content: "\f249"; -} -.fa-sticky-note-o:before { - content: "\f24a"; -} -.fa-cc-jcb:before { - content: "\f24b"; -} -.fa-cc-diners-club:before { - content: "\f24c"; -} -.fa-clone:before { - content: "\f24d"; -} -.fa-balance-scale:before { - content: "\f24e"; -} -.fa-hourglass-o:before { - content: "\f250"; -} -.fa-hourglass-1:before, -.fa-hourglass-start:before { - content: "\f251"; -} -.fa-hourglass-2:before, -.fa-hourglass-half:before { - content: "\f252"; -} -.fa-hourglass-3:before, -.fa-hourglass-end:before { - content: "\f253"; -} -.fa-hourglass:before { - content: "\f254"; -} -.fa-hand-grab-o:before, -.fa-hand-rock-o:before { - content: "\f255"; -} -.fa-hand-stop-o:before, -.fa-hand-paper-o:before { - content: "\f256"; -} -.fa-hand-scissors-o:before { - content: "\f257"; -} -.fa-hand-lizard-o:before { - content: "\f258"; -} -.fa-hand-spock-o:before { - content: "\f259"; -} -.fa-hand-pointer-o:before { - content: "\f25a"; -} -.fa-hand-peace-o:before { - content: "\f25b"; -} -.fa-trademark:before { - content: "\f25c"; -} -.fa-registered:before { - content: "\f25d"; -} -.fa-creative-commons:before { - content: "\f25e"; -} -.fa-gg:before { - content: "\f260"; -} -.fa-gg-circle:before { - content: "\f261"; -} -.fa-tripadvisor:before { - content: "\f262"; -} -.fa-odnoklassniki:before { - content: "\f263"; -} -.fa-odnoklassniki-square:before { - content: "\f264"; -} -.fa-get-pocket:before { - content: "\f265"; -} -.fa-wikipedia-w:before { - content: "\f266"; -} -.fa-safari:before { - content: "\f267"; -} -.fa-chrome:before { - content: "\f268"; -} -.fa-firefox:before { - content: "\f269"; -} -.fa-opera:before { - content: "\f26a"; -} -.fa-internet-explorer:before { - content: "\f26b"; -} -.fa-tv:before, -.fa-television:before { - content: "\f26c"; -} -.fa-contao:before { - content: "\f26d"; -} -.fa-500px:before { - content: "\f26e"; -} -.fa-amazon:before { - content: "\f270"; -} -.fa-calendar-plus-o:before { - content: "\f271"; -} -.fa-calendar-minus-o:before { - content: "\f272"; -} -.fa-calendar-times-o:before { - content: "\f273"; -} -.fa-calendar-check-o:before { - content: "\f274"; -} -.fa-industry:before { - content: "\f275"; -} -.fa-map-pin:before { - content: "\f276"; -} -.fa-map-signs:before { - content: "\f277"; -} -.fa-map-o:before { - content: "\f278"; -} -.fa-map:before { - content: "\f279"; -} -.fa-commenting:before { - content: "\f27a"; -} -.fa-commenting-o:before { - content: "\f27b"; -} -.fa-houzz:before { - content: "\f27c"; -} -.fa-vimeo:before { - content: "\f27d"; -} -.fa-black-tie:before { - content: "\f27e"; -} -.fa-fonticons:before { - content: "\f280"; -} -.fa-reddit-alien:before { - content: "\f281"; -} -.fa-edge:before { - content: "\f282"; -} -.fa-credit-card-alt:before { - content: "\f283"; -} -.fa-codiepie:before { - content: "\f284"; -} -.fa-modx:before { - content: "\f285"; -} -.fa-fort-awesome:before { - content: "\f286"; -} -.fa-usb:before { - content: "\f287"; -} -.fa-product-hunt:before { - content: "\f288"; -} -.fa-mixcloud:before { - content: "\f289"; -} -.fa-scribd:before { - content: "\f28a"; -} -.fa-pause-circle:before { - content: "\f28b"; -} -.fa-pause-circle-o:before { - content: "\f28c"; -} -.fa-stop-circle:before { - content: "\f28d"; -} -.fa-stop-circle-o:before { - content: "\f28e"; -} -.fa-shopping-bag:before { - content: "\f290"; -} -.fa-shopping-basket:before { - content: "\f291"; -} -.fa-hashtag:before { - content: "\f292"; -} -.fa-bluetooth:before { - content: "\f293"; -} -.fa-bluetooth-b:before { - content: "\f294"; -} -.fa-percent:before { - content: "\f295"; -} -.fa-gitlab:before { - content: "\f296"; -} -.fa-wpbeginner:before { - content: "\f297"; -} -.fa-wpforms:before { - content: "\f298"; -} -.fa-envira:before { - content: "\f299"; -} -.fa-universal-access:before { - content: "\f29a"; -} -.fa-wheelchair-alt:before { - content: "\f29b"; -} -.fa-question-circle-o:before { - content: "\f29c"; -} -.fa-blind:before { - content: "\f29d"; -} -.fa-audio-description:before { - content: "\f29e"; -} -.fa-volume-control-phone:before { - content: "\f2a0"; -} -.fa-braille:before { - content: "\f2a1"; -} -.fa-assistive-listening-systems:before { - content: "\f2a2"; -} -.fa-asl-interpreting:before, -.fa-american-sign-language-interpreting:before { - content: "\f2a3"; -} -.fa-deafness:before, -.fa-hard-of-hearing:before, -.fa-deaf:before { - content: "\f2a4"; -} -.fa-glide:before { - content: "\f2a5"; -} -.fa-glide-g:before { - content: "\f2a6"; -} -.fa-signing:before, -.fa-sign-language:before { - content: "\f2a7"; -} -.fa-low-vision:before { - content: "\f2a8"; -} -.fa-viadeo:before { - content: "\f2a9"; -} -.fa-viadeo-square:before { - content: "\f2aa"; -} -.fa-snapchat:before { - content: "\f2ab"; -} -.fa-snapchat-ghost:before { - content: "\f2ac"; -} -.fa-snapchat-square:before { - content: "\f2ad"; -} -.fa-pied-piper:before { - content: "\f2ae"; -} -.fa-first-order:before { - content: "\f2b0"; -} -.fa-yoast:before { - content: "\f2b1"; -} -.fa-themeisle:before { - content: "\f2b2"; -} -.fa-google-plus-circle:before, -.fa-google-plus-official:before { - content: "\f2b3"; -} -.fa-fa:before, -.fa-font-awesome:before { - content: "\f2b4"; -} -.fa-handshake-o:before { - content: "\f2b5"; -} -.fa-envelope-open:before { - content: "\f2b6"; -} -.fa-envelope-open-o:before { - content: "\f2b7"; -} -.fa-linode:before { - content: "\f2b8"; -} -.fa-address-book:before { - content: "\f2b9"; -} -.fa-address-book-o:before { - content: "\f2ba"; -} -.fa-vcard:before, -.fa-address-card:before { - content: "\f2bb"; -} -.fa-vcard-o:before, -.fa-address-card-o:before { - content: "\f2bc"; -} -.fa-user-circle:before { - content: "\f2bd"; -} -.fa-user-circle-o:before { - content: "\f2be"; -} -.fa-user-o:before { - content: "\f2c0"; -} -.fa-id-badge:before { - content: "\f2c1"; -} -.fa-drivers-license:before, -.fa-id-card:before { - content: "\f2c2"; -} -.fa-drivers-license-o:before, -.fa-id-card-o:before { - content: "\f2c3"; -} -.fa-quora:before { - content: "\f2c4"; -} -.fa-free-code-camp:before { - content: "\f2c5"; -} -.fa-telegram:before { - content: "\f2c6"; -} -.fa-thermometer-4:before, -.fa-thermometer:before, -.fa-thermometer-full:before { - content: "\f2c7"; -} -.fa-thermometer-3:before, -.fa-thermometer-three-quarters:before { - content: "\f2c8"; -} -.fa-thermometer-2:before, -.fa-thermometer-half:before { - content: "\f2c9"; -} -.fa-thermometer-1:before, -.fa-thermometer-quarter:before { - content: "\f2ca"; -} -.fa-thermometer-0:before, -.fa-thermometer-empty:before { - content: "\f2cb"; -} -.fa-shower:before { - content: "\f2cc"; -} -.fa-bathtub:before, -.fa-s15:before, -.fa-bath:before { - content: "\f2cd"; -} -.fa-podcast:before { - content: "\f2ce"; -} -.fa-window-maximize:before { - content: "\f2d0"; -} -.fa-window-minimize:before { - content: "\f2d1"; -} -.fa-window-restore:before { - content: "\f2d2"; -} -.fa-times-rectangle:before, -.fa-window-close:before { - content: "\f2d3"; -} -.fa-times-rectangle-o:before, -.fa-window-close-o:before { - content: "\f2d4"; -} -.fa-bandcamp:before { - content: "\f2d5"; -} -.fa-grav:before { - content: "\f2d6"; -} -.fa-etsy:before { - content: "\f2d7"; -} -.fa-imdb:before { - content: "\f2d8"; -} -.fa-ravelry:before { - content: "\f2d9"; -} -.fa-eercast:before { - content: "\f2da"; -} -.fa-microchip:before { - content: "\f2db"; -} -.fa-snowflake-o:before { - content: "\f2dc"; -} -.fa-superpowers:before { - content: "\f2dd"; -} -.fa-wpexplorer:before { - content: "\f2de"; -} -.fa-meetup:before { - content: "\f2e0"; -} -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0; -} -.sr-only-focusable:active, -.sr-only-focusable:focus { - position: static; - width: auto; - height: auto; - margin: 0; - overflow: visible; - clip: auto; -} diff --git a/public/s/font-awesome-4.7.0/css/font-awesome.min.css b/public/s/font-awesome-4.7.0/css/font-awesome.min.css deleted file mode 100644 index 540440c..0000000 --- a/public/s/font-awesome-4.7.0/css/font-awesome.min.css +++ /dev/null @@ -1,4 +0,0 @@ -/*! - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} diff --git a/public/s/font-awesome-4.7.0/fonts/fontawesome-webfont.eot b/public/s/font-awesome-4.7.0/fonts/fontawesome-webfont.eot deleted file mode 100644 index e9f60ca..0000000 Binary files a/public/s/font-awesome-4.7.0/fonts/fontawesome-webfont.eot and /dev/null differ diff --git a/public/s/font-awesome-4.7.0/fonts/fontawesome-webfont.svg b/public/s/font-awesome-4.7.0/fonts/fontawesome-webfont.svg deleted file mode 100644 index 855c845..0000000 --- a/public/s/font-awesome-4.7.0/fonts/fontawesome-webfont.svg +++ /dev/null @@ -1,2671 +0,0 @@ - - - - -Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 - By ,,, -Copyright Dave Gandy 2016. All rights reserved. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/public/s/font-awesome-4.7.0/fonts/fontawesome-webfont.ttf b/public/s/font-awesome-4.7.0/fonts/fontawesome-webfont.ttf deleted file mode 100644 index 35acda2..0000000 Binary files a/public/s/font-awesome-4.7.0/fonts/fontawesome-webfont.ttf and /dev/null differ diff --git a/public/s/font-awesome-4.7.0/fonts/fontawesome-webfont.woff b/public/s/font-awesome-4.7.0/fonts/fontawesome-webfont.woff deleted file mode 100644 index 400014a..0000000 Binary files a/public/s/font-awesome-4.7.0/fonts/fontawesome-webfont.woff and /dev/null differ diff --git a/public/s/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2 b/public/s/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2 deleted file mode 100644 index 4d13fc6..0000000 Binary files a/public/s/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2 and /dev/null differ diff --git a/public/s/js/bootstrap.min.js b/public/s/js/bootstrap.min.js deleted file mode 100644 index e5a2429..0000000 --- a/public/s/js/bootstrap.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Bootstrap v4.4.1 (https://getbootstrap.com/) - * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery"),require("popper.js")):"function"==typeof define&&define.amd?define(["exports","jquery","popper.js"],e):e((t=t||self).bootstrap={},t.jQuery,t.Popper)}(this,function(t,g,u){"use strict";function i(t,e){for(var n=0;nthis._items.length-1||t<0))if(this._isSliding)g(this._element).one(Y.SLID,function(){return e.to(t)});else{if(n===t)return this.pause(),void this.cycle();var i=ndocument.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},t._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},t._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=t.left+t.right',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:Se,popperConfig:null},Fe="show",Ue="out",We={HIDE:"hide"+Oe,HIDDEN:"hidden"+Oe,SHOW:"show"+Oe,SHOWN:"shown"+Oe,INSERTED:"inserted"+Oe,CLICK:"click"+Oe,FOCUSIN:"focusin"+Oe,FOCUSOUT:"focusout"+Oe,MOUSEENTER:"mouseenter"+Oe,MOUSELEAVE:"mouseleave"+Oe},qe="fade",Me="show",Ke=".tooltip-inner",Qe=".arrow",Be="hover",Ve="focus",Ye="click",ze="manual",Xe=function(){function i(t,e){if("undefined"==typeof u)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var t=i.prototype;return t.enable=function(){this._isEnabled=!0},t.disable=function(){this._isEnabled=!1},t.toggleEnabled=function(){this._isEnabled=!this._isEnabled},t.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=g(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(g(this.getTipElement()).hasClass(Me))return void this._leave(null,this);this._enter(null,this)}},t.dispose=function(){clearTimeout(this._timeout),g.removeData(this.element,this.constructor.DATA_KEY),g(this.element).off(this.constructor.EVENT_KEY),g(this.element).closest(".modal").off("hide.bs.modal",this._hideModalHandler),this.tip&&g(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},t.show=function(){var e=this;if("none"===g(this.element).css("display"))throw new Error("Please use show on visible elements");var t=g.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){g(this.element).trigger(t);var n=_.findShadowRoot(this.element),i=g.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(t.isDefaultPrevented()||!i)return;var o=this.getTipElement(),r=_.getUID(this.constructor.NAME);o.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&g(o).addClass(qe);var s="function"==typeof this.config.placement?this.config.placement.call(this,o,this.element):this.config.placement,a=this._getAttachment(s);this.addAttachmentClass(a);var l=this._getContainer();g(o).data(this.constructor.DATA_KEY,this),g.contains(this.element.ownerDocument.documentElement,this.tip)||g(o).appendTo(l),g(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new u(this.element,o,this._getPopperConfig(a)),g(o).addClass(Me),"ontouchstart"in document.documentElement&&g(document.body).children().on("mouseover",null,g.noop);var c=function(){e.config.animation&&e._fixTransition();var t=e._hoverState;e._hoverState=null,g(e.element).trigger(e.constructor.Event.SHOWN),t===Ue&&e._leave(null,e)};if(g(this.tip).hasClass(qe)){var h=_.getTransitionDurationFromElement(this.tip);g(this.tip).one(_.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},t.hide=function(t){function e(){n._hoverState!==Fe&&i.parentNode&&i.parentNode.removeChild(i),n._cleanTipClass(),n.element.removeAttribute("aria-describedby"),g(n.element).trigger(n.constructor.Event.HIDDEN),null!==n._popper&&n._popper.destroy(),t&&t()}var n=this,i=this.getTipElement(),o=g.Event(this.constructor.Event.HIDE);if(g(this.element).trigger(o),!o.isDefaultPrevented()){if(g(i).removeClass(Me),"ontouchstart"in document.documentElement&&g(document.body).children().off("mouseover",null,g.noop),this._activeTrigger[Ye]=!1,this._activeTrigger[Ve]=!1,this._activeTrigger[Be]=!1,g(this.tip).hasClass(qe)){var r=_.getTransitionDurationFromElement(i);g(i).one(_.TRANSITION_END,e).emulateTransitionEnd(r)}else e();this._hoverState=""}},t.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},t.isWithContent=function(){return Boolean(this.getTitle())},t.addAttachmentClass=function(t){g(this.getTipElement()).addClass(Pe+"-"+t)},t.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},t.setContent=function(){var t=this.getTipElement();this.setElementContent(g(t.querySelectorAll(Ke)),this.getTitle()),g(t).removeClass(qe+" "+Me)},t.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=we(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?g(e).parent().is(t)||t.empty().append(e):t.text(g(e).text())},t.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t=t||("function"==typeof this.config.title?this.config.title.call(this.element):this.config.title)},t._getPopperConfig=function(t){var e=this;return l({},{placement:t,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:Qe},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}},{},this.config.popperConfig)},t._getOffset=function(){var e=this,t={};return"function"==typeof this.config.offset?t.fn=function(t){return t.offsets=l({},t.offsets,{},e.config.offset(t.offsets,e.element)||{}),t}:t.offset=this.config.offset,t},t._getContainer=function(){return!1===this.config.container?document.body:_.isElement(this.config.container)?g(this.config.container):g(document).find(this.config.container)},t._getAttachment=function(t){return Re[t.toUpperCase()]},t._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(t){if("click"===t)g(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(t){return i.toggle(t)});else if(t!==ze){var e=t===Be?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=t===Be?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;g(i.element).on(e,i.config.selector,function(t){return i._enter(t)}).on(n,i.config.selector,function(t){return i._leave(t)})}}),this._hideModalHandler=function(){i.element&&i.hide()},g(this.element).closest(".modal").on("hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},t._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");!this.element.getAttribute("title")&&"string"==t||(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},t._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Ve:Be]=!0),g(e.getTipElement()).hasClass(Me)||e._hoverState===Fe?e._hoverState=Fe:(clearTimeout(e._timeout),e._hoverState=Fe,e.config.delay&&e.config.delay.show?e._timeout=setTimeout(function(){e._hoverState===Fe&&e.show()},e.config.delay.show):e.show())},t._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Ve:Be]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=Ue,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout(function(){e._hoverState===Ue&&e.hide()},e.config.delay.hide):e.hide())},t._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},t._getConfig=function(t){var e=g(this.element).data();return Object.keys(e).forEach(function(t){-1!==je.indexOf(t)&&delete e[t]}),"number"==typeof(t=l({},this.constructor.Default,{},e,{},"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),_.typeCheckConfig(Ae,t,this.constructor.DefaultType),t.sanitize&&(t.template=we(t.template,t.whiteList,t.sanitizeFn)),t},t._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},t._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Le);null!==e&&e.length&&t.removeClass(e.join(""))},t._handlePopperPlacementChange=function(t){var e=t.instance;this.tip=e.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},t._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(g(t).removeClass(qe),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},i._jQueryInterface=function(n){return this.each(function(){var t=g(this).data(Ne),e="object"==typeof n&&n;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),g(this).data(Ne,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.4.1"}},{key:"Default",get:function(){return xe}},{key:"NAME",get:function(){return Ae}},{key:"DATA_KEY",get:function(){return Ne}},{key:"Event",get:function(){return We}},{key:"EVENT_KEY",get:function(){return Oe}},{key:"DefaultType",get:function(){return He}}]),i}();g.fn[Ae]=Xe._jQueryInterface,g.fn[Ae].Constructor=Xe,g.fn[Ae].noConflict=function(){return g.fn[Ae]=ke,Xe._jQueryInterface};var $e="popover",Ge="bs.popover",Je="."+Ge,Ze=g.fn[$e],tn="bs-popover",en=new RegExp("(^|\\s)"+tn+"\\S+","g"),nn=l({},Xe.Default,{placement:"right",trigger:"click",content:"",template:''}),on=l({},Xe.DefaultType,{content:"(string|element|function)"}),rn="fade",sn="show",an=".popover-header",ln=".popover-body",cn={HIDE:"hide"+Je,HIDDEN:"hidden"+Je,SHOW:"show"+Je,SHOWN:"shown"+Je,INSERTED:"inserted"+Je,CLICK:"click"+Je,FOCUSIN:"focusin"+Je,FOCUSOUT:"focusout"+Je,MOUSEENTER:"mouseenter"+Je,MOUSELEAVE:"mouseleave"+Je},hn=function(t){function i(){return t.apply(this,arguments)||this}!function(t,e){t.prototype=Object.create(e.prototype),(t.prototype.constructor=t).__proto__=e}(i,t);var e=i.prototype;return e.isWithContent=function(){return this.getTitle()||this._getContent()},e.addAttachmentClass=function(t){g(this.getTipElement()).addClass(tn+"-"+t)},e.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},e.setContent=function(){var t=g(this.getTipElement());this.setElementContent(t.find(an),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(ln),e),t.removeClass(rn+" "+sn)},e._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},e._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(en);null!==e&&0=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t li > .active",Qn='[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',Bn=".dropdown-toggle",Vn="> .dropdown-menu .active",Yn=function(){function i(t){this._element=t}var t=i.prototype;return t.show=function(){var n=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&g(this._element).hasClass(Rn)||g(this._element).hasClass(xn))){var t,i,e=g(this._element).closest(qn)[0],o=_.getSelectorFromElement(this._element);if(e){var r="UL"===e.nodeName||"OL"===e.nodeName?Kn:Mn;i=(i=g.makeArray(g(e).find(r)))[i.length-1]}var s=g.Event(jn.HIDE,{relatedTarget:this._element}),a=g.Event(jn.SHOW,{relatedTarget:i});if(i&&g(i).trigger(s),g(this._element).trigger(a),!a.isDefaultPrevented()&&!s.isDefaultPrevented()){o&&(t=document.querySelector(o)),this._activate(this._element,e);var l=function(){var t=g.Event(jn.HIDDEN,{relatedTarget:n._element}),e=g.Event(jn.SHOWN,{relatedTarget:i});g(i).trigger(t),g(n._element).trigger(e)};t?this._activate(t,t.parentNode,l):l()}}},t.dispose=function(){g.removeData(this._element,kn),this._element=null},t._activate=function(t,e,n){function i(){return o._transitionComplete(t,r,n)}var o=this,r=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?g(e).children(Mn):g(e).find(Kn))[0],s=n&&r&&g(r).hasClass(Fn);if(r&&s){var a=_.getTransitionDurationFromElement(r);g(r).removeClass(Un).one(_.TRANSITION_END,i).emulateTransitionEnd(a)}else i()},t._transitionComplete=function(t,e,n){if(e){g(e).removeClass(Rn);var i=g(e.parentNode).find(Vn)[0];i&&g(i).removeClass(Rn),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}if(g(t).addClass(Rn),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),_.reflow(t),t.classList.contains(Fn)&&t.classList.add(Un),t.parentNode&&g(t.parentNode).hasClass(Hn)){var o=g(t).closest(Wn)[0];if(o){var r=[].slice.call(o.querySelectorAll(Bn));g(r).addClass(Rn)}t.setAttribute("aria-expanded",!0)}n&&n()},i._jQueryInterface=function(n){return this.each(function(){var t=g(this),e=t.data(kn);if(e||(e=new i(this),t.data(kn,e)),"string"==typeof n){if("undefined"==typeof e[n])throw new TypeError('No method named "'+n+'"');e[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.4.1"}}]),i}();g(document).on(jn.CLICK_DATA_API,Qn,function(t){t.preventDefault(),Yn._jQueryInterface.call(g(this),"show")}),g.fn.tab=Yn._jQueryInterface,g.fn.tab.Constructor=Yn,g.fn.tab.noConflict=function(){return g.fn.tab=Ln,Yn._jQueryInterface};var zn="toast",Xn="bs.toast",$n="."+Xn,Gn=g.fn[zn],Jn={CLICK_DISMISS:"click.dismiss"+$n,HIDE:"hide"+$n,HIDDEN:"hidden"+$n,SHOW:"show"+$n,SHOWN:"shown"+$n},Zn="fade",ti="hide",ei="show",ni="showing",ii={animation:"boolean",autohide:"boolean",delay:"number"},oi={animation:!0,autohide:!0,delay:500},ri='[data-dismiss="toast"]',si=function(){function i(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var t=i.prototype;return t.show=function(){var t=this,e=g.Event(Jn.SHOW);if(g(this._element).trigger(e),!e.isDefaultPrevented()){this._config.animation&&this._element.classList.add(Zn);var n=function(){t._element.classList.remove(ni),t._element.classList.add(ei),g(t._element).trigger(Jn.SHOWN),t._config.autohide&&(t._timeout=setTimeout(function(){t.hide()},t._config.delay))};if(this._element.classList.remove(ti),_.reflow(this._element),this._element.classList.add(ni),this._config.animation){var i=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,n).emulateTransitionEnd(i)}else n()}},t.hide=function(){if(this._element.classList.contains(ei)){var t=g.Event(Jn.HIDE);g(this._element).trigger(t),t.isDefaultPrevented()||this._close()}},t.dispose=function(){clearTimeout(this._timeout),this._timeout=null,this._element.classList.contains(ei)&&this._element.classList.remove(ei),g(this._element).off(Jn.CLICK_DISMISS),g.removeData(this._element,Xn),this._element=null,this._config=null},t._getConfig=function(t){return t=l({},oi,{},g(this._element).data(),{},"object"==typeof t&&t?t:{}),_.typeCheckConfig(zn,t,this.constructor.DefaultType),t},t._setListeners=function(){var t=this;g(this._element).on(Jn.CLICK_DISMISS,ri,function(){return t.hide()})},t._close=function(){function t(){e._element.classList.add(ti),g(e._element).trigger(Jn.HIDDEN)}var e=this;if(this._element.classList.remove(ei),this._config.animation){var n=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,t).emulateTransitionEnd(n)}else t()},i._jQueryInterface=function(n){return this.each(function(){var t=g(this),e=t.data(Xn);if(e||(e=new i(this,"object"==typeof n&&n),t.data(Xn,e)),"string"==typeof n){if("undefined"==typeof e[n])throw new TypeError('No method named "'+n+'"');e[n](this)}})},s(i,null,[{key:"VERSION",get:function(){return"4.4.1"}},{key:"DefaultType",get:function(){return ii}},{key:"Default",get:function(){return oi}}]),i}();g.fn[zn]=si._jQueryInterface,g.fn[zn].Constructor=si,g.fn[zn].noConflict=function(){return g.fn[zn]=Gn,si._jQueryInterface},t.Alert=v,t.Button=H,t.Carousel=ut,t.Collapse=wt,t.Dropdown=ee,t.Modal=Te,t.Popover=hn,t.Scrollspy=On,t.Tab=Yn,t.Toast=si,t.Tooltip=Xe,t.Util=_,Object.defineProperty(t,"__esModule",{value:!0})}); -//# sourceMappingURL=bootstrap.min.js.map \ No newline at end of file diff --git a/public/s/js/plyr.js b/public/s/js/plyr.js deleted file mode 100644 index 4d49560..0000000 --- a/public/s/js/plyr.js +++ /dev/null @@ -1,3772 +0,0 @@ -// ========================================================================== -// Plyr -// plyr.js v2.0.11 -// https://github.com/selz/plyr -// License: The MIT License (MIT) -// ========================================================================== -// Credits: http://paypal.github.io/accessible-html5-video-player/ -// ========================================================================== - -;(function(root, factory) { - 'use strict'; - /*global define,module*/ - - if (typeof module === 'object' && typeof module.exports === 'object') { - // Node, CommonJS-like - module.exports = factory(root, document); - } else if (typeof define === 'function' && define.amd) { - // AMD - define([], function () { return factory(root, document); }); - } else { - // Browser globals (root is window) - root.plyr = factory(root, document); - } -}(typeof window !== 'undefined' ? window : this, function(window, document) { - 'use strict'; - - // Globals - var fullscreen, - scroll = { x: 0, y: 0 }, - - // Default config - defaults = { - enabled: true, - debug: false, - autoplay: false, - loop: false, - seekTime: 10, - volume: 10, - volumeMin: 0, - volumeMax: 10, - volumeStep: 1, - duration: null, - displayDuration: true, - loadSprite: true, - iconPrefix: 'plyr', - iconUrl: 'https://f0ck.me/s/plyr.svg', - clickToPlay: true, - hideControls: true, - showPosterOnEnd: false, - disableContextMenu: true, - keyboardShorcuts: { - focused: true, - global: false - }, - tooltips: { - controls: false, - seek: true - }, - selectors: { - html5: 'video, audio', - embed: '[data-type]', - editable: 'input, textarea, select, [contenteditable]', - container: '.plyr', - controls: { - container: null, - wrapper: '.plyr__controls' - }, - labels: '[data-plyr]', - buttons: { - seek: '[data-plyr="seek"]', - play: '[data-plyr="play"]', - pause: '[data-plyr="pause"]', - restart: '[data-plyr="restart"]', - rewind: '[data-plyr="rewind"]', - forward: '[data-plyr="fast-forward"]', - mute: '[data-plyr="mute"]', - captions: '[data-plyr="captions"]', - fullscreen: '[data-plyr="fullscreen"]' - }, - volume: { - input: '[data-plyr="volume"]', - display: '.plyr__volume--display' - }, - progress: { - container: '.plyr__progress', - buffer: '.plyr__progress--buffer', - played: '.plyr__progress--played' - }, - captions: '.plyr__captions', - currentTime: '.plyr__time--current', - duration: '.plyr__time--duration' - }, - classes: { - setup: 'plyr--setup', - ready: 'plyr--ready', - videoWrapper: 'plyr__video-wrapper', - embedWrapper: 'plyr__video-embed', - type: 'plyr--{0}', - stopped: 'plyr--stopped', - playing: 'plyr--playing', - muted: 'plyr--muted', - loading: 'plyr--loading', - hover: 'plyr--hover', - tooltip: 'plyr__tooltip', - hidden: 'plyr__sr-only', - hideControls: 'plyr--hide-controls', - isIos: 'plyr--is-ios', - isTouch: 'plyr--is-touch', - captions: { - enabled: 'plyr--captions-enabled', - active: 'plyr--captions-active' - }, - fullscreen: { - enabled: 'plyr--fullscreen-enabled', - active: 'plyr--fullscreen-active' - }, - tabFocus: 'tab-focus' - }, - captions: { - defaultActive: false - }, - fullscreen: { - enabled: true, - fallback: true, - allowAudio: false - }, - storage: { - enabled: true, - key: 'plyr' - }, - controls: ['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'fullscreen'], - i18n: { - restart: 'Restart', - rewind: 'Rewind {seektime} secs', - play: 'Play', - pause: 'Pause', - forward: 'Forward {seektime} secs', - played: 'played', - buffered: 'buffered', - currentTime: 'Current time', - duration: 'Duration', - volume: 'Volume', - toggleMute: 'Toggle Mute', - toggleCaptions: 'Toggle Captions', - toggleFullscreen: 'Toggle Fullscreen', - frameTitle: 'Player for {title}' - }, - types: { - embed: ['youtube', 'vimeo', 'soundcloud'], - html5: ['video', 'audio'] - }, - // URLs - urls: { - vimeo: { - api: 'https://player.vimeo.com/api/player.js', - }, - youtube: { - api: 'https://www.youtube.com/iframe_api' - }, - soundcloud: { - api: 'https://w.soundcloud.com/player/api.js' - } - }, - // Custom control listeners - listeners: { - seek: null, - play: null, - pause: null, - restart: null, - rewind: null, - forward: null, - mute: null, - volume: null, - captions: null, - fullscreen: null - }, - // Events to watch on HTML5 media elements - events: ['ready', 'ended', 'progress', 'stalled', 'playing', 'waiting', 'canplay', 'canplaythrough', 'loadstart', 'loadeddata', 'loadedmetadata', 'timeupdate', 'volumechange', 'play', 'pause', 'error', 'seeking', 'seeked', 'emptied'], - // Logging - logPrefix: '[Plyr]' - }; - - // Credits: http://paypal.github.io/accessible-html5-video-player/ - // Unfortunately, due to mixed support, UA sniffing is required - function _browserSniff() { - var ua = navigator.userAgent, - name = navigator.appName, - fullVersion = '' + parseFloat(navigator.appVersion), - majorVersion = parseInt(navigator.appVersion, 10), - nameOffset, - verOffset, - ix, - isIE = false, - isFirefox = false, - isChrome = false, - isSafari = false; - - if ((navigator.appVersion.indexOf('Windows NT') !== -1) && (navigator.appVersion.indexOf('rv:11') !== -1)) { - // MSIE 11 - isIE = true; - name = 'IE'; - fullVersion = '11'; - } else if ((verOffset = ua.indexOf('MSIE')) !== -1) { - // MSIE - isIE = true; - name = 'IE'; - fullVersion = ua.substring(verOffset + 5); - } else if ((verOffset = ua.indexOf('Chrome')) !== -1) { - // Chrome - isChrome = true; - name = 'Chrome'; - fullVersion = ua.substring(verOffset + 7); - } else if ((verOffset = ua.indexOf('Safari')) !== -1) { - // Safari - isSafari = true; - name = 'Safari'; - fullVersion = ua.substring(verOffset + 7); - if ((verOffset = ua.indexOf('Version')) !== -1) { - fullVersion = ua.substring(verOffset + 8); - } - } else if ((verOffset = ua.indexOf('Firefox')) !== -1) { - // Firefox - isFirefox = true; - name = 'Firefox'; - fullVersion = ua.substring(verOffset + 8); - } else if ((nameOffset = ua.lastIndexOf(' ') + 1) < (verOffset = ua.lastIndexOf('/'))) { - // In most other browsers, 'name/version' is at the end of userAgent - name = ua.substring(nameOffset,verOffset); - fullVersion = ua.substring(verOffset + 1); - - if (name.toLowerCase() === name.toUpperCase()) { - name = navigator.appName; - } - } - - // Trim the fullVersion string at semicolon/space if present - if ((ix = fullVersion.indexOf(';')) !== -1) { - fullVersion = fullVersion.substring(0, ix); - } - if ((ix = fullVersion.indexOf(' ')) !== -1) { - fullVersion = fullVersion.substring(0, ix); - } - - // Get major version - majorVersion = parseInt('' + fullVersion, 10); - if (isNaN(majorVersion)) { - fullVersion = '' + parseFloat(navigator.appVersion); - majorVersion = parseInt(navigator.appVersion, 10); - } - - // Return data - return { - name: name, - version: majorVersion, - isIE: isIE, - isFirefox: isFirefox, - isChrome: isChrome, - isSafari: isSafari, - isIos: /(iPad|iPhone|iPod)/g.test(navigator.platform), - isIphone: /(iPhone|iPod)/g.test(navigator.userAgent), - isTouch: 'ontouchstart' in document.documentElement - }; - } - - // Check for mime type support against a player instance - // Credits: http://diveintohtml5.info/everything.html - // Related: http://www.leanbackplyr.com/test/h5mt.html - function _supportMime(plyr, mimeType) { - var media = plyr.media; - - if (plyr.type === 'video') { - // Check type - switch (mimeType) { - case 'video/webm': return !!(media.canPlayType && media.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/no/, '')); - case 'video/mp4': return !!(media.canPlayType && media.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/, '')); - case 'video/ogg': return !!(media.canPlayType && media.canPlayType('video/ogg; codecs="theora"').replace(/no/, '')); - } - } else if (plyr.type === 'audio') { - // Check type - switch (mimeType) { - case 'audio/mpeg': return !!(media.canPlayType && media.canPlayType('audio/mpeg;').replace(/no/, '')); - case 'audio/ogg': return !!(media.canPlayType && media.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/, '')); - case 'audio/wav': return !!(media.canPlayType && media.canPlayType('audio/wav; codecs="1"').replace(/no/, '')); - } - } - - // If we got this far, we're stuffed - return false; - } - - // Inject a script - function _injectScript(source) { - if (document.querySelectorAll('script[src="' + source + '"]').length) { - return; - } - - var tag = document.createElement('script'); - tag.src = source; - var firstScriptTag = document.getElementsByTagName('script')[0]; - firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); - } - - // Element exists in an array - function _inArray(haystack, needle) { - return Array.prototype.indexOf && (haystack.indexOf(needle) !== -1); - } - - // Replace all - function _replaceAll(string, find, replace) { - return string.replace(new RegExp(find.replace(/([.*+?\^=!:${}()|\[\]\/\\])/g, '\\$1'), 'g'), replace); - } - - // Wrap an element - function _wrap(elements, wrapper) { - // Convert `elements` to an array, if necessary. - if (!elements.length) { - elements = [elements]; - } - - // Loops backwards to prevent having to clone the wrapper on the - // first element (see `child` below). - for (var i = elements.length - 1; i >= 0; i--) { - var child = (i > 0) ? wrapper.cloneNode(true) : wrapper; - var element = elements[i]; - - // Cache the current parent and sibling. - var parent = element.parentNode; - var sibling = element.nextSibling; - - // Wrap the element (is automatically removed from its current - // parent). - child.appendChild(element); - - // If the element had a sibling, insert the wrapper before - // the sibling to maintain the HTML structure; otherwise, just - // append it to the parent. - if (sibling) { - parent.insertBefore(child, sibling); - } else { - parent.appendChild(child); - } - - return child; - } - } - - // Unwrap an element - // http://plainjs.com/javascript/manipulation/unwrap-a-dom-element-35/ - /*function _unwrap(wrapper) { - // Get the element's parent node - var parent = wrapper.parentNode; - - // Move all children out of the element - while (wrapper.firstChild) { - parent.insertBefore(wrapper.firstChild, wrapper); - } - - // Remove the empty element - parent.removeChild(wrapper); - }*/ - - // Remove an element - function _remove(element) { - if (!element) { - return; - } - element.parentNode.removeChild(element); - } - - // Prepend child - function _prependChild(parent, element) { - parent.insertBefore(element, parent.firstChild); - } - - // Set attributes - function _setAttributes(element, attributes) { - for (var key in attributes) { - element.setAttribute(key, (_is.boolean(attributes[key]) && attributes[key]) ? '' : attributes[key]); - } - } - - // Insert a HTML element - function _insertElement(type, parent, attributes) { - // Create a new - var element = document.createElement(type); - - // Set all passed attributes - _setAttributes(element, attributes); - - // Inject the new element - _prependChild(parent, element); - } - - // Get a classname from selector - function _getClassname(selector) { - return selector.replace('.', ''); - } - - // Toggle class on an element - function _toggleClass(element, className, state) { - if (element) { - if (element.classList) { - element.classList[state ? 'add' : 'remove'](className); - } else { - var name = (' ' + element.className + ' ').replace(/\s+/g, ' ').replace(' ' + className + ' ', ''); - element.className = name + (state ? ' ' + className : ''); - } - } - } - - // Has class name - function _hasClass(element, className) { - if (element) { - if (element.classList) { - return element.classList.contains(className); - } else { - return new RegExp('(\\s|^)' + className + '(\\s|$)').test(element.className); - } - } - return false; - } - - // Element matches selector - function _matches(element, selector) { - var p = Element.prototype; - - var f = p.matches || p.webkitMatchesSelector || p.mozMatchesSelector || p.msMatchesSelector || function(s) { - return [].indexOf.call(document.querySelectorAll(s), this) !== -1; - }; - - return f.call(element, selector); - } - - // Bind along with custom handler - function _proxyListener(element, eventName, userListener, defaultListener, useCapture) { - _on(element, eventName, function(event) { - if (userListener) { - userListener.apply(element, [event]); - } - defaultListener.apply(element, [event]); - }, useCapture); - } - - // Toggle event listener - function _toggleListener(element, events, callback, toggle, useCapture) { - var eventList = events.split(' '); - - // Whether the listener is a capturing listener or not - // Default to false - if (!_is.boolean(useCapture)) { - useCapture = false; - } - - // If a nodelist is passed, call itself on each node - if (element instanceof NodeList) { - for (var x = 0; x < element.length; x++) { - if (element[x] instanceof Node) { - _toggleListener(element[x], arguments[1], arguments[2], arguments[3]); - } - } - return; - } - - // If a single node is passed, bind the event listener - for (var i = 0; i < eventList.length; i++) { - element[toggle ? 'addEventListener' : 'removeEventListener'](eventList[i], callback, useCapture); - } - } - - // Bind event - function _on(element, events, callback, useCapture) { - if (element) { - _toggleListener(element, events, callback, true, useCapture); - } - } - - // Unbind event - /*function _off(element, events, callback, useCapture) { - if (element) { - _toggleListener(element, events, callback, false, useCapture); - } - }*/ - - // Trigger event - function _event(element, type, bubbles, properties) { - // Bail if no element - if (!element || !type) { - return; - } - - // Default bubbles to false - if (!_is.boolean(bubbles)) { - bubbles = false; - } - - // Create and dispatch the event - var event = new CustomEvent(type, { - bubbles: bubbles, - detail: properties - }); - - // Dispatch the event - element.dispatchEvent(event); - } - - // Toggle aria-pressed state on a toggle button - // http://www.ssbbartgroup.com/blog/how-not-to-misuse-aria-states-properties-and-roles - function _toggleState(target, state) { - // Bail if no target - if (!target) { - return; - } - - // Get state - state = (_is.boolean(state) ? state : !target.getAttribute('aria-pressed')); - - // Set the attribute on target - target.setAttribute('aria-pressed', state); - - return state; - } - - // Get percentage - function _getPercentage(current, max) { - if (current === 0 || max === 0 || isNaN(current) || isNaN(max)) { - return 0; - } - return ((current / max) * 100).toFixed(2); - } - - // Deep extend/merge destination object with N more objects - // http://andrewdupont.net/2009/08/28/deep-extending-objects-in-javascript/ - // Removed call to arguments.callee (used explicit function name instead) - function _extend() { - // Get arguments - var objects = arguments; - - // Bail if nothing to merge - if (!objects.length) { - return; - } - - // Return first if specified but nothing to merge - if (objects.length === 1) { - return objects[0]; - } - - // First object is the destination - var destination = Array.prototype.shift.call(objects), - length = objects.length; - - // Loop through all objects to merge - for (var i = 0; i < length; i++) { - var source = objects[i]; - - for (var property in source) { - if (source[property] && source[property].constructor && source[property].constructor === Object) { - destination[property] = destination[property] || {}; - _extend(destination[property], source[property]); - } else { - destination[property] = source[property]; - } - } - } - - return destination; - } - - // Check variable types - var _is = { - object: function(input) { - return input !== null && typeof(input) === 'object'; - }, - array: function(input) { - return input !== null && (typeof(input) === 'object' && input.constructor === Array); - }, - number: function(input) { - return input !== null && (typeof(input) === 'number' && !isNaN(input - 0) || (typeof input === 'object' && input.constructor === Number)); - }, - string: function(input) { - return input !== null && (typeof input === 'string' || (typeof input === 'object' && input.constructor === String)); - }, - boolean: function(input) { - return input !== null && typeof input === 'boolean'; - }, - nodeList: function(input) { - return input !== null && input instanceof NodeList; - }, - htmlElement: function(input) { - return input !== null && input instanceof HTMLElement; - }, - function: function(input) { - return input !== null && typeof input === 'function'; - }, - undefined: function(input) { - return input !== null && typeof input === 'undefined'; - } - }; - - // Parse YouTube ID from url - function _parseYouTubeId(url) { - var regex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/; - return (url.match(regex)) ? RegExp.$2 : url; - } - - // Parse Vimeo ID from url - function _parseVimeoId(url) { - var regex = /^.*(vimeo.com\/|video\/)(\d+).*/; - return (url.match(regex)) ? RegExp.$2 : url; - } - - // Fullscreen API - function _fullscreen() { - var fullscreen = { - supportsFullScreen: false, - isFullScreen: function() { return false; }, - requestFullScreen: function() {}, - cancelFullScreen: function() {}, - fullScreenEventName: '', - element: null, - prefix: '' - }, - browserPrefixes = 'webkit o moz ms khtml'.split(' '); - - // Check for native support - if (!_is.undefined(document.cancelFullScreen)) { - fullscreen.supportsFullScreen = true; - } else { - // Check for fullscreen support by vendor prefix - for (var i = 0, il = browserPrefixes.length; i < il; i++ ) { - fullscreen.prefix = browserPrefixes[i]; - - if (!_is.undefined(document[fullscreen.prefix + 'CancelFullScreen'])) { - fullscreen.supportsFullScreen = true; - break; - } else if (!_is.undefined(document.msExitFullscreen) && document.msFullscreenEnabled) { - // Special case for MS (when isn't it?) - fullscreen.prefix = 'ms'; - fullscreen.supportsFullScreen = true; - break; - } - } - } - - // Update methods to do something useful - if (fullscreen.supportsFullScreen) { - // Yet again Microsoft awesomeness, - // Sometimes the prefix is 'ms', sometimes 'MS' to keep you on your toes - fullscreen.fullScreenEventName = (fullscreen.prefix === 'ms' ? 'MSFullscreenChange' : fullscreen.prefix + 'fullscreenchange'); - - fullscreen.isFullScreen = function(element) { - if (_is.undefined(element)) { - element = document.body; - } - switch (this.prefix) { - case '': - return document.fullscreenElement === element; - case 'moz': - return document.mozFullScreenElement === element; - default: - return document[this.prefix + 'FullscreenElement'] === element; - } - }; - fullscreen.requestFullScreen = function(element) { - if (_is.undefined(element)) { - element = document.body; - } - return (this.prefix === '') ? element.requestFullScreen() : element[this.prefix + (this.prefix === 'ms' ? 'RequestFullscreen' : 'RequestFullScreen')](); - }; - fullscreen.cancelFullScreen = function() { - return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + (this.prefix === 'ms' ? 'ExitFullscreen' : 'CancelFullScreen')](); - }; - fullscreen.element = function() { - return (this.prefix === '') ? document.fullscreenElement : document[this.prefix + 'FullscreenElement']; - }; - } - - return fullscreen; - } - - // Local storage - var _storage = { - supported: (function() { - if (!('localStorage' in window)) { - return false; - } - - // Try to use it (it might be disabled, e.g. user is in private/porn mode) - // see: https://github.com/Selz/plyr/issues/131 - try { - // Add test item - window.localStorage.setItem('___test', 'OK'); - - // Get the test item - var result = window.localStorage.getItem('___test'); - - // Clean up - window.localStorage.removeItem('___test'); - - // Check if value matches - return (result === 'OK'); - } - catch (e) { - return false; - } - - return false; - })() - }; - - // Player instance - function Plyr(media, config) { - var plyr = this, - timers = {}, - api; - - // Set media - plyr.media = media; - var original = media.cloneNode(true); - - // Trigger events, with plyr instance passed - function _triggerEvent(element, type, bubbles, properties) { - _event(element, type, bubbles, _extend({}, properties, { - plyr: api - })); - } - - // Debugging - function _console(type, args) { - if (config.debug && window.console) { - args = Array.prototype.slice.call(args); - - if (_is.string(config.logPrefix) && config.logPrefix.length) { - args.unshift(config.logPrefix); - } - - console[type].apply(console, args); - } - } - var _log = function() { _console('log', arguments) }, - _warn = function() { _console('warn', arguments) }; - - // Log config options - _log('Config', config); - - // Get icon URL - function _getIconUrl() { - return { - url: config.iconUrl, - absolute: (config.iconUrl.indexOf("http") === 0) || plyr.browser.isIE - }; - } - - // Build the default HTML - function _buildControls() { - // Create html array - var html = [], - iconUrl = _getIconUrl(), - iconPath = (!iconUrl.absolute ? iconUrl.url : '') + '#' + config.iconPrefix; - - // Larger overlaid play button - if (_inArray(config.controls, 'play-large')) { - html.push( - '', - '', - '' + config.i18n.play + '', - '' - ); - } - - html.push(''); - - // Restart button - if (_inArray(config.controls, 'restart')) { - html.push( - '', - '', - '' + config.i18n.restart + '', - '' - ); - } - - // Rewind button - if (_inArray(config.controls, 'rewind')) { - html.push( - '', - '', - '' + config.i18n.rewind + '', - '' - ); - } - - // Play Pause button - // TODO: This should be a toggle button really? - if (_inArray(config.controls, 'play')) { - html.push( - '', - '', - '' + config.i18n.play + '', - '', - '', - '', - '' + config.i18n.pause + '', - '' - ); - } - - // Fast forward button - if (_inArray(config.controls, 'fast-forward')) { - html.push( - '', - '', - '' + config.i18n.forward + '', - '' - ); - } - - // Progress - if (_inArray(config.controls, 'progress')) { - // Create progress - html.push('', - 'Seek', - '', - '', - '', - '0% ' + config.i18n.buffered, - ''); - - // Seek tooltip - if (config.tooltips.seek) { - html.push('00:00'); - } - - // Close - html.push(''); - } - - // Media current time display - if (_inArray(config.controls, 'current-time')) { - html.push( - '', - '' + config.i18n.currentTime + '', - '00:00', - '' - ); - } - - // Media duration display - if (_inArray(config.controls, 'duration')) { - html.push( - '', - '' + config.i18n.duration + '', - '00:00', - '' - ); - } - - // Toggle mute button - if (_inArray(config.controls, 'mute')) { - html.push( - '', - '', - '', - '' + config.i18n.toggleMute + '', - '' - ); - } - - // Volume range control - if (_inArray(config.controls, 'volume')) { - html.push( - '', - '' + config.i18n.volume + '', - '', - '', - '' - ); - } - - // Toggle captions button - if (_inArray(config.controls, 'captions')) { - html.push( - '', - '', - '', - '' + config.i18n.toggleCaptions + '', - '' - ); - } - - // Toggle fullscreen button - if (_inArray(config.controls, 'fullscreen')) { - html.push( - '', - '', - '', - '' + config.i18n.toggleFullscreen + '', - '' - ); - } - - // Close everything - html.push(''); - - return html.join(''); - } - - // Setup fullscreen - function _setupFullscreen() { - if (!plyr.supported.full) { - return; - } - - if ((plyr.type !== 'audio' || config.fullscreen.allowAudio) && config.fullscreen.enabled) { - // Check for native support - var nativeSupport = fullscreen.supportsFullScreen; - - if (nativeSupport || (config.fullscreen.fallback && !_inFrame())) { - _log((nativeSupport ? 'Native' : 'Fallback') + ' fullscreen enabled'); - - // Add styling hook - _toggleClass(plyr.container, config.classes.fullscreen.enabled, true); - } else { - _log('Fullscreen not supported and fallback disabled'); - } - - // Toggle state - if (plyr.buttons && plyr.buttons.fullscreen) { - _toggleState(plyr.buttons.fullscreen, false); - } - - // Setup focus trap - _focusTrap(); - } - } - - // Setup captions - function _setupCaptions() { - // Bail if not HTML5 video - if (plyr.type !== 'video') { - return; - } - - // Inject the container - if (!_getElement(config.selectors.captions)) { - plyr.videoContainer.insertAdjacentHTML('afterbegin', ''); - } - - // Determine if HTML5 textTracks is supported - plyr.usingTextTracks = false; - if (plyr.media.textTracks) { - plyr.usingTextTracks = true; - } - - // Get URL of caption file if exists - var captionSrc = '', - kind, - children = plyr.media.childNodes; - - for (var i = 0; i < children.length; i++) { - if (children[i].nodeName.toLowerCase() === 'track') { - kind = children[i].kind; - if (kind === 'captions' || kind === 'subtitles') { - captionSrc = children[i].getAttribute('src'); - } - } - } - - // Record if caption file exists or not - plyr.captionExists = true; - if (captionSrc === '') { - plyr.captionExists = false; - _log('No caption track found'); - } else { - _log('Caption track found; URI: ' + captionSrc); - } - - // If no caption file exists, hide container for caption text - if (!plyr.captionExists) { - _toggleClass(plyr.container, config.classes.captions.enabled); - } else { - // Turn off native caption rendering to avoid double captions - // This doesn't seem to work in Safari 7+, so the elements are removed from the dom below - var tracks = plyr.media.textTracks; - for (var x = 0; x < tracks.length; x++) { - tracks[x].mode = 'hidden'; - } - - // Enable UI - _showCaptions(plyr); - - // Disable unsupported browsers than report false positive - // Firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1033144 - if ((plyr.browser.isIE && plyr.browser.version >= 10) || - (plyr.browser.isFirefox && plyr.browser.version >= 31)) { - - // Debugging - _log('Detected browser with known TextTrack issues - using manual fallback'); - - // Set to false so skips to 'manual' captioning - plyr.usingTextTracks = false; - } - - // Rendering caption tracks - // Native support required - http://caniuse.com/webvtt - if (plyr.usingTextTracks) { - _log('TextTracks supported'); - - for (var y = 0; y < tracks.length; y++) { - var track = tracks[y]; - - if (track.kind === 'captions' || track.kind === 'subtitles') { - _on(track, 'cuechange', function() { - // Display a cue, if there is one - if (this.activeCues[0] && 'text' in this.activeCues[0]) { - _setCaption(this.activeCues[0].getCueAsHTML()); - } else { - _setCaption(); - } - }); - } - } - } else { - // Caption tracks not natively supported - _log('TextTracks not supported so rendering captions manually'); - - // Render captions from array at appropriate time - plyr.currentCaption = ''; - plyr.captions = []; - - if (captionSrc !== '') { - // Create XMLHttpRequest Object - var xhr = new XMLHttpRequest(); - - xhr.onreadystatechange = function() { - if (xhr.readyState === 4) { - if (xhr.status === 200) { - var captions = [], - caption, - req = xhr.responseText; - - //According to webvtt spec, line terminator consists of one of the following - // CRLF (U+000D U+000A), LF (U+000A) or CR (U+000D) - var lineSeparator = '\r\n'; - if(req.indexOf(lineSeparator+lineSeparator) === -1) { - if(req.indexOf('\r\r') !== -1){ - lineSeparator = '\r'; - } else { - lineSeparator = '\n'; - } - } - - captions = req.split(lineSeparator+lineSeparator); - - for (var r = 0; r < captions.length; r++) { - caption = captions[r]; - plyr.captions[r] = []; - - // Get the parts of the captions - var parts = caption.split(lineSeparator), - index = 0; - - // Incase caption numbers are added - if (parts[index].indexOf(":") === -1) { - index = 1; - } - - plyr.captions[r] = [parts[index], parts[index + 1]]; - } - - // Remove first element ('VTT') - plyr.captions.shift(); - - _log('Successfully loaded the caption file via AJAX'); - } else { - _warn(config.logPrefix + 'There was a problem loading the caption file via AJAX'); - } - } - }; - - xhr.open('get', captionSrc, true); - - xhr.send(); - } - } - } - } - - // Set the current caption - function _setCaption(caption) { - /* jshint unused:false */ - var container = _getElement(config.selectors.captions), - content = document.createElement('span'); - - // Empty the container - container.innerHTML = ''; - - // Default to empty - if (_is.undefined(caption)) { - caption = ''; - } - - // Set the span content - if (_is.string(caption)) { - content.innerHTML = caption.trim(); - } else { - content.appendChild(caption); - } - - // Set new caption text - container.appendChild(content); - - // Force redraw (for Safari) - var redraw = container.offsetHeight; - } - - // Captions functions - // Seek the manual caption time and update UI - function _seekManualCaptions(time) { - // Utilities for caption time codes - function _timecodeCommon(tc, pos) { - var tcpair = []; - tcpair = tc.split(' --> '); - for(var i = 0; i < tcpair.length; i++) { - // WebVTT allows for extra meta data after the timestamp line - // So get rid of this if it exists - tcpair[i] = tcpair[i].replace(/(\d+:\d+:\d+\.\d+).*/, "$1"); - } - return _subTcSecs(tcpair[pos]); - } - function _timecodeMin(tc) { - return _timecodeCommon(tc, 0); - } - function _timecodeMax(tc) { - return _timecodeCommon(tc, 1); - } - function _subTcSecs(tc) { - if (tc === null || tc === undefined) { - return 0; - } else { - var tc1 = [], - tc2 = [], - seconds; - tc1 = tc.split(','); - tc2 = tc1[0].split(':'); - seconds = Math.floor(tc2[0]*60*60) + Math.floor(tc2[1]*60) + Math.floor(tc2[2]); - return seconds; - } - } - - // If it's not video, or we're using textTracks, bail. - if (plyr.usingTextTracks || plyr.type !== 'video' || !plyr.supported.full) { - return; - } - - // Reset subcount - plyr.subcount = 0; - - // Check time is a number, if not use currentTime - // IE has a bug where currentTime doesn't go to 0 - // https://twitter.com/Sam_Potts/status/573715746506731521 - time = _is.number(time) ? time : plyr.media.currentTime; - - // If there's no subs available, bail - if (!plyr.captions[plyr.subcount]) { - return; - } - - while (_timecodeMax(plyr.captions[plyr.subcount][0]) < time.toFixed(1)) { - plyr.subcount++; - if (plyr.subcount > plyr.captions.length - 1) { - plyr.subcount = plyr.captions.length - 1; - break; - } - } - - // Check if the next caption is in the current time range - if (plyr.media.currentTime.toFixed(1) >= _timecodeMin(plyr.captions[plyr.subcount][0]) && - plyr.media.currentTime.toFixed(1) <= _timecodeMax(plyr.captions[plyr.subcount][0])) { - plyr.currentCaption = plyr.captions[plyr.subcount][1]; - - // Render the caption - _setCaption(plyr.currentCaption); - } else { - _setCaption(); - } - } - - // Display captions container and button (for initialization) - function _showCaptions() { - // If there's no caption toggle, bail - if (!plyr.buttons.captions) { - return; - } - - _toggleClass(plyr.container, config.classes.captions.enabled, true); - - // Try to load the value from storage - var active = plyr.storage.captionsEnabled; - - // Otherwise fall back to the default config - if (!_is.boolean(active)) { - active = config.captions.defaultActive; - } - - if (active) { - _toggleClass(plyr.container, config.classes.captions.active, true); - _toggleState(plyr.buttons.captions, true); - } - } - - // Find all elements - function _getElements(selector) { - return plyr.container.querySelectorAll(selector); - } - - // Find a single element - function _getElement(selector) { - return _getElements(selector)[0]; - } - - // Determine if we're in an iframe - function _inFrame() { - try { - return window.self !== window.top; - } - catch (e) { - return true; - } - } - - // Trap focus inside container - function _focusTrap() { - var tabbables = _getElements('input:not([disabled]), button:not([disabled])'), - first = tabbables[0], - last = tabbables[tabbables.length - 1]; - - function _checkFocus(event) { - // If it is TAB - if (event.which === 9 && plyr.isFullscreen) { - if (event.target === last && !event.shiftKey) { - // Move focus to first element that can be tabbed if Shift isn't used - event.preventDefault(); - first.focus(); - } else if (event.target === first && event.shiftKey) { - // Move focus to last element that can be tabbed if Shift is used - event.preventDefault(); - last.focus(); - } - } - } - - // Bind the handler - _on(plyr.container, 'keydown', _checkFocus); - } - - // Add elements to HTML5 media (source, tracks, etc) - function _insertChildElements(type, attributes) { - if (_is.string(attributes)) { - _insertElement(type, plyr.media, { src: attributes }); - } else if (attributes.constructor === Array) { - for (var i = attributes.length - 1; i >= 0; i--) { - _insertElement(type, plyr.media, attributes[i]); - } - } - } - - // Insert controls - function _injectControls() { - // Sprite - if (config.loadSprite) { - var iconUrl = _getIconUrl(); - - // Only load external sprite using AJAX - if (iconUrl.absolute) { - _log('AJAX loading absolute SVG sprite' + (plyr.browser.isIE ? ' (due to IE)' : '')); - loadSprite(iconUrl.url, "sprite-plyr"); - } else { - _log('Sprite will be used as external resource directly'); - } - } - - // Make a copy of the html - var html = config.html; - - // Insert custom video controls - _log('Injecting custom controls'); - - // If no controls are specified, create default - if (!html) { - html = _buildControls(); - } - - // Replace seek time instances - html = _replaceAll(html, '{seektime}', config.seekTime); - - // Replace all id references with random numbers - html = _replaceAll(html, '{id}', Math.floor(Math.random() * (10000))); - - // Controls container - var target; - - // Inject to custom location - if (_is.string(config.selectors.controls.container)) { - target = document.querySelector(config.selectors.controls.container); - } - - // Inject into the container by default - if (!_is.htmlElement(target)) { - target = plyr.container - } - - // Inject controls HTML - target.insertAdjacentHTML('beforeend', html); - - // Setup tooltips - if (config.tooltips.controls) { - var labels = _getElements([config.selectors.controls.wrapper, ' ', config.selectors.labels, ' .', config.classes.hidden].join('')); - - for (var i = labels.length - 1; i >= 0; i--) { - var label = labels[i]; - - _toggleClass(label, config.classes.hidden, false); - _toggleClass(label, config.classes.tooltip, true); - } - } - } - - // Find the UI controls and store references - function _findElements() { - try { - plyr.controls = _getElement(config.selectors.controls.wrapper); - - // Buttons - plyr.buttons = {}; - plyr.buttons.seek = _getElement(config.selectors.buttons.seek); - plyr.buttons.play = _getElements(config.selectors.buttons.play); - plyr.buttons.pause = _getElement(config.selectors.buttons.pause); - plyr.buttons.restart = _getElement(config.selectors.buttons.restart); - plyr.buttons.rewind = _getElement(config.selectors.buttons.rewind); - plyr.buttons.forward = _getElement(config.selectors.buttons.forward); - plyr.buttons.fullscreen = _getElement(config.selectors.buttons.fullscreen); - - // Inputs - plyr.buttons.mute = _getElement(config.selectors.buttons.mute); - plyr.buttons.captions = _getElement(config.selectors.buttons.captions); - - // Progress - plyr.progress = {}; - plyr.progress.container = _getElement(config.selectors.progress.container); - - // Progress - Buffering - plyr.progress.buffer = {}; - plyr.progress.buffer.bar = _getElement(config.selectors.progress.buffer); - plyr.progress.buffer.text = plyr.progress.buffer.bar && plyr.progress.buffer.bar.getElementsByTagName('span')[0]; - - // Progress - Played - plyr.progress.played = _getElement(config.selectors.progress.played); - - // Seek tooltip - plyr.progress.tooltip = plyr.progress.container && plyr.progress.container.querySelector('.' + config.classes.tooltip); - - // Volume - plyr.volume = {}; - plyr.volume.input = _getElement(config.selectors.volume.input); - plyr.volume.display = _getElement(config.selectors.volume.display); - - // Timing - plyr.duration = _getElement(config.selectors.duration); - plyr.currentTime = _getElement(config.selectors.currentTime); - plyr.seekTime = _getElements(config.selectors.seekTime); - - return true; - } - catch(e) { - _warn('It looks like there is a problem with your controls HTML'); - - // Restore native video controls - _toggleNativeControls(true); - - return false; - } - } - - // Toggle style hook - function _toggleStyleHook() { - _toggleClass(plyr.container, config.selectors.container.replace('.', ''), plyr.supported.full); - } - - // Toggle native controls - function _toggleNativeControls(toggle) { - if (toggle && _inArray(config.types.html5, plyr.type)) { - plyr.media.setAttribute('controls', ''); - } else { - plyr.media.removeAttribute('controls'); - } - } - - // Setup aria attribute for play and iframe title - function _setTitle(iframe) { - // Find the current text - var label = config.i18n.play; - - // If there's a media title set, use that for the label - if (_is.string(config.title) && config.title.length) { - label += ', ' + config.title; - - // Set container label - plyr.container.setAttribute('aria-label', config.title); - } - - // If there's a play button, set label - if (plyr.supported.full && plyr.buttons.play) { - for (var i = plyr.buttons.play.length - 1; i >= 0; i--) { - plyr.buttons.play[i].setAttribute('aria-label', label); - } - } - - // Set iframe title - // https://github.com/Selz/plyr/issues/124 - if (_is.htmlElement(iframe)) { - iframe.setAttribute('title', config.i18n.frameTitle.replace('{title}', config.title)); - } - } - - // Setup localStorage - function _setupStorage() { - var value = null; - plyr.storage = {}; - - // Bail if we don't have localStorage support or it's disabled - if (!_storage.supported || !config.storage.enabled) { - return; - } - - // Clean up old volume - // https://github.com/Selz/plyr/issues/171 - window.localStorage.removeItem('plyr-volume'); - - // load value from the current key - value = window.localStorage.getItem(config.storage.key); - - if (!value) { - // Key wasn't set (or had been cleared), move along - return; - } else if (/^\d+(\.\d+)?$/.test(value)) { - // If value is a number, it's probably volume from an older - // version of plyr. See: https://github.com/Selz/plyr/pull/313 - // Update the key to be JSON - _updateStorage({volume: parseFloat(value)}); - } else { - // Assume it's JSON from this or a later version of plyr - plyr.storage = JSON.parse(value); - } - } - - // Save a value back to local storage - function _updateStorage(value) { - // Bail if we don't have localStorage support or it's disabled - if (!_storage.supported || !config.storage.enabled) { - return; - } - - // Update the working copy of the values - _extend(plyr.storage, value); - - // Update storage - window.localStorage.setItem(config.storage.key, JSON.stringify(plyr.storage)); - } - - // Setup media - function _setupMedia() { - // If there's no media, bail - if (!plyr.media) { - _warn('No media element found!'); - return; - } - - if (plyr.supported.full) { - // Add type class - _toggleClass(plyr.container, config.classes.type.replace('{0}', plyr.type), true); - - // Add video class for embeds - // This will require changes if audio embeds are added - if (_inArray(config.types.embed, plyr.type)) { - _toggleClass(plyr.container, config.classes.type.replace('{0}', 'video'), true); - } - - // If there's no autoplay attribute, assume the video is stopped and add state class - _toggleClass(plyr.container, config.classes.stopped, config.autoplay); - - // Add iOS class - _toggleClass(plyr.container, config.classes.isIos, plyr.browser.isIos); - - // Add touch class - _toggleClass(plyr.container, config.classes.isTouch, plyr.browser.isTouch); - - // Inject the player wrapper - if (plyr.type === 'video') { - // Create the wrapper div - var wrapper = document.createElement('div'); - wrapper.setAttribute('class', config.classes.videoWrapper); - - // Wrap the video in a container - _wrap(plyr.media, wrapper); - - // Cache the container - plyr.videoContainer = wrapper; - } - } - - // Embeds - if (_inArray(config.types.embed, plyr.type)) { - _setupEmbed(); - } - } - - // Setup YouTube/Vimeo - function _setupEmbed() { - var container = document.createElement('div'), - mediaId, - id = plyr.type + '-' + Math.floor(Math.random() * (10000)); - - // Parse IDs from URLs if supplied - switch (plyr.type) { - case 'youtube': - mediaId = _parseYouTubeId(plyr.embedId); - break; - - case 'vimeo': - mediaId = _parseVimeoId(plyr.embedId); - break; - - default: - mediaId = plyr.embedId; - } - - // Remove old containers - var containers = _getElements('[id^="' + plyr.type + '-"]'); - for (var i = containers.length - 1; i >= 0; i--) { - _remove(containers[i]); - } - - // Add embed class for responsive - _toggleClass(plyr.media, config.classes.videoWrapper, true); - _toggleClass(plyr.media, config.classes.embedWrapper, true); - - if (plyr.type === 'youtube') { - // Create the YouTube container - plyr.media.appendChild(container); - - // Set ID - container.setAttribute('id', id); - - // Setup API - if (_is.object(window.YT)) { - _youTubeReady(mediaId, container); - } else { - // Load the API - _injectScript(config.urls.youtube.api); - - // Setup callback for the API - window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || []; - - // Add to queue - window.onYouTubeReadyCallbacks.push(function() { _youTubeReady(mediaId, container); }); - - // Set callback to process queue - window.onYouTubeIframeAPIReady = function () { - window.onYouTubeReadyCallbacks.forEach(function(callback) { callback(); }); - }; - } - } else if (plyr.type === 'vimeo') { - // Vimeo needs an extra div to hide controls on desktop (which has full support) - if (plyr.supported.full) { - plyr.media.appendChild(container); - } else { - container = plyr.media; - } - - // Set ID - container.setAttribute('id', id); - - // Load the API if not already - if (!_is.object(window.Vimeo)) { - _injectScript(config.urls.vimeo.api); - - // Wait for fragaloop load - var vimeoTimer = window.setInterval(function() { - if (_is.object(window.Vimeo)) { - window.clearInterval(vimeoTimer); - _vimeoReady(mediaId, container); - } - }, 50); - } else { - _vimeoReady(mediaId, container); - } - } else if (plyr.type === 'soundcloud') { - // TODO: Currently unsupported and undocumented - // Inject the iframe - var soundCloud = document.createElement('iframe'); - - // Watch for iframe load - soundCloud.loaded = false; - _on(soundCloud, 'load', function() { soundCloud.loaded = true; }); - - _setAttributes(soundCloud, { - 'src': 'https://w.soundcloud.com/player/?url=https://api.soundcloud.com/tracks/' + mediaId, - 'id': id - }); - - container.appendChild(soundCloud); - plyr.media.appendChild(container); - - // Load the API if not already - if (!window.SC) { - _injectScript(config.urls.soundcloud.api); - } - - // Wait for SC load - var soundCloudTimer = window.setInterval(function() { - if (window.SC && soundCloud.loaded) { - window.clearInterval(soundCloudTimer); - _soundcloudReady.call(soundCloud); - } - }, 50); - } - } - - // When embeds are ready - function _embedReady() { - // Setup the UI and call ready if full support - if (plyr.supported.full) { - _setupInterface(); - _ready(); - } - - // Set title - _setTitle(_getElement('iframe')); - } - - // Handle YouTube API ready - function _youTubeReady(videoId, container) { - // Setup instance - // https://developers.google.com/youtube/iframe_api_reference - plyr.embed = new window.YT.Player(container.id, { - videoId: videoId, - playerVars: { - autoplay: (config.autoplay ? 1 : 0), - controls: (plyr.supported.full ? 0 : 1), - rel: 0, - showinfo: 0, - iv_load_policy: 3, - cc_load_policy: (config.captions.defaultActive ? 1 : 0), - cc_lang_pref: 'en', - wmode: 'transparent', - modestbranding: 1, - disablekb: 1, - origin: '*' // https://code.google.com/p/gdata-issues/issues/detail?id=5788#c45 - }, - events: { - 'onError': function(event) { - _triggerEvent(plyr.container, 'error', true, { - code: event.data, - embed: event.target - }); - }, - 'onReady': function(event) { - // Get the instance - var instance = event.target; - - // Create a faux HTML5 API using the YouTube API - plyr.media.play = function() { - instance.playVideo(); - plyr.media.paused = false; - }; - plyr.media.pause = function() { - instance.pauseVideo(); - plyr.media.paused = true; - }; - plyr.media.stop = function() { - instance.stopVideo(); - plyr.media.paused = true; - }; - plyr.media.duration = instance.getDuration(); - plyr.media.paused = true; - plyr.media.currentTime = 0; - plyr.media.muted = instance.isMuted(); - - // Set title - config.title = instance.getVideoData().title; - - // Set the tabindex - if (plyr.supported.full) { - plyr.media.querySelector('iframe').setAttribute('tabindex', '-1'); - } - - // Update UI - _embedReady(); - - // Trigger timeupdate - _triggerEvent(plyr.media, 'timeupdate'); - - // Trigger timeupdate - _triggerEvent(plyr.media, 'durationchange'); - - // Reset timer - window.clearInterval(timers.buffering); - - // Setup buffering - timers.buffering = window.setInterval(function() { - // Get loaded % from YouTube - plyr.media.buffered = instance.getVideoLoadedFraction(); - - // Trigger progress only when we actually buffer something - if (plyr.media.lastBuffered === null || plyr.media.lastBuffered < plyr.media.buffered) { - _triggerEvent(plyr.media, 'progress'); - } - - // Set last buffer point - plyr.media.lastBuffered = plyr.media.buffered; - - // Bail if we're at 100% - if (plyr.media.buffered === 1) { - window.clearInterval(timers.buffering); - - // Trigger event - _triggerEvent(plyr.media, 'canplaythrough'); - } - }, 200); - }, - 'onStateChange': function(event) { - // Get the instance - var instance = event.target; - - // Reset timer - window.clearInterval(timers.playing); - - // Handle events - // -1 Unstarted - // 0 Ended - // 1 Playing - // 2 Paused - // 3 Buffering - // 5 Video cued - switch (event.data) { - case 0: - plyr.media.paused = true; - _triggerEvent(plyr.media, 'ended'); - break; - - case 1: - plyr.media.paused = false; - - // If we were seeking, fire seeked event - if (plyr.media.seeking) { - _triggerEvent(plyr.media, 'seeked'); - } - - plyr.media.seeking = false; - _triggerEvent(plyr.media, 'play'); - _triggerEvent(plyr.media, 'playing'); - - // Poll to get playback progress - timers.playing = window.setInterval(function() { - // Set the current time - plyr.media.currentTime = instance.getCurrentTime(); - - // Trigger timeupdate - _triggerEvent(plyr.media, 'timeupdate'); - }, 100); - - // Check duration again due to YouTube bug - // https://github.com/Selz/plyr/issues/374 - // https://code.google.com/p/gdata-issues/issues/detail?id=8690 - if (plyr.media.duration !== instance.getDuration()) { - plyr.media.duration = instance.getDuration(); - _triggerEvent(plyr.media, 'durationchange'); - } - - break; - - case 2: - plyr.media.paused = true; - _triggerEvent(plyr.media, 'pause'); - break; - } - - _triggerEvent(plyr.container, 'statechange', false, { - code: event.data - }); - } - } - }); - } - - // Vimeo ready - function _vimeoReady(mediaId, container) { - // Setup instance - // https://github.com/vimeo/player.js - plyr.embed = new window.Vimeo.Player(container, { - id: parseInt(mediaId), - loop: config.loop, - autoplay: config.autoplay, - byline: false, - portrait: false, - title: false - }); - - // Create a faux HTML5 API using the Vimeo API - plyr.media.play = function() { - plyr.embed.play(); - plyr.media.paused = false; - }; - plyr.media.pause = function() { - plyr.embed.pause(); - plyr.media.paused = true; - }; - plyr.media.stop = function() { - plyr.embed.stop(); - plyr.media.paused = true; - }; - - plyr.media.paused = true; - plyr.media.currentTime = 0; - - // Update UI - _embedReady(); - - plyr.embed.getCurrentTime().then(function(value) { - plyr.media.currentTime = value; - - // Trigger timeupdate - _triggerEvent(plyr.media, 'timeupdate'); - }); - - plyr.embed.getDuration().then(function(value) { - plyr.media.duration = value; - - // Trigger timeupdate - _triggerEvent(plyr.media, 'durationchange'); - }); - - // TODO: Captions - /*if (config.captions.defaultActive) { - plyr.embed.enableTextTrack('en'); - }*/ - - plyr.embed.on('loaded', function() { - // Fix keyboard focus issues - // https://github.com/Selz/plyr/issues/317 - if (_is.htmlElement(plyr.embed.element) && plyr.supported.full) { - plyr.embed.element.setAttribute('tabindex', '-1'); - } - }); - - plyr.embed.on('play', function() { - plyr.media.paused = false; - _triggerEvent(plyr.media, 'play'); - _triggerEvent(plyr.media, 'playing'); - }); - - plyr.embed.on('pause', function() { - plyr.media.paused = true; - _triggerEvent(plyr.media, 'pause'); - }); - - plyr.embed.on('timeupdate', function(data) { - plyr.media.seeking = false; - plyr.media.currentTime = data.seconds; - _triggerEvent(plyr.media, 'timeupdate'); - }); - - plyr.embed.on('progress', function(data) { - plyr.media.buffered = data.percent; - _triggerEvent(plyr.media, 'progress'); - - if (parseInt(data.percent) === 1) { - // Trigger event - _triggerEvent(plyr.media, 'canplaythrough'); - } - }); - - plyr.embed.on('seeked', function() { - plyr.media.seeking = false; - _triggerEvent(plyr.media, 'seeked'); - _triggerEvent(plyr.media, 'play'); - }); - - plyr.embed.on('ended', function() { - plyr.media.paused = true; - _triggerEvent(plyr.media, 'ended'); - }); - } - - // Soundcloud ready - function _soundcloudReady() { - /* jshint validthis: true */ - plyr.embed = window.SC.Widget(this); - - // Setup on ready - plyr.embed.bind(window.SC.Widget.Events.READY, function() { - // Create a faux HTML5 API using the Soundcloud API - plyr.media.play = function() { - plyr.embed.play(); - plyr.media.paused = false; - }; - plyr.media.pause = function() { - plyr.embed.pause(); - plyr.media.paused = true; - }; - plyr.media.stop = function() { - plyr.embed.seekTo(0); - plyr.embed.pause(); - plyr.media.paused = true; - }; - - plyr.media.paused = true; - plyr.media.currentTime = 0; - - plyr.embed.getDuration(function(value) { - plyr.media.duration = value/1000; - - // Update UI - _embedReady(); - }); - - plyr.embed.getPosition(function(value) { - plyr.media.currentTime = value; - - // Trigger timeupdate - _triggerEvent(plyr.media, 'timeupdate'); - }); - - plyr.embed.bind(window.SC.Widget.Events.PLAY, function() { - plyr.media.paused = false; - _triggerEvent(plyr.media, 'play'); - _triggerEvent(plyr.media, 'playing'); - }); - - plyr.embed.bind(window.SC.Widget.Events.PAUSE, function() { - plyr.media.paused = true; - _triggerEvent(plyr.media, 'pause'); - }); - - plyr.embed.bind(window.SC.Widget.Events.PLAY_PROGRESS, function(data) { - plyr.media.seeking = false; - plyr.media.currentTime = data.currentPosition/1000; - _triggerEvent(plyr.media, 'timeupdate'); - }); - - plyr.embed.bind(window.SC.Widget.Events.LOAD_PROGRESS, function(data) { - plyr.media.buffered = data.loadProgress; - _triggerEvent(plyr.media, 'progress'); - - if (parseInt(data.loadProgress) === 1) { - // Trigger event - _triggerEvent(plyr.media, 'canplaythrough'); - } - }); - - plyr.embed.bind(window.SC.Widget.Events.FINISH, function() { - plyr.media.paused = true; - _triggerEvent(plyr.media, 'ended'); - }); - }); - } - - // Play media - function _play() { - if ('play' in plyr.media) { - plyr.media.play(); - } - } - - // Pause media - function _pause() { - if ('pause' in plyr.media) { - plyr.media.pause(); - } - } - - // Toggle playback - function _togglePlay(toggle) { - // True toggle - if (!_is.boolean(toggle)) { - toggle = plyr.media.paused; - } - - if (toggle) { - _play(); - } else { - _pause(); - } - - return toggle; - } - - // Rewind - function _rewind(seekTime) { - // Use default if needed - if (!_is.number(seekTime)) { - seekTime = config.seekTime; - } - _seek(plyr.media.currentTime - seekTime); - } - - // Fast forward - function _forward(seekTime) { - // Use default if needed - if (!_is.number(seekTime)) { - seekTime = config.seekTime; - } - _seek(plyr.media.currentTime + seekTime); - } - - // Seek to time - // The input parameter can be an event or a number - function _seek(input) { - var targetTime = 0, - paused = plyr.media.paused, - duration = _getDuration(); - - if (_is.number(input)) { - targetTime = input; - } else if (_is.object(input) && _inArray(['input', 'change'], input.type)) { - // It's the seek slider - // Seek to the selected time - targetTime = ((input.target.value / input.target.max) * duration); - } - - // Normalise targetTime - if (targetTime < 0) { - targetTime = 0; - } else if (targetTime > duration) { - targetTime = duration; - } - - // Update seek range and progress - _updateSeekDisplay(targetTime); - - // Set the current time - // Try/catch incase the media isn't set and we're calling seek() from source() and IE moans - try { - plyr.media.currentTime = targetTime.toFixed(4); - } - catch(e) {} - - // Embeds - if (_inArray(config.types.embed, plyr.type)) { - switch(plyr.type) { - case 'youtube': - plyr.embed.seekTo(targetTime); - break; - - case 'vimeo': - // Round to nearest second for vimeo - plyr.embed.setCurrentTime(targetTime.toFixed(0)); - break; - - case 'soundcloud': - plyr.embed.seekTo(targetTime * 1000); - break; - } - - if (paused) { - _pause(); - } - - // Trigger timeupdate - _triggerEvent(plyr.media, 'timeupdate'); - - // Set seeking flag - plyr.media.seeking = true; - - // Trigger seeking - _triggerEvent(plyr.media, 'seeking'); - } - - // Logging - _log('Seeking to ' + plyr.media.currentTime + ' seconds'); - - // Special handling for 'manual' captions - _seekManualCaptions(targetTime); - } - - // Get the duration (or custom if set) - function _getDuration() { - // It should be a number, but parse it just incase - var duration = parseInt(config.duration), - - // True duration - mediaDuration = 0; - - // Only if duration available - if (plyr.media.duration !== null && !isNaN(plyr.media.duration)) { - mediaDuration = plyr.media.duration; - } - - // If custom duration is funky, use regular duration - return (isNaN(duration) ? mediaDuration : duration); - } - - // Check playing state - function _checkPlaying() { - _toggleClass(plyr.container, config.classes.playing, !plyr.media.paused); - - _toggleClass(plyr.container, config.classes.stopped, plyr.media.paused); - - _toggleControls(plyr.media.paused); - } - - // Save scroll position - function _saveScrollPosition() { - scroll = { - x: window.pageXOffset || 0, - y: window.pageYOffset || 0 - }; - } - - // Restore scroll position - function _restoreScrollPosition() { - window.scrollTo(scroll.x, scroll.y); - } - - // Toggle fullscreen - function _toggleFullscreen(event) { - // Check for native support - var nativeSupport = fullscreen.supportsFullScreen; - - if (nativeSupport) { - // If it's a fullscreen change event, update the UI - if (event && event.type === fullscreen.fullScreenEventName) { - plyr.isFullscreen = fullscreen.isFullScreen(plyr.container); - } else { - // Else it's a user request to enter or exit - if (!fullscreen.isFullScreen(plyr.container)) { - // Save scroll position - _saveScrollPosition(); - - // Request full screen - fullscreen.requestFullScreen(plyr.container); - } else { - // Bail from fullscreen - fullscreen.cancelFullScreen(); - } - - // Check if we're actually full screen (it could fail) - plyr.isFullscreen = fullscreen.isFullScreen(plyr.container); - - return; - } - } else { - // Otherwise, it's a simple toggle - plyr.isFullscreen = !plyr.isFullscreen; - - // Bind/unbind escape key - document.body.style.overflow = plyr.isFullscreen ? 'hidden' : ''; - } - - // Set class hook - _toggleClass(plyr.container, config.classes.fullscreen.active, plyr.isFullscreen); - - // Trap focus - _focusTrap(plyr.isFullscreen); - - // Set button state - if (plyr.buttons && plyr.buttons.fullscreen) { - _toggleState(plyr.buttons.fullscreen, plyr.isFullscreen); - } - - // Trigger an event - _triggerEvent(plyr.container, plyr.isFullscreen ? 'enterfullscreen' : 'exitfullscreen', true); - - // Restore scroll position - if (!plyr.isFullscreen && nativeSupport) { - _restoreScrollPosition(); - } - } - - // Mute - function _toggleMute(muted) { - // If the method is called without parameter, toggle based on current value - if (!_is.boolean(muted)) { - muted = !plyr.media.muted; - } - - // Set button state - _toggleState(plyr.buttons.mute, muted); - - // Set mute on the player - plyr.media.muted = muted; - - // If volume is 0 after unmuting, set to default - if (plyr.media.volume === 0) { - _setVolume(config.volume); - } - - // Embeds - if (_inArray(config.types.embed, plyr.type)) { - // YouTube - switch(plyr.type) { - case 'youtube': - plyr.embed[plyr.media.muted ? 'mute' : 'unMute'](); - break; - - case 'vimeo': - case 'soundcloud': - plyr.embed.setVolume(plyr.media.muted ? 0 : parseFloat(config.volume / config.volumeMax)); - break; - } - - // Trigger volumechange for embeds - _triggerEvent(plyr.media, 'volumechange'); - } - } - - // Set volume - function _setVolume(volume) { - var max = config.volumeMax, - min = config.volumeMin; - - // Load volume from storage if no value specified - if (_is.undefined(volume)) { - volume = plyr.storage.volume; - } - - // Use config if all else fails - if (volume === null || isNaN(volume)) { - volume = config.volume; - } - - // Maximum is volumeMax - if (volume > max) { - volume = max; - } - // Minimum is volumeMin - if (volume < min) { - volume = min; - } - - // Set the player volume - plyr.media.volume = parseFloat(volume / max); - - // Set the display - if (plyr.volume.display) { - plyr.volume.display.value = volume; - } - - // Embeds - if (_inArray(config.types.embed, plyr.type)) { - switch(plyr.type) { - case 'youtube': - plyr.embed.setVolume(plyr.media.volume * 100); - break; - - case 'vimeo': - case 'soundcloud': - plyr.embed.setVolume(plyr.media.volume); - break; - } - - // Trigger volumechange for embeds - _triggerEvent(plyr.media, 'volumechange'); - } - - // Toggle muted state - if (volume === 0) { - plyr.media.muted = true; - } else if (plyr.media.muted && volume > 0) { - _toggleMute(); - } - } - - // Increase volume - function _increaseVolume(step) { - var volume = plyr.media.muted ? 0 : (plyr.media.volume * config.volumeMax); - - if (!_is.number(step)) { - step = config.volumeStep; - } - - _setVolume(volume + step); - } - - // Decrease volume - function _decreaseVolume(step) { - var volume = plyr.media.muted ? 0 : (plyr.media.volume * config.volumeMax); - - if (!_is.number(step)) { - step = config.volumeStep; - } - - _setVolume(volume - step); - } - - // Update volume UI and storage - function _updateVolume() { - // Get the current volume - var volume = plyr.media.muted ? 0 : (plyr.media.volume * config.volumeMax); - - // Update the if present - if (plyr.supported.full) { - if (plyr.volume.input) { - plyr.volume.input.value = volume; - } - if (plyr.volume.display) { - plyr.volume.display.value = volume; - } - } - - // Update the volume in storage - _updateStorage({volume: volume}); - - // Toggle class if muted - _toggleClass(plyr.container, config.classes.muted, (volume === 0)); - - // Update checkbox for mute state - if (plyr.supported.full && plyr.buttons.mute) { - _toggleState(plyr.buttons.mute, (volume === 0)); - } - } - - // Toggle captions - function _toggleCaptions(show) { - // If there's no full support, or there's no caption toggle - if (!plyr.supported.full || !plyr.buttons.captions) { - return; - } - - // If the method is called without parameter, toggle based on current value - if (!_is.boolean(show)) { - show = (plyr.container.className.indexOf(config.classes.captions.active) === -1); - } - - // Set global - plyr.captionsEnabled = show; - - // Toggle state - _toggleState(plyr.buttons.captions, plyr.captionsEnabled); - - // Add class hook - _toggleClass(plyr.container, config.classes.captions.active, plyr.captionsEnabled); - - // Trigger an event - _triggerEvent(plyr.container, plyr.captionsEnabled ? 'captionsenabled' : 'captionsdisabled', true); - - // Save captions state to localStorage - _updateStorage({captionsEnabled: plyr.captionsEnabled}); - } - - // Check if media is loading - function _checkLoading(event) { - var loading = (event.type === 'waiting'); - - // Clear timer - clearTimeout(timers.loading); - - // Timer to prevent flicker when seeking - timers.loading = setTimeout(function() { - // Toggle container class hook - _toggleClass(plyr.container, config.classes.loading, loading); - - // Show controls if loading, hide if done - _toggleControls(loading); - }, (loading ? 250 : 0)); - } - - // Update elements - function _updateProgress(event) { - if (!plyr.supported.full) { - return; - } - - var progress = plyr.progress.played, - value = 0, - duration = _getDuration(); - - if (event) { - switch (event.type) { - // Video playing - case 'timeupdate': - case 'seeking': - if (plyr.controls.pressed) { - return; - } - - value = _getPercentage(plyr.media.currentTime, duration); - - // Set seek range value only if it's a 'natural' time event - if (event.type === 'timeupdate' && plyr.buttons.seek) { - plyr.buttons.seek.value = value; - } - - break; - - // Check buffer status - case 'playing': - case 'progress': - progress = plyr.progress.buffer; - value = (function() { - var buffered = plyr.media.buffered; - - if (buffered && buffered.length) { - // HTML5 - return _getPercentage(buffered.end(0), duration); - } else if (_is.number(buffered)) { - // YouTube returns between 0 and 1 - return (buffered * 100); - } - - return 0; - })(); - - break; - } - } - - // Set values - _setProgress(progress, value); - } - - // Set value - function _setProgress(progress, value) { - if (!plyr.supported.full) { - return; - } - - // Default to 0 - if (_is.undefined(value)) { - value = 0; - } - // Default to buffer or bail - if (_is.undefined(progress)) { - if (plyr.progress && plyr.progress.buffer) { - progress = plyr.progress.buffer; - } else { - return; - } - } - - // One progress element passed - if (_is.htmlElement(progress)) { - progress.value = value; - } else if (progress) { - // Object of progress + text element - if (progress.bar) { - progress.bar.value = value; - } - if (progress.text) { - progress.text.innerHTML = value; - } - } - } - - // Update the displayed time - function _updateTimeDisplay(time, element) { - // Bail if there's no duration display - if (!element) { - return; - } - - // Fallback to 0 - if (isNaN(time)) { - time = 0; - } - - plyr.secs = parseInt(time % 60); - plyr.mins = parseInt((time / 60) % 60); - plyr.hours = parseInt(((time / 60) / 60) % 60); - - // Do we need to display hours? - var displayHours = (parseInt(((_getDuration() / 60) / 60) % 60) > 0); - - // Ensure it's two digits. For example, 03 rather than 3. - plyr.secs = ('0' + plyr.secs).slice(-2); - plyr.mins = ('0' + plyr.mins).slice(-2); - - // Render - element.innerHTML = (displayHours ? plyr.hours + ':' : '') + plyr.mins + ':' + plyr.secs; - } - - // Show the duration on metadataloaded - function _displayDuration() { - if (!plyr.supported.full) { - return; - } - - // Determine duration - var duration = _getDuration() || 0; - - // If there's only one time display, display duration there - if (!plyr.duration && config.displayDuration && plyr.media.paused) { - _updateTimeDisplay(duration, plyr.currentTime); - } - - // If there's a duration element, update content - if (plyr.duration) { - _updateTimeDisplay(duration, plyr.duration); - } - - // Update the tooltip (if visible) - _updateSeekTooltip(); - } - - // Handle time change event - function _timeUpdate(event) { - // Duration - _updateTimeDisplay(plyr.media.currentTime, plyr.currentTime); - - // Ignore updates while seeking - if (event && event.type === 'timeupdate' && plyr.media.seeking) { - return; - } - - // Playing progress - _updateProgress(event); - } - - // Update seek range and progress - function _updateSeekDisplay(time) { - // Default to 0 - if (!_is.number(time)) { - time = 0; - } - - var duration = _getDuration(), - value = _getPercentage(time, duration); - - // Update progress - if (plyr.progress && plyr.progress.played) { - plyr.progress.played.value = value; - } - - // Update seek range input - if (plyr.buttons && plyr.buttons.seek) { - plyr.buttons.seek.value = value; - } - } - - // Update hover tooltip for seeking - function _updateSeekTooltip(event) { - var duration = _getDuration(); - - // Bail if setting not true - if (!config.tooltips.seek || !plyr.progress.container || duration === 0) { - return; - } - - // Calculate percentage - var clientRect = plyr.progress.container.getBoundingClientRect(), - percent = 0, - visible = config.classes.tooltip + '--visible'; - - // Determine percentage, if already visible - if (!event) { - if (_hasClass(plyr.progress.tooltip, visible)) { - percent = plyr.progress.tooltip.style.left.replace('%', ''); - } else { - return; - } - } else { - percent = ((100 / clientRect.width) * (event.pageX - clientRect.left)); - } - - // Set bounds - if (percent < 0) { - percent = 0; - } else if (percent > 100) { - percent = 100; - } - - // Display the time a click would seek to - _updateTimeDisplay(((duration / 100) * percent), plyr.progress.tooltip); - - // Set position - plyr.progress.tooltip.style.left = percent + "%"; - - // Show/hide the tooltip - // If the event is a moues in/out and percentage is inside bounds - if (event && _inArray(['mouseenter', 'mouseleave'], event.type)) { - _toggleClass(plyr.progress.tooltip, visible, (event.type === 'mouseenter')); - } - } - - // Show the player controls in fullscreen mode - function _toggleControls(toggle) { - // Don't hide if config says not to, it's audio, or not ready or loading - if (!config.hideControls || plyr.type === 'audio') { - return; - } - - var delay = 0, - isEnterFullscreen = false, - show = toggle, - loading = _hasClass(plyr.container, config.classes.loading); - - // Default to false if no boolean - if (!_is.boolean(toggle)) { - if (toggle && toggle.type) { - // Is the enter fullscreen event - isEnterFullscreen = (toggle.type === 'enterfullscreen'); - - // Whether to show controls - show = _inArray(['mousemove', 'touchstart', 'mouseenter', 'focus'], toggle.type); - - // Delay hiding on move events - if (_inArray(['mousemove', 'touchmove'], toggle.type)) { - delay = 20000; - } - - // Delay a little more for keyboard users - if (toggle.type === 'focus') { - delay = 3000; - } - } else { - show = _hasClass(plyr.container, config.classes.hideControls); - } - } - - // Clear timer every movement - window.clearTimeout(timers.hover); - - // If the mouse is not over the controls, set a timeout to hide them - if (show || plyr.media.paused || loading) { - _toggleClass(plyr.container, config.classes.hideControls, false); - - // Always show controls when paused or if touch - if (plyr.media.paused || loading) { - return; - } - - // Delay for hiding on touch - if (plyr.browser.isTouch) { - delay = 3000; - } - } - - // If toggle is false or if we're playing (regardless of toggle), - // then set the timer to hide the controls - if (!show || !plyr.media.paused) { - timers.hover = window.setTimeout(function() { - // If the mouse is over the controls (and not entering fullscreen), bail - if ((plyr.controls.pressed || plyr.controls.hover) && !isEnterFullscreen) { - return; - } - - _toggleClass(plyr.container, config.classes.hideControls, true); - }, delay); - } - } - - // Add common function to retrieve media source - function _source(source) { - // If not null or undefined, parse it - if (!_is.undefined(source)) { - _updateSource(source); - return; - } - - // Return the current source - var url; - switch(plyr.type) { - case 'youtube': - url = plyr.embed.getVideoUrl(); - break; - - case 'vimeo': - plyr.embed.getVideoUrl.then(function (value) { - url = value; - }); - break; - - case 'soundcloud': - plyr.embed.getCurrentSound(function(object) { - url = object.permalink_url; - }); - break; - - default: - url = plyr.media.currentSrc; - break; - } - - return url || ''; - } - - // Update source - // Sources are not checked for support so be careful - function _updateSource(source) { - if (!_is.object(source) || !('sources' in source) || !source.sources.length) { - _warn('Invalid source format'); - return; - } - - // Remove ready class hook - _toggleClass(plyr.container, config.classes.ready, false); - - // Pause playback - _pause(); - - // Update seek range and progress - _updateSeekDisplay(); - - // Reset buffer progress - _setProgress(); - - // Cancel current network requests - _cancelRequests(); - - // Setup new source - function setup() { - // Remove embed object - plyr.embed = null; - - // Remove the old media - _remove(plyr.media); - - // Remove video container - if (plyr.type === 'video' && plyr.videoContainer) { - _remove(plyr.videoContainer); - } - - // Reset class name - if (plyr.container) { - plyr.container.removeAttribute('class'); - } - - // Set the type - if ('type' in source) { - plyr.type = source.type; - - // Get child type for video (it might be an embed) - if (plyr.type === 'video') { - var firstSource = source.sources[0]; - - if ('type' in firstSource && _inArray(config.types.embed, firstSource.type)) { - plyr.type = firstSource.type; - } - } - } - - // Check for support - plyr.supported = supported(plyr.type); - - // Create new markup - switch(plyr.type) { - case 'video': - plyr.media = document.createElement('video'); - break; - - case 'audio': - plyr.media = document.createElement('audio'); - break; - - case 'youtube': - case 'vimeo': - case 'soundcloud': - plyr.media = document.createElement('div'); - plyr.embedId = source.sources[0].src; - break; - } - - // Inject the new element - _prependChild(plyr.container, plyr.media); - - // Autoplay the new source? - if (_is.boolean(source.autoplay)) { - config.autoplay = source.autoplay; - } - - // Set attributes for audio and video - if (_inArray(config.types.html5, plyr.type)) { - if (config.crossorigin) { - plyr.media.setAttribute('crossorigin', ''); - } - if (config.autoplay) { - plyr.media.setAttribute('autoplay', ''); - } - if ('poster' in source) { - plyr.media.setAttribute('poster', source.poster); - } - if (config.loop) { - plyr.media.setAttribute('loop', ''); - } - } - - // Restore class hooks - _toggleClass(plyr.container, config.classes.fullscreen.active, plyr.isFullscreen); - _toggleClass(plyr.container, config.classes.captions.active, plyr.captionsEnabled); - _toggleStyleHook(); - - // Set new sources for html5 - if (_inArray(config.types.html5, plyr.type)) { - _insertChildElements('source', source.sources); - } - - // Set up from scratch - _setupMedia(); - - // HTML5 stuff - if (_inArray(config.types.html5, plyr.type)) { - // Setup captions - if ('tracks' in source) { - _insertChildElements('track', source.tracks); - } - - // Load HTML5 sources - plyr.media.load(); - } - - // If HTML5 or embed but not fully supported, setupInterface and call ready now - if (_inArray(config.types.html5, plyr.type) || (_inArray(config.types.embed, plyr.type) && !plyr.supported.full)) { - // Setup interface - _setupInterface(); - - // Call ready - _ready(); - } - - // Set aria title and iframe title - config.title = source.title; - _setTitle(); - } - - // Destroy instance adn wait for callback - // Vimeo throws a wobbly if you don't wait - _destroy(setup, false); - } - - // Update poster - function _updatePoster(source) { - if (plyr.type === 'video') { - plyr.media.setAttribute('poster', source); - } - } - - // Listen for control events - function _controlListeners() { - // IE doesn't support input event, so we fallback to change - var inputEvent = (plyr.browser.isIE ? 'change' : 'input'); - - // Click play/pause helper - function togglePlay() { - var play = _togglePlay(); - - // Determine which buttons - var trigger = plyr.buttons[play ? 'play' : 'pause'], - target = plyr.buttons[play ? 'pause' : 'play']; - - // Get the last play button to account for the large play button - if (target && target.length > 1) { - target = target[target.length - 1]; - } else { - target = target[0]; - } - - // Setup focus and tab focus - if (target) { - var hadTabFocus = _hasClass(trigger, config.classes.tabFocus); - - setTimeout(function() { - target.focus(); - - if (hadTabFocus) { - _toggleClass(trigger, config.classes.tabFocus, false); - _toggleClass(target, config.classes.tabFocus, true); - } - }, 100); - } - } - - // Get the focused element - function getFocusElement() { - var focused = document.activeElement; - - if (!focused || focused === document.body) { - focused = null; - } else { - focused = document.querySelector(':focus'); - } - - return focused; - } - - // Get the key code for an event - function getKeyCode(event) { - return event.keyCode ? event.keyCode : event.which; - } - - // Detect tab focus - function checkTabFocus(focused) { - for (var button in plyr.buttons) { - var element = plyr.buttons[button]; - - if (_is.nodeList(element)) { - for (var i = 0; i < element.length; i++) { - _toggleClass(element[i], config.classes.tabFocus, (element[i] === focused)); - } - } else { - _toggleClass(element, config.classes.tabFocus, (element === focused)); - } - } - } - - // Keyboard shortcuts - if (config.keyboardShorcuts.focused) { - var last = null; - - // Handle global presses - if (config.keyboardShorcuts.global) { - _on(window, 'keydown keyup', function(event) { - var code = getKeyCode(event), - focused = getFocusElement(), - allowed = [48,49,50,51,52,53,54,56,57,75,77,70,67], - count = get().length; - - // Only handle global key press if there's only one player - // and the key is in the allowed keys - // and if the focused element is not editable (e.g. text input) - // and any that accept key input http://webaim.org/techniques/keyboard/ - if (count === 1 && _inArray(allowed, code) && (!_is.htmlElement(focused) || !_matches(focused, config.selectors.editable))) { - handleKey(event); - } - }); - } - - // Handle presses on focused - _on(plyr.container, 'keydown keyup', handleKey); - } - - function handleKey(event) { - var code = getKeyCode(event), - pressed = event.type === 'keydown', - held = pressed && code === last; - - // If the event is bubbled from the media element - // Firefox doesn't get the keycode for whatever reason - if (!_is.number(code)) { - return; - } - - // Seek by the number keys - function seekByKey() { - // Get current duration - var duration = plyr.media.duration; - - // Bail if we have no duration set - if (!_is.number(duration)) { - return; - } - - // Divide the max duration into 10th's and times by the number value - _seek((duration / 10) * (code - 48)); - } - - // Handle the key on keydown - // Reset on keyup - if (pressed) { - // Which keycodes should we prevent default - var preventDefault = [48,49,50,51,52,53,54,56,57,32,75,38,40,77,39,37,70,67]; - - // If the code is found prevent default (e.g. prevent scrolling for arrows) - if (_inArray(preventDefault, code)) { - event.preventDefault(); - event.stopPropagation(); - } - - switch(code) { - // 0-9 - case 48: - case 49: - case 50: - case 51: - case 52: - case 53: - case 54: - case 55: - case 56: - case 57: if (!held) { seekByKey(); } break; - // Space and K key - case 32: - case 75: if (!held) { _togglePlay(); } break; - // Arrow up - case 38: _increaseVolume(); break; - // Arrow down - case 40: _decreaseVolume(); break; - // M key - case 77: if (!held) { _toggleMute() } break; - // Arrow forward - case 39: _forward(); break; - // Arrow back - case 37: _rewind(); break; - // F key - case 70: _toggleFullscreen(); break; - // C key - case 67: if (!held) { _toggleCaptions(); } break; - } - - // Escape is handle natively when in full screen - // So we only need to worry about non native - if (!fullscreen.supportsFullScreen && plyr.isFullscreen && code === 27) { - _toggleFullscreen(); - } - - // Store last code for next cycle - last = code; - } else { - last = null; - } - } - - // Focus/tab management - _on(window, 'keyup', function(event) { - var code = getKeyCode(event), - focused = getFocusElement(); - - if (code === 9) { - checkTabFocus(focused); - } - }); - _on(document.body, 'click', function() { - _toggleClass(_getElement('.' + config.classes.tabFocus), config.classes.tabFocus, false); - }); - for (var button in plyr.buttons) { - var element = plyr.buttons[button]; - - _on(element, 'blur', function() { - _toggleClass(element, 'tab-focus', false); - }); - } - - // Play - _proxyListener(plyr.buttons.play, 'click', config.listeners.play, togglePlay); - - // Pause - _proxyListener(plyr.buttons.pause, 'click', config.listeners.pause, togglePlay); - - // Restart - _proxyListener(plyr.buttons.restart, 'click', config.listeners.restart, _seek); - - // Rewind - _proxyListener(plyr.buttons.rewind, 'click', config.listeners.rewind, _rewind); - - // Fast forward - _proxyListener(plyr.buttons.forward, 'click', config.listeners.forward, _forward); - - // Seek - _proxyListener(plyr.buttons.seek, inputEvent, config.listeners.seek, _seek); - - // Set volume - _proxyListener(plyr.volume.input, inputEvent, config.listeners.volume, function() { - _setVolume(plyr.volume.input.value); - }); - - // Mute - _proxyListener(plyr.buttons.mute, 'click', config.listeners.mute, _toggleMute); - - // Fullscreen - _proxyListener(plyr.buttons.fullscreen, 'click', config.listeners.fullscreen, _toggleFullscreen); - - // Handle user exiting fullscreen by escaping etc - if (fullscreen.supportsFullScreen) { - _on(document, fullscreen.fullScreenEventName, _toggleFullscreen); - } - - // Captions - _on(plyr.buttons.captions, 'click', _toggleCaptions); - - // Seek tooltip - _on(plyr.progress.container, 'mouseenter mouseleave mousemove', _updateSeekTooltip); - - // Toggle controls visibility based on mouse movement - if (config.hideControls) { - // Toggle controls on mouse events and entering fullscreen - _on(plyr.container, 'mouseenter mouseleave mousemove touchstart touchend touchcancel touchmove enterfullscreen', _toggleControls); - - // Watch for cursor over controls so they don't hide when trying to interact - _on(plyr.controls, 'mouseenter mouseleave', function(event) { - plyr.controls.hover = event.type === 'mouseenter'; - }); - - // Watch for cursor over controls so they don't hide when trying to interact - _on(plyr.controls, 'mousedown mouseup touchstart touchend touchcancel', function(event) { - plyr.controls.pressed = _inArray(['mousedown', 'touchstart'], event.type); - }); - - // Focus in/out on controls - _on(plyr.controls, 'focus blur', _toggleControls, true); - } - - // Adjust volume on scroll - _on(plyr.volume.input, 'wheel', function(event) { - event.preventDefault(); - - // Detect "natural" scroll - suppored on OS X Safari only - // Other browsers on OS X will be inverted until support improves - var inverted = event.webkitDirectionInvertedFromDevice, - step = (config.volumeStep / 5); - - // Scroll down (or up on natural) to decrease - if (event.deltaY < 0 || event.deltaX > 0) { - if (inverted) { - _decreaseVolume(step); - } else { - _increaseVolume(step); - } - } - - // Scroll up (or down on natural) to increase - if (event.deltaY > 0 || event.deltaX < 0) { - if (inverted) { - _increaseVolume(step); - } else { - _decreaseVolume(step); - } - } - }); - } - - // Listen for media events - function _mediaListeners() { - // Time change on media - _on(plyr.media, 'timeupdate seeking', _timeUpdate); - - // Update manual captions - _on(plyr.media, 'timeupdate', _seekManualCaptions); - - // Display duration - _on(plyr.media, 'durationchange loadedmetadata', _displayDuration); - - // Handle the media finishing - _on(plyr.media, 'ended', function() { - // Show poster on end - if (plyr.type === 'video' && config.showPosterOnEnd) { - // Clear - if (plyr.type === 'video') { - _setCaption(); - } - - // Restart - _seek(); - - // Re-load media - plyr.media.load(); - } - }); - - // Check for buffer progress - _on(plyr.media, 'progress playing', _updateProgress); - - // Handle native mute - _on(plyr.media, 'volumechange', _updateVolume); - - // Handle native play/pause - _on(plyr.media, 'play pause ended', _checkPlaying); - - // Loading - _on(plyr.media, 'waiting canplay seeked', _checkLoading); - - // Click video - if (config.clickToPlay && plyr.type !== 'audio') { - // Re-fetch the wrapper - var wrapper = _getElement('.' + config.classes.videoWrapper); - - // Bail if there's no wrapper (this should never happen) - if (!wrapper) { - return; - } - - // Set cursor - wrapper.style.cursor = "pointer"; - - // On click play, pause ore restart - _on(wrapper, 'click', function() { - // Touch devices will just show controls (if we're hiding controls) - if (config.hideControls && plyr.browser.isTouch && !plyr.media.paused) { - return; - } - - if (plyr.media.paused) { - _play(); - } else if (plyr.media.ended) { - _seek(); - _play(); - } else { - _pause(); - } - }); - } - - // Disable right click - - // Proxy events to container - // Bubble up key events for Edge - _on(plyr.media, config.events.concat(['keyup', 'keydown']).join(' '), function(event) { - _triggerEvent(plyr.container, event.type, true); - }); - } - - // Cancel current network requests - // See https://github.com/Selz/plyr/issues/174 - function _cancelRequests() { - if (!_inArray(config.types.html5, plyr.type)) { - return; - } - - // Remove child sources - var sources = plyr.media.querySelectorAll('source'); - for (var i = 0; i < sources.length; i++) { - _remove(sources[i]); - } - - // Set blank video src attribute - // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error - // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection - plyr.media.setAttribute('src', 'https://cdn.selz.com/plyr/blank.mp4'); - - // Load the new empty source - // This will cancel existing requests - // See https://github.com/Selz/plyr/issues/174 - plyr.media.load(); - - // Debugging - _log('Cancelled network requests'); - } - - // Destroy an instance - // Event listeners are removed when elements are removed - // http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory - function _destroy(callback, restore) { - // Bail if the element is not initialized - if (!plyr.init) { - return null; - } - - // Type specific stuff - switch (plyr.type) { - case 'youtube': - // Clear timers - window.clearInterval(timers.buffering); - window.clearInterval(timers.playing); - - // Destroy YouTube API - plyr.embed.destroy(); - - // Clean up - cleanUp(); - - break; - - case 'vimeo': - // Destroy Vimeo API - // then clean up (wait, to prevent postmessage errors) - plyr.embed.unload().then(cleanUp); - - // Vimeo does not always return - timers.cleanUp = window.setTimeout(cleanUp, 200); - - break; - - case 'video': - case 'audio': - // Restore native video controls - _toggleNativeControls(true); - - // Clean up - cleanUp(); - - break; - } - - function cleanUp() { - clearTimeout(timers.cleanUp); - - // Default to restore original element - if (!_is.boolean(restore)) { - restore = true; - } - - // Callback - if (_is.function(callback)) { - callback.call(original); - } - - // Bail if we don't need to restore the original element - if (!restore) { - return; - } - - // Remove init flag - plyr.init = false; - - // Replace the container with the original element provided - plyr.container.parentNode.replaceChild(original, plyr.container); - - // Allow overflow (set on fullscreen) - document.body.style.overflow = ''; - - // Event - _triggerEvent(original, 'destroyed', true); - } - } - - // Setup a player - function _init() { - // Bail if the element is initialized - if (plyr.init) { - return null; - } - - // Setup the fullscreen api - fullscreen = _fullscreen(); - - // Sniff out the browser - plyr.browser = _browserSniff(); - - // Bail if nothing to setup - if (!_is.htmlElement(plyr.media)) { - return; - } - - // Load saved settings from localStorage - _setupStorage(); - - // Set media type based on tag or data attribute - // Supported: video, audio, vimeo, youtube - var tagName = media.tagName.toLowerCase(); - if (tagName === 'div') { - plyr.type = media.getAttribute('data-type'); - plyr.embedId = media.getAttribute('data-video-id'); - - // Clean up - media.removeAttribute('data-type'); - media.removeAttribute('data-video-id'); - } else { - plyr.type = tagName; - config.crossorigin = (media.getAttribute('crossorigin') !== null); - config.autoplay = (config.autoplay || (media.getAttribute('autoplay') !== null)); - config.loop = (config.loop || (media.getAttribute('loop') !== null)); - } - - // Check for support - plyr.supported = supported(plyr.type); - - // If no native support, bail - if (!plyr.supported.basic) { - return; - } - - // Wrap media - plyr.container = _wrap(media, document.createElement('div')); - - // Allow focus to be captured - plyr.container.setAttribute('tabindex', 0); - - // Add style hook - _toggleStyleHook(); - - // Debug info - _log('' + plyr.browser.name + ' ' + plyr.browser.version); - - // Setup media - _setupMedia(); - - // Setup interface - // If embed but not fully supported, setupInterface (to avoid flash of controls) and call ready now - if (_inArray(config.types.html5, plyr.type) || (_inArray(config.types.embed, plyr.type) && !plyr.supported.full)) { - // Setup UI - _setupInterface(); - - // Call ready - _ready(); - - // Set title on button and frame - _setTitle(); - } - - // Successful setup - plyr.init = true; - } - - // Setup the UI - function _setupInterface() { - // Don't setup interface if no support - if (!plyr.supported.full) { - _warn('Basic support only', plyr.type); - - // Remove controls - _remove(_getElement(config.selectors.controls.wrapper)); - - // Remove large play - _remove(_getElement(config.selectors.buttons.play)); - - // Restore native controls - _toggleNativeControls(true); - - // Bail - return; - } - - // Inject custom controls if not present - var controlsMissing = !_getElements(config.selectors.controls.wrapper).length; - if (controlsMissing) { - // Inject custom controls - _injectControls(); - } - - // Find the elements - if (!_findElements()) { - return; - } - - // If the controls are injected, re-bind listeners for controls - if (controlsMissing) { - _controlListeners(); - } - - // Media element listeners - _mediaListeners(); - - // Remove native controls - _toggleNativeControls(); - - // Setup fullscreen - _setupFullscreen(); - - // Captions - _setupCaptions(); - - // Set volume - _setVolume(); - _updateVolume(); - - // Reset time display - _timeUpdate(); - - // Update the UI - _checkPlaying(); - } - - api = { - getOriginal: function() { return original; }, - getContainer: function() { return plyr.container }, - getEmbed: function() { return plyr.embed; }, - getMedia: function() { return plyr.media; }, - getType: function() { return plyr.type; }, - getDuration: _getDuration, - getCurrentTime: function() { return plyr.media.currentTime; }, - getVolume: function() { return plyr.media.volume; }, - isMuted: function() { return plyr.media.muted; }, - isReady: function() { return _hasClass(plyr.container, config.classes.ready); }, - isLoading: function() { return _hasClass(plyr.container, config.classes.loading); }, - isPaused: function() { return plyr.media.paused; }, - on: function(event, callback) { _on(plyr.container, event, callback); return this; }, - play: _play, - pause: _pause, - stop: function() { _pause(); _seek(); }, - restart: _seek, - rewind: _rewind, - forward: _forward, - seek: _seek, - source: _source, - poster: _updatePoster, - setVolume: _setVolume, - togglePlay: _togglePlay, - toggleMute: _toggleMute, - toggleCaptions: _toggleCaptions, - toggleFullscreen: _toggleFullscreen, - toggleControls: _toggleControls, - isFullscreen: function() { return plyr.isFullscreen || false; }, - support: function(mimeType) { return _supportMime(plyr, mimeType); }, - destroy: _destroy - }; - - // Everything done - function _ready() { - // Ready event at end of execution stack - window.setTimeout(function() { - _triggerEvent(plyr.media, 'ready'); - }, 0); - - // Set class hook on media element - _toggleClass(plyr.media, defaults.classes.setup, true); - - // Set container class for ready - _toggleClass(plyr.container, config.classes.ready, true); - - // Store a refernce to instance - plyr.media.plyr = api; - - // Autoplay - if (config.autoplay) { - _play(); - } - } - - // Initialize instance - _init(); - - // If init failed, return null - if (!plyr.init) { - return null; - } - - return api; - } - - // Load a sprite - function loadSprite(url, id) { - var x = new XMLHttpRequest(); - - // If the id is set and sprite exists, bail - if (_is.string(id) && _is.htmlElement(document.querySelector('#' + id))) { - return; - } - - // Create placeholder (to prevent loading twice) - var container = document.createElement('div'); - container.setAttribute('hidden', ''); - if (_is.string(id)) { - container.setAttribute('id', id); - } - document.body.insertBefore(container, document.body.childNodes[0]); - - // Check for CORS support - if ('withCredentials' in x) { - x.open('GET', url, true); - } else { - return; - } - - // Inject hidden div with sprite on load - x.onload = function() { - container.innerHTML = x.responseText; - } - - x.send(); - } - - // Check for support - function supported(type) { - var browser = _browserSniff(), - isOldIE = (browser.isIE && browser.version <= 9), - isIos = browser.isIos, - isIphone = browser.isIphone, - audioSupport = !!document.createElement('audio').canPlayType, - videoSupport = !!document.createElement('video').canPlayType, - basic = false, - full = false; - - switch (type) { - case 'video': - basic = videoSupport; - full = (basic && (!isOldIE && !isIphone)); - break; - - case 'audio': - basic = audioSupport; - full = (basic && !isOldIE); - break; - - // Vimeo does not seem to be supported on iOS via API - // Issue raised https://github.com/vimeo/player.js/issues/87 - case 'vimeo': - basic = true; - full = (!isOldIE && !isIos); - break; - - case 'youtube': - basic = true; - full = (!isOldIE && !isIos); - - // YouTube seems to work on iOS 10+ on iPad - if (isIos && !isIphone && browser.version >= 10) { - full = true; - } - - break; - - case 'soundcloud': - basic = true; - full = (!isOldIE && !isIphone); - break; - - default: - basic = (audioSupport && videoSupport); - full = (basic && !isOldIE); - } - - return { - basic: basic, - full: full - }; - } - - // Setup function - function setup(targets, options) { - // Get the players - var players = [], - instances = [], - selector = [defaults.selectors.html5, defaults.selectors.embed].join(','); - - // Select the elements - if (_is.string(targets)) { - // String selector passed - targets = document.querySelectorAll(targets); - } else if (_is.htmlElement(targets)) { - // Single HTMLElement passed - targets = [targets]; - } else if (!_is.nodeList(targets) && !_is.array(targets) && !_is.string(targets)) { - // No selector passed, possibly options as first argument - // If options are the first argument - if (_is.undefined(options) && _is.object(targets)) { - options = targets; - } - - // Use default selector - targets = document.querySelectorAll(selector); - } - - // Convert NodeList to array - if (_is.nodeList(targets)) { - targets = Array.prototype.slice.call(targets); - } - - // Bail if disabled or no basic support - // You may want to disable certain UAs etc - if (!supported().basic || !targets.length) { - return false; - } - - // Add to container list - function add(target, media) { - if (!_hasClass(media, defaults.classes.hook)) { - players.push({ - // Always wrap in a for styling - //container: _wrap(media, document.createElement('div')), - // Could be a container or the media itself - target: target, - // This should be the , or (YouTube/Vimeo) - media: media - }); - } - } - - // Check if the targets have multiple media elements - for (var i = 0; i < targets.length; i++) { - var target = targets[i]; - - // Get children - var children = target.querySelectorAll(selector); - - // If there's more than one media element child, wrap them - if (children.length) { - for (var x = 0; x < children.length; x++) { - add(target, children[x]); - } - } else if (_matches(target, selector)) { - // Target is media element - add(target, target); - } - } - - // Create a player instance for each element - players.forEach(function(player) { - var element = player.target, - media = player.media, - match = false; - - // The target element can also be the media element - if (media === element) { - match = true; - } - - // Setup a player instance and add to the element - // Create instance-specific config - var data = {}; - - // Try parsing data attribute config - try { data = JSON.parse(element.getAttribute('data-plyr')); } - catch(e) { } - - var config = _extend({}, defaults, options, data); - - // Bail if not enabled - if (!config.enabled) { - return null; - } - - // Create new instance - var instance = new Plyr(media, config); - - // Go to next if setup failed - if (!_is.object(instance)) { - return; - } - - // Listen for events if debugging - if (config.debug) { - var events = config.events.concat(['setup', 'statechange', 'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled']); - - _on(instance.getContainer(), events.join(' '), function(event) { - console.log([config.logPrefix, 'event:', event.type].join(' '), event.detail.plyr); - }); - } - - // Callback - _event(instance.getContainer(), 'setup', true, { - plyr: instance - }); - - // Add to return array even if it's already setup - instances.push(instance); - }); - - return instances; - } - - // Get all instances within a provided container - function get(container) { - if (_is.string(container)) { - // Get selector if string passed - container = document.querySelector(container); - } else if (_is.undefined(container)) { - // Use body by default to get all on page - container = document.body; - } - - // If we have a HTML element - if (_is.htmlElement(container)) { - var elements = container.querySelectorAll('.' + defaults.classes.setup), - instances = []; - - Array.prototype.slice.call(elements).forEach(function(element) { - if (_is.object(element.plyr)) { - instances.push(element.plyr); - } - }); - - return instances; - } - - return []; - } - - return { - setup: setup, - supported: supported, - loadSprite: loadSprite, - get: get - }; -})); - -// Custom event polyfill -// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent -(function () { - if (typeof window.CustomEvent === 'function') { - return; - } - - function CustomEvent(event, params) { - params = params || { bubbles: false, cancelable: false, detail: undefined }; - var evt = document.createEvent('CustomEvent'); - evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); - return evt; - } - - CustomEvent.prototype = window.Event.prototype; - - window.CustomEvent = CustomEvent; -})(); diff --git a/public/s/js/theme.js b/public/s/js/theme.js index e785d7c..ff6681d 100644 --- a/public/s/js/theme.js +++ b/public/s/js/theme.js @@ -20,9 +20,8 @@ const speaker = () => { const k = document.querySelector("body"); if(localStorage.selectedTheme && localStorage.selectedTheme === "f0ck95") k.document.createElement("div"); - else { + else return; - } }; var customCss; diff --git a/src/inc/lib.mjs b/src/inc/lib.mjs index 99bb06d..898c7e8 100644 --- a/src/inc/lib.mjs +++ b/src/inc/lib.mjs @@ -2,4 +2,7 @@ export default new class { formatSize(size, i = ~~(Math.log(size) / Math.log(1024))) { return (size / Math.pow(1024, i)).toFixed(2) * 1 + " " + ["B", "kB", "MB", "GB", "TB"][i]; } + calcSpeed(b, s) { + return `${(Math.round((b * 8 / s / 1e6) * 1e4) / 1e4).toFixed(2)} Mbit/s`; + } }; diff --git a/src/inc/routes/api.mjs b/src/inc/routes/api.mjs index e12e3af..e9f4b74 100644 --- a/src/inc/routes/api.mjs +++ b/src/inc/routes/api.mjs @@ -84,23 +84,15 @@ router.get(/^\/api\/p\/([0-9]+)/, async (req, res) => { // legacy router.get(/^\/api\/item\/[0-9]+$/, async (req, res) => { try { const rows = await sql.query(queries.item, Array(3).fill(req.url.split[2])); - const data = rows[0].length > 0 ? { - ...rows[0][0], ...{ - thumb: `${cfg.main.url}/t/${rows[0][0].id}.png`, - srchost: parse(rows[0][0].src).hostname, - next: rows[1].length ? rows[1][0].id : null, - prev: rows[2].length ? rows[2][0].id : null, - } - } : { - error: true - }; - res - .writeHead(200, { "Content-Type": "application/json" }) - .end(JSON.stringify(data), "utf-8"); + res.reply({ + type: "application/json", + body: JSON.stringify(rows?.shift() || []) + }); } catch(err) { - res - .writeHead(500) - .end(JSON.stringify(err), "utf-8"); + res.reply({ + code: 500, + body: JSON.stringify(err) + }); } }); @@ -109,13 +101,14 @@ router.get(/^\/api\/user\/.*(\/[0-9]+)?$/, async (req, res) => { // auf qs umste const eps = Math.min(req.url.split[3] || 50, 50); try { const rows = await sql.query(queries.user, [ user, eps ]); - res - .writeHead(200, { "Content-Type": "application/json" }) - .end(JSON.stringify(rows.length > 0 ? rows : []), "utf-8"); + res.reply({ + type: "application/json", + body: JSON.stringify(rows.length > 0 ? rows : []) + }); } catch(err) { - res - .writeHead(500) - .end(JSON.stringify(err), "utf-8"); + res.reply({ + code: 500, + body: JSON.stringify(err) + }); } - db.end(); }); diff --git a/src/inc/routes/inc/api.mjs b/src/inc/routes/inc/api.mjs index 295e171..485132a 100644 --- a/src/inc/routes/inc/api.mjs +++ b/src/inc/routes/inc/api.mjs @@ -9,9 +9,10 @@ export const queries = { main: "select id, mime, size, username, userchannel, usernetwork, stamp, dest, src from items ", where: where => `${where?`where ${where}`:""} order by rand() limit 1` }, - item: "select id, mime, dest, size, src, stamp, userchannel, username, usernetwork from items where id = ? limit 1;" - + "select id from items where id = (select min(id) from items where id > ?);" - + "select id from items where id = (select max(id) from items where id < ?)", + item: "select id, mime, dest, size, src, stamp, userchannel, username, usernetwork, " + + "(select id from items where id = (select min(id) from items where id > ?)) as next, " + + "(select id from items where id = (select max(id) from items where id < ?)) as prev " + + "from items where items.id = ? limit 1", p: (trend, order) => `select id, mime from items where id ${trend} ? order by id ${order} limit ?`, user: "select id, mime, size, src, stamp, userchannel, username, usernetwork from items where username = ? limit ?" }; diff --git a/src/inc/tpl.mjs b/src/inc/tpl.mjs index b35314e..446429b 100644 --- a/src/inc/tpl.mjs +++ b/src/inc/tpl.mjs @@ -10,7 +10,7 @@ export default new class { [ "elseif", t => `}else if(${t.slice(6).trim()}){` ], [ "else", () => "}else{" ], [ "/if", () => "}" ], - [ "include", (t, data) => `html+='${this.render(t.slice(7).trim(), data)}';` ], //`html+=util.include("${t.slice(7).trim()}", data);`], // parse them aswell + [ "include", (t, data) => `html+='${this.render(t.slice(7).trim(), data)}';` ], [ "=", t => `html+=${t.slice(1).trim()};` ] ]; readdir(dir, root = dir, rel = dir.replace(`${root}/`, "")) { diff --git a/src/inc/trigger/f0ck.mjs b/src/inc/trigger/f0ck.mjs index dbd17ad..ac469c4 100644 --- a/src/inc/trigger/f0ck.mjs +++ b/src/inc/trigger/f0ck.mjs @@ -35,7 +35,7 @@ export default async bot => { e.reply(`${tmp.length}, ${rows.length}, ${dir.length}`); break; default: - return e.reply("lul"); + return; } } }] diff --git a/src/inc/trigger/parser.mjs b/src/inc/trigger/parser.mjs index 0adde0a..fc00b0b 100644 --- a/src/inc/trigger/parser.mjs +++ b/src/inc/trigger/parser.mjs @@ -1,5 +1,6 @@ import cfg from "../../../config.json"; import sql from "../sql.mjs"; +import lib from "../lib.mjs"; import fs from "fs"; import { exec as _exec } from "child_process"; @@ -8,6 +9,10 @@ const exec = promisify(_exec); const regex = /https?:\/\/[\w\S(\.|:|/)]+/gi; +console.log( + lib.calcSpeed(123456, 56432) +); + export default async bot => { return [{ @@ -40,9 +45,11 @@ export default async bot => { const filename = `${uuid}.${meta.ext}`; // download data - const source = (await exec(`youtube-dl "${link}" --max-filesize 100m -o ./tmp/${filename}`)).stdout.trim(); + const start = new Date(); + const source = (await exec(`youtube-dl "${link}" --max-filesize 10000m -o ./tmp/${filename}`)).stdout.trim(); if(source.match(/larger than/)) return e.reply("too large lol"); + const end = ~~((new Date() - start) / 1e3); // generate checksum const checksum = (await exec(`sha256sum ./tmp/${filename}`)).stdout.trim().split(" ")[0]; @@ -81,8 +88,8 @@ export default async bot => { e.reply([ `title: ${meta.fulltitle}`, - `name: ${filename}`, - `size: ${size}`, + `size: ${lib.formatSize(size)}`, + `speed: ${lib.calcSpeed(size, end)}`, `link: ${cfg.main.url}/${insertq.insertId}` ]); diff --git a/views/item.html b/views/item.html index 8083f1a..4fa1d1b 100644 --- a/views/item.html +++ b/views/item.html @@ -38,13 +38,11 @@ - {{=item.id}} by {{=user.name}} + {{=item.id}} by {{=user.name}} {{=user.network}} / {{=user.channel}} - {{=item.src.short}} + {{=item.src.short}} {{=item.size}} - - +