| | 417 | |
| | 418 | /* Normalizes differences between Flash and HTML5 internal players' event responses. */ |
| | 419 | utils.translateEventResponse = function(type, eventProperties) { |
| | 420 | var translated = utils.extend({}, eventProperties); |
| | 421 | if (type == jwplayer.events.JWPLAYER_FULLSCREEN && !translated.fullscreen) { |
| | 422 | translated.fullscreen = translated.message == "true" ? true : false; |
| | 423 | delete translated.message; |
| | 424 | } else if (typeof translated.data == "object") { |
| | 425 | // Takes ViewEvent "data" block and moves it up a level |
| | 426 | translated = utils.extend(translated, translated.data); |
| | 427 | delete translated.data; |
| | 428 | } else if (typeof translated.metadata == "object") { |
| | 429 | utils.deepReplaceKeyName(translated.metadata, ["__dot__","__spc__","__dsh__"], ["."," ","-"]); |
| | 430 | } |
| | 431 | |
| | 432 | var rounders = ["position", "duration", "offset"]; |
| | 433 | for (var rounder in rounders) { |
| | 434 | if (translated[rounders[rounder]]) { |
| | 435 | translated[rounders[rounder]] = Math.round(translated[rounders[rounder]] * 1000) / 1000; |
| | 436 | } |
| | 437 | } |
| | 438 | |
| | 439 | return translated; |
| | 440 | } |
| | 441 | |
| | 442 | /** |
| | 443 | * Detects whether or not the current player has flash capabilities |
| | 444 | * TODO: Add minimum flash version constraint: 9.0.115 |
| | 445 | */ |
| | 446 | utils.hasFlash = function() { |
| | 447 | if (typeof navigator.plugins != "undefined" && typeof navigator.plugins['Shockwave Flash'] != "undefined") { |
| | 448 | return true; |
| | 449 | } |
| | 450 | if (typeof WINDOW.ActiveXObject != "undefined") { |
| | 451 | try { |
| | 452 | new ActiveXObject("ShockwaveFlash.ShockwaveFlash"); |
| | 453 | return true |
| | 454 | } catch (err) { |
| | 455 | } |
| | 456 | } |
| | 457 | return false; |
| | 458 | }; |
| | 459 | |
| | 460 | |
| | 461 | /** Wraps an HTML element with another element * */ |
| | 462 | utils.wrap = function(originalElement, appendedElement) { |
| | 463 | if (originalElement.parentNode) { |
| | 464 | originalElement.parentNode.replaceChild(appendedElement, originalElement); |
| | 465 | } |
| | 466 | appendedElement.appendChild(originalElement); |
| | 467 | }; |
| | 468 | |
| | 469 | /** Finds the location of jwplayer.js and returns the path **/ |
| | 470 | utils.getScriptPath = function(scriptName) { |
| | 471 | var scripts = DOCUMENT.getElementsByTagName("script"); |
| | 472 | for (var i=0; i<scripts.length; i++) { |
| | 473 | var src = scripts[i].src; |
| | 474 | if (src && src.indexOf(scriptName) >= 0) { |
| | 475 | return src.substr(0, src.indexOf(scriptName)); |
| | 476 | } |
| | 477 | } |
| | 478 | return ""; |
| | 479 | } |
| | 480 | |
| | 481 | })(jwplayer); |
| | 482 | /** |
| | 483 | * JW Player Media Extension to Mime Type mapping |
| | 484 | * |
| | 485 | * @author zach |
| | 486 | * @version 5.4 |
| | 487 | */ |
| | 488 | (function(utils) { |
| | 489 | utils.extensionmap = { |
| | 490 | "3gp": { |
| | 491 | html5: "video/3gpp", |
| | 492 | flash: "video" |
| | 493 | }, |
| | 494 | "3gpp": { |
| | 495 | html5: "video/3gpp" |
| | 496 | }, |
| | 497 | "3g2": { |
| | 498 | html5: "video/3gpp2", |
| | 499 | flash: "video" |
| | 500 | }, |
| | 501 | "3gpp2": { |
| | 502 | html5: "video/3gpp2" |
| | 503 | }, |
| | 504 | "flv": { |
| | 505 | flash: "video" |
| | 506 | }, |
| | 507 | "f4a": { |
| | 508 | html5: "audio/mp4" |
| | 509 | }, |
| | 510 | "f4b": { |
| | 511 | html5: "audio/mp4", |
| | 512 | flash: "video" |
| | 513 | }, |
| | 514 | "f4v": { |
| | 515 | html5: "video/mp4", |
| | 516 | flash: "video" |
| | 517 | }, |
| | 518 | "mov": { |
| | 519 | html5: "video/quicktime", |
| | 520 | flash: "video" |
| | 521 | }, |
| | 522 | "m4a": { |
| | 523 | html5: "audio/mp4", |
| | 524 | flash: "video" |
| | 525 | }, |
| | 526 | "m4b": { |
| | 527 | html5: "audio/mp4" |
| | 528 | }, |
| | 529 | "m4p": { |
| | 530 | html5: "audio/mp4" |
| | 531 | }, |
| | 532 | "m4v": { |
| | 533 | html5: "video/mp4", |
| | 534 | flash: "video" |
| | 535 | }, |
| | 536 | "mp4": { |
| | 537 | html5: "video/mp4", |
| | 538 | flash: "video" |
| | 539 | }, |
| | 540 | "rbs":{ |
| | 541 | flash: "sound" |
| | 542 | }, |
| | 543 | "aac": { |
| | 544 | html5: "audio/aac", |
| | 545 | flash: "video" |
| | 546 | }, |
| | 547 | "mp3": { |
| | 548 | html5: "audio/mp3", |
| | 549 | flash: "sound" |
| | 550 | }, |
| | 551 | "ogg": { |
| | 552 | html5: "audio/ogg" |
| | 553 | }, |
| | 554 | "oga": { |
| | 555 | html5: "audio/ogg" |
| | 556 | }, |
| | 557 | "ogv": { |
| | 558 | html5: "video/ogg" |
| | 559 | }, |
| | 560 | "webm": { |
| | 561 | html5: "video/webm" |
| | 562 | }, |
| | 563 | "m3u8": { |
| | 564 | html5: "audio/x-mpegurl" |
| | 565 | }, |
| | 566 | "gif": { |
| | 567 | flash: "image" |
| | 568 | }, |
| | 569 | "jpeg": { |
| | 570 | flash: "image" |
| | 571 | }, |
| | 572 | "jpg": { |
| | 573 | flash: "image" |
| | 574 | }, |
| | 575 | "swf":{ |
| | 576 | flash: "image" |
| | 577 | }, |
| | 578 | "png":{ |
| | 579 | flash: "image" |
| | 580 | }, |
| | 581 | "wav":{ |
| | 582 | html5: "audio/x-wav" |
| | 583 | }, |
| | 584 | "rtmp":{ |
| | 585 | flash: "rtmp" |
| | 586 | }, |
| | 587 | "hls":{ |
| | 588 | flash: "hls" |
| | 589 | } |
| | 590 | }; |
| | 591 | })(jwplayer.utils); |
| | 592 | /** |
| | 593 | * Loads a <script> tag |
| | 594 | * @author zach |
| | 595 | * @modified pablo |
| | 596 | * @version 6.0 |
| | 597 | */ |
| | 598 | (function(utils) { |
| | 599 | |
| | 600 | var _loaderstatus = utils.loaderstatus = { |
| | 601 | NEW: 0, |
| | 602 | LOADING: 1, |
| | 603 | ERROR: 2, |
| | 604 | COMPLETE: 3 |
| | 605 | }, |
| | 606 | _events = jwplayer.events, |
| | 607 | DOCUMENT = document; |
| | 608 | |
| | 609 | |
| | 610 | utils.scriptloader = function(url) { |
| | 611 | var _status = _loaderstatus.NEW; |
| | 612 | var _eventDispatcher = new _events.eventdispatcher(); |
| | 613 | utils.extend(this, _eventDispatcher); |
| | 614 | |
| | 615 | this.load = function() { |
| | 616 | if (_status == _loaderstatus.NEW) { |
| | 617 | _status = _loaderstatus.LOADING; |
| | 618 | var scriptTag = DOCUMENT.createElement("script"); |
| | 619 | // Most browsers |
| | 620 | scriptTag.onload = function(evt) { |
| | 621 | _status = _loaderstatus.COMPLETE; |
| | 622 | _eventDispatcher.sendEvent(_events.COMPLETE); |
| | 623 | } |
| | 624 | scriptTag.onerror = function(evt) { |
| | 625 | _status = _loaderstatus.ERROR; |
| | 626 | _eventDispatcher.sendEvent(_events.ERROR); |
| | 627 | } |
| | 628 | // IE |
| | 629 | scriptTag.onreadystatechange = function() { |
| | 630 | if (scriptTag.readyState == 'loaded' || scriptTag.readyState == 'complete') { |
| | 631 | _status = _loaderstatus.COMPLETE; |
| | 632 | _eventDispatcher.sendEvent(_events.COMPLETE); |
| | 633 | } |
| | 634 | // Error? |
| | 635 | } |
| | 636 | DOCUMENT.getElementsByTagName("head")[0].appendChild(scriptTag); |
| | 637 | scriptTag.src = url; |
| | 638 | } |
| | 639 | |
| | 640 | }; |
| | 641 | |
| | 642 | this.getStatus = function() { |
| | 643 | return _status; |
| | 644 | } |
| | 645 | } |
| | 646 | })(jwplayer.utils); |
| | 647 | /** |
| | 648 | * Utility methods for the JW Player. |
| | 649 | * |
| | 650 | * @author pablo |
| | 651 | * @version 6.0 |
| | 652 | */ |
| | 653 | (function(jwplayer) { |
| | 654 | var DOCUMENT = document; |
| | 655 | var WINDOW = window; |
| | 656 | |
| | 657 | //Declare namespace |
| | 658 | var utils = jwplayer.utils = function() { |
| | 659 | }; |
| | 660 | |
| | 661 | /** |
| | 662 | * Returns true if the value of the object is null, undefined or the empty |
| | 663 | * string |
| | 664 | * |
| | 665 | * @param a The variable to inspect |
| | 666 | */ |
| | 667 | utils.exists = function(item) { |
| | 668 | switch (typeof (item)) { |
| | 669 | case "string": |
| | 670 | return (item.length > 0); |
| | 671 | break; |
| | 672 | case "object": |
| | 673 | return (item !== null); |
| | 674 | case "undefined": |
| | 675 | return false; |
| | 676 | } |
| | 677 | return true; |
| | 678 | } |
| | 679 | |
| | 680 | var _styleSheets={}, |
| | 681 | _styleSheet, |
| | 682 | _rules = {}; |
| | 683 | |
| | 684 | function _createStylesheet() { |
| | 685 | var styleSheet = DOCUMENT.createElement("style"); |
| | 686 | styleSheet.type = "text/css"; |
| | 687 | DOCUMENT.getElementsByTagName('head')[0].appendChild(styleSheet); |
| | 688 | return styleSheet; |
| | 689 | } |
| | 690 | |
| | 691 | utils.css = function(selector, styles, important) { |
| | 692 | if (!utils.exists(important)) important = false; |
| | 693 | |
| | 694 | if (utils.isIE()) { |
| | 695 | if (!_styleSheet) { |
| | 696 | _styleSheet = _createStylesheet(); |
| | 697 | } |
| | 698 | } else if (!_styleSheets[selector]) { |
| | 699 | _styleSheets[selector] = _createStylesheet(); |
| | 700 | } |
| | 701 | |
| | 702 | if (!_rules[selector]) { |
| | 703 | _rules[selector] = {}; |
| | 704 | } |
| | 705 | |
| | 706 | for (var style in styles) { |
| | 707 | var val = _styleValue(style, styles[style], important); |
| | 708 | if (utils.exists(_rules[selector][style]) && !utils.exists(val)) { |
| | 709 | delete _rules[selector][style]; |
| | 710 | } else { |
| | 711 | _rules[selector][style] = val; |
| | 712 | } |
| | 713 | } |
| | 714 | |
| | 715 | // IE9 limits the number of style tags in the head, so we need to update the entire stylesheet each time |
| | 716 | if (utils.isIE()) { |
| | 717 | _updateAllStyles(); |
| | 718 | } else { |
| | 719 | _updateStylesheet(selector, _styleSheets[selector]); |
| | 720 | } |
| | 721 | } |
| | 722 | |
| | 723 | function _styleValue(style, value, important) { |
| | 724 | if (typeof value === "undefined") { |
| | 725 | return undefined; |
| | 726 | } |
| | 727 | |
| | 728 | var importantString = important ? " !important" : ""; |
| | 729 | |
| | 730 | if (typeof value == "number") { |
| | 731 | if (isNaN(value)) { |
| | 732 | return undefined; |
| | 733 | } |
| | 734 | switch (style) { |
| | 735 | case "z-index": |
| | 736 | case "opacity": |
| | 737 | return value + importantString; |
| | 738 | break; |
| | 739 | default: |
| | 740 | if (style.match(/color/i)) { |
| | 741 | return "#" + utils.pad(value.toString(16), 6); |
| | 742 | } else { |
| | 743 | return Math.ceil(value) + "px" + importantString; |
| | 744 | } |
| | 745 | break; |
| | 746 | } |
| | 747 | } else { |
| | 748 | return value + importantString; |
| | 749 | } |
| | 750 | } |
| | 751 | |
| | 752 | function _updateAllStyles() { |
| | 753 | var ruleText = "\n"; |
| | 754 | for (var rule in _rules) { |
| | 755 | ruleText += _getRuleText(rule); |
| | 756 | } |
| | 757 | _styleSheet.innerHTML = ruleText; |
| | 758 | } |
| | 759 | |
| | 760 | function _updateStylesheet(selector, sheet) { |
| | 761 | if (sheet) { |
| | 762 | sheet.innerHTML = _getRuleText(selector); |
| | 763 | } |
| | 764 | } |
| | 765 | |
| | 766 | function _getRuleText(selector) { |
| | 767 | var ruleText = selector + "{\n"; |
| | 768 | var styles = _rules[selector]; |
| | 769 | for (var style in styles) { |
| | 770 | ruleText += " "+style + ": " + styles[style] + ";\n"; |
| | 771 | } |
| | 772 | ruleText += "}\n"; |
| | 773 | return ruleText; |
| | 774 | } |
| | 775 | |
| | 776 | |
| | 777 | /** |
| | 778 | * Removes all css elements which match a particular style |
| | 779 | */ |
| | 780 | utils.clearCss = function(filter) { |
| | 781 | for (var rule in _rules) { |
| | 782 | if (rule.indexOf(filter) >= 0) { |
| | 783 | delete _rules[rule]; |
| | 784 | } |
| | 785 | } |
| | 786 | for (var selector in _styleSheets) { |
| | 787 | if (selector.indexOf(filter) >= 0) { |
| | 788 | _styleSheets[selector].innerHTML = ''; |
| | 789 | } |
| | 790 | } |
| | 791 | } |
| | 792 | |
| | 793 | /** Gets an absolute file path based on a relative filepath * */ |
| | 794 | utils.getAbsolutePath = function(path, base) { |
| | 795 | if (!utils.exists(base)) { |
| | 796 | base = DOCUMENT.location.href; |
| | 797 | } |
| | 798 | if (!utils.exists(path)) { |
| | 799 | return undefined; |
| | 800 | } |
| | 801 | if (isAbsolutePath(path)) { |
| | 802 | return path; |
| | 803 | } |
| | 804 | var protocol = base.substring(0, base.indexOf("://") + 3); |
| | 805 | var domain = base.substring(protocol.length, base.indexOf('/', protocol.length + 1)); |
| | 806 | var patharray; |
| | 807 | if (path.indexOf("/") === 0) { |
| | 808 | patharray = path.split("/"); |
| | 809 | } else { |
| | 810 | var basepath = base.split("?")[0]; |
| | 811 | basepath = basepath.substring(protocol.length + domain.length + 1, basepath.lastIndexOf('/')); |
| | 812 | patharray = basepath.split("/").concat(path.split("/")); |
| | 813 | } |
| | 814 | var result = []; |
| | 815 | for ( var i = 0; i < patharray.length; i++) { |
| | 816 | if (!patharray[i] || !utils.exists(patharray[i]) || patharray[i] == ".") { |
| | 817 | continue; |
| | 818 | } else if (patharray[i] == "..") { |
| | 819 | result.pop(); |
| | 820 | } else { |
| | 821 | result.push(patharray[i]); |
| | 822 | } |
| | 823 | } |
| | 824 | return protocol + domain + "/" + result.join("/"); |
| | 825 | }; |
| | 826 | |
| | 827 | function isAbsolutePath(path) { |
| | 828 | if (!utils.exists(path)) { |
| | 829 | return; |
| | 830 | } |
| | 831 | var protocol = path.indexOf("://"); |
| | 832 | var queryparams = path.indexOf("?"); |
| | 833 | return (protocol > 0 && (queryparams < 0 || (queryparams > protocol))); |
| | 834 | } |
| | 835 | |
| | 836 | /** Merges a list of objects **/ |
| | 837 | utils.extend = function() { |
| | 838 | var args = utils.extend['arguments']; |
| | 839 | if (args.length > 1) { |
| | 840 | for ( var i = 1; i < args.length; i++) { |
| | 841 | for ( var element in args[i]) { |
| | 842 | args[0][element] = args[i][element]; |
| | 843 | } |
| | 844 | } |
| | 845 | return args[0]; |
| | 846 | } |
| | 847 | return null; |
| | 848 | }; |
| | 849 | |
| | 850 | /** |
| | 851 | * Cleans up a css dimension (e.g. '420px') and returns an integer. |
| | 852 | */ |
| | 853 | utils.parseDimension = function(dimension) { |
| | 854 | if (typeof dimension == "string") { |
| | 855 | if (dimension === "") { |
| | 856 | return 0; |
| | 857 | } else if (dimension.lastIndexOf("%") > -1) { |
| | 858 | return dimension; |
| | 859 | } else { |
| | 860 | return parseInt(dimension.replace("px", ""), 10); |
| | 861 | } |
| | 862 | } |
| | 863 | return dimension; |
| | 864 | } |
| | 865 | |
| | 866 | /** Format the elapsed / remaining text. **/ |
| | 867 | utils.timeFormat = function(sec) { |
| | 868 | if (sec > 0) { |
| | 869 | var str = Math.floor(sec / 60) < 10 ? "0" + Math.floor(sec / 60) + ":" : Math.floor(sec / 60) + ":"; |
| | 870 | str += Math.floor(sec % 60) < 10 ? "0" + Math.floor(sec % 60) : Math.floor(sec % 60); |
| | 871 | return str; |
| | 872 | } else { |
| | 873 | return "00:00"; |
| | 874 | } |
| | 875 | } |
| | 876 | |
| | 877 | /** Logger * */ |
| | 878 | utils.log = function(msg, obj) { |
| | 879 | if (typeof console != "undefined" && typeof console.log != "undefined") { |
| | 880 | if (obj) { |
| | 881 | console.log(msg, obj); |
| | 882 | } else { |
| | 883 | console.log(msg); |
| | 884 | } |
| | 885 | } |
| | 886 | }; |
| | 887 | |
| | 888 | /** Replacement for getBoundingClientRect, which isn't supported in iOS 3.1.2 **/ |
| | 889 | utils.getBoundingClientRect = function(element) { |
| | 890 | if (typeof element.getBoundingClientRect == "function") { |
| | 891 | return element.getBoundingClientRect(); |
| | 892 | } else { |
| | 893 | return { |
| | 894 | left: element.offsetLeft + DOCUMENT.body.scrollLeft, |
| | 895 | top: element.offsetTop + DOCUMENT.body.scrollTop, |
| | 896 | width: element.offsetWidth, |
| | 897 | height: element.offsetHeight |
| | 898 | }; |
| | 899 | } |
| | 900 | } |
| | 901 | |
| | 902 | var _userAgentMatch = utils.userAgentMatch = function(regex) { |
| | 903 | var agent = navigator.userAgent.toLowerCase(); |
| | 904 | return (agent.match(regex) !== null); |
| | 905 | }; |
| | 906 | |
| | 907 | utils.isIE = function() { |
| | 908 | return _userAgentMatch(/msie/i); |
| | 909 | }; |
| | 910 | |
| | 911 | /** Matches iOS and Android devices **/ |
| | 912 | utils.isMobile = function() { |
| | 913 | return _userAgentMatch(/(iP(hone|ad|od))|android/i); |
| | 914 | } |
| | 915 | |
| | 916 | /** |
| | 917 | * Detects whether the current browser is mobile Safari. |
| | 918 | */ |
| | 919 | jwplayer.utils.isIOS = function() { |
| | 920 | return _userAgentMatch(/iP(hone|ad|od)/i); |
| | 921 | }; |
| | 922 | |
| | 923 | utils.isIPod = function() { |
| | 924 | return _userAgentMatch(/iP(hone|od)/i); |
| | 925 | }; |
| | 926 | |
| | 927 | utils.isIPad = function() { |
| | 928 | return _userAgentMatch(/iPad/i); |
| | 929 | }; |
| | 930 | |
| | 931 | /** Save a setting **/ |
| | 932 | utils.saveCookie = function(name, value) { |
| | 933 | DOCUMENT.cookie = "jwplayer." + name + "=" + value + "; path=/"; |
| | 934 | } |
| | 935 | |
| | 936 | /** Retrieve saved player settings **/ |
| | 937 | utils.getCookies = function() { |
| | 938 | var jwCookies = {}; |
| | 939 | var cookies = DOCUMENT.cookie.split('; '); |
| | 940 | for (var i=0; i<cookies.length; i++) { |
| | 941 | var split = cookies[i].split('='); |
| | 942 | if (split[0].indexOf("jwplayer.") == 0) { |
| | 943 | jwCookies[split[0].substring(9, split[0].length)] = utils.serialize(split[1]); |
| | 944 | } |
| | 945 | } |
| | 946 | return jwCookies; |
| | 947 | } |
| | 948 | |
| | 949 | /** Loads an XML file into a DOM object * */ |
| | 950 | utils.ajax = function(xmldocpath, completecallback, errorcallback) { |
| | 951 | var xmlhttp; |
| | 952 | if (_isCrossdomain(xmldocpath) && utils.exists(WINDOW.XDomainRequest)) { |
| | 953 | // IE9 |
| | 954 | xmlhttp = new XDomainRequest(); |
| | 955 | xmlhttp.onload = _ajaxComplete(xmlhttp, xmldocpath, completecallback, errorcallback); |
| | 956 | xmlhttp.onerror = _ajaxError(errorcallback, xmldocpath, xmlhttp); |
| | 957 | } else if (utils.exists(WINDOW.XMLHttpRequest)) { |
| | 958 | // Firefox, Chrome, Opera, Safari |
| | 959 | xmlhttp = new XMLHttpRequest(); |
| | 960 | xmlhttp.onreadystatechange = _readyStateChangeHandler(xmlhttp, xmldocpath, completecallback, errorcallback); |
| | 961 | xmlhttp.onerror = _ajaxError(errorcallback, xmldocpath); |
| | 962 | } else { |
| | 963 | if (errorcallback) errorcallback(); |
| | 964 | } |
| | 965 | |
| | 966 | try { |
| | 967 | xmlhttp.open("GET", xmldocpath, true); |
| | 968 | xmlhttp.send(null); |
| | 969 | } catch (error) { |
| | 970 | if (errorcallback) errorcallback(xmldocpath); |
| | 971 | } |
| | 972 | return xmlhttp; |
| | 973 | }; |
| | 974 | |
| | 975 | function _isCrossdomain(path) { |
| | 976 | if (path && path.indexOf("://") >= 0) { |
| | 977 | if (path.split("/")[2] != window.location.href.split("/")[2]) |
| | 978 | return true |
| | 979 | } |
| | 980 | return false; |
| | 981 | } |
| | 982 | |
| | 983 | function _ajaxError(errorcallback, xmldocpath, xmlhttp) { |
| | 984 | return function() { |
| | 985 | errorcallback(xmldocpath); |
| | 986 | } |
| | 987 | } |
| | 988 | |
| | 989 | function _readyStateChangeHandler(xmlhttp, xmldocpath, completecallback, errorcallback) { |
| | 990 | return function() { |
| | 991 | if (xmlhttp.readyState === 4) { |
| | 992 | if (xmlhttp.status == 200) { |
| | 993 | _ajaxComplete(xmlhttp, xmldocpath, completecallback, errorcallback)(); |
| | 994 | } else if (errorcallback) { |
| | 995 | errorcallback(xmldocpath); |
| | 996 | } |
| | 997 | } |
| | 998 | } |
| | 999 | } |
| | 1000 | |
| | 1001 | function _ajaxComplete(xmlhttp, xmldocpath, completecallback, errorcallback) { |
| | 1002 | return function() { |
| | 1003 | // Handle the case where an XML document was returned with an incorrect MIME type. |
| | 1004 | if (!utils.exists(xmlhttp.responseXML)) { |
| | 1005 | try { |
| | 1006 | var parsedXML; |
| | 1007 | // Parse XML in FF/Chrome/Safari/Opera |
| | 1008 | if (WINDOW.DOMParser) { |
| | 1009 | parsedXML = (new DOMParser()).parseFromString(xmlhttp.responseText,"text/xml"); |
| | 1010 | } else { |
| | 1011 | // Internet Explorer |
| | 1012 | parsedXML = new ActiveXObject("Microsoft.XMLDOM"); |
| | 1013 | parsedXML.async="false"; |
| | 1014 | parsedXML.loadXML(xmlhttp.responseText); |
| | 1015 | } |
| | 1016 | if (parsedXML) { |
| | 1017 | xmlhttp = utils.extend({}, xmlhttp, {responseXML:parsedXML}); |
| | 1018 | } |
| | 1019 | } catch(e) { |
| | 1020 | if (errorcallback) errorcallback(xmldocpath); |
| | 1021 | return; |
| | 1022 | } |
| | 1023 | } |
| | 1024 | completecallback(xmlhttp); |
| | 1025 | } |
| | 1026 | } |
| | 1027 | |
| | 1028 | /** Returns the true type of an object * */ |
| | 1029 | utils.typeOf = function(value) { |
| | 1030 | var typeofString = typeof value; |
| | 1031 | if (typeofString === 'object') { |
| | 1032 | if (!value) return "null"; |
| | 1033 | return (value instanceof Array) ? 'array' : typeofString; |
| | 1034 | } else { |
| | 1035 | return typeofString; |
| | 1036 | } |
| | 1037 | }; |
| | 1038 | |
| | 1039 | /* Normalizes differences between Flash and HTML5 internal players' event responses. */ |
| | 1040 | utils.translateEventResponse = function(type, eventProperties) { |
| | 1041 | var translated = jwplayer.utils.extend({}, eventProperties); |
| | 1042 | if (type == jwplayer.api.events.JWPLAYER_FULLSCREEN && !translated.fullscreen) { |
| | 1043 | translated.fullscreen = translated.message == "true" ? true : false; |
| | 1044 | delete translated.message; |
| | 1045 | } else if (typeof translated.data == "object") { |
| | 1046 | // Takes ViewEvent "data" block and moves it up a level |
| | 1047 | translated = jwplayer.utils.extend(translated, translated.data); |
| | 1048 | delete translated.data; |
| | 1049 | } else if (typeof translated.metadata == "object") { |
| | 1050 | jwplayer.utils.deepReplaceKeyName(translated.metadata, ["__dot__","__spc__","__dsh__"], ["."," ","-"]); |
| | 1051 | } |
| | 1052 | |
| | 1053 | var rounders = ["position", "duration", "offset"]; |
| | 1054 | for (var rounder in rounders) { |
| | 1055 | if (translated[rounders[rounder]]) { |
| | 1056 | translated[rounders[rounder]] = Math.round(translated[rounders[rounder]] * 1000) / 1000; |
| | 1057 | } |
| | 1058 | } |
| | 1059 | |
| | 1060 | return translated; |
| | 1061 | } |
| | 1062 | |
| 1016 | | * Parsers namespace declaration |
| 1017 | | * |
| 1018 | | * @author pablo |
| 1019 | | * @version 6.0 |
| 1020 | | */ |
| 1021 | | (function(html5) { |
| 1022 | | html5.parsers = { |
| 1023 | | localName : function(node) { |
| 1024 | | if (!node) { |
| 1025 | | return ""; |
| 1026 | | } else if (node.localName) { |
| 1027 | | return node.localName; |
| 1028 | | } else if (node.baseName) { |
| 1029 | | return node.baseName; |
| 1030 | | } else { |
| 1031 | | return ""; |
| 1032 | | } |
| 1033 | | }, |
| 1034 | | textContent : function(node) { |
| 1035 | | if (!node) { |
| 1036 | | return ""; |
| 1037 | | } else if (node.textContent) { |
| 1038 | | return node.textContent; |
| 1039 | | } else if (node.text) { |
| 1040 | | return node.text; |
| 1041 | | } else { |
| 1042 | | return ""; |
| 1043 | | } |
| 1044 | | }, |
| 1045 | | getChildNode : function(parent, index) { |
| 1046 | | return parent.childNodes[index]; |
| 1047 | | }, |
| 1048 | | numChildren : function(parent) { |
| 1049 | | if (parent.childNodes) { |
| 1050 | | return parent.childNodes.length; |
| 1051 | | } else { |
| 1052 | | return 0; |
| 1053 | | } |
| 1054 | | } |
| 1055 | | |
| 1056 | | }; |
| 1057 | | })(jwplayer.html5); |
| 1058 | | /** |
| 1059 | | * Parse a feed item for JWPlayer content. |
| 1060 | | * |
| 1061 | | * @author zach |
| 1062 | | * @modified pablo |
| 1063 | | * @version 6.0 |
| 1064 | | */ |
| 1065 | | (function(jwplayer) { |
| 1066 | | var _parsers = jwplayer.html5.parsers; |
| 1067 | | |
| 1068 | | var jwparser = _parsers.jwparser = function() { |
| 1069 | | }; |
| 1070 | | |
| 1071 | | var PREFIX = 'jwplayer'; |
| 1072 | | |
| 1073 | | /** |
| 1074 | | * Parse a feed entry for JWPlayer content. |
| 1075 | | * |
| 1076 | | * @param {XML} |
| 1077 | | * obj The XML object to parse. |
| 1078 | | * @param {Object} |
| 1079 | | * itm The playlistentry to amend the object to. |
| 1080 | | * @return {Object} The playlistentry, amended with the JWPlayer info. |
| 1081 | | */ |
| 1082 | | jwparser.parseEntry = function(obj, itm) { |
| 1083 | | for ( var i = 0; i < obj.childNodes.length; i++) { |
| 1084 | | var node = obj.childNodes[i]; |
| 1085 | | if (node.prefix == PREFIX) { |
| 1086 | | var _localName = _parsers.localName(node); |
| 1087 | | itm[_localName] = jwplayer.utils.strings.serialize(_parsers.textContent(node)); |
| 1088 | | if (_localName == "file" && itm.levels) { |
| 1089 | | // jwplayer namespace file should override existing level |
| 1090 | | // (probably set in MediaParser) |
| 1091 | | delete itm.levels; |
| 1092 | | } |
| 1093 | | } |
| 1094 | | if (!itm['file']) { |
| 1095 | | itm['file'] = itm['link']; |
| 1096 | | } |
| 1097 | | } |
| 1098 | | return itm; |
| 1099 | | } |
| 1100 | | })(jwplayer);/** |
| 1101 | | * Parse a MRSS group into a playlistitem (used in RSS and ATOM). |
| 1102 | | * |
| 1103 | | * author zach |
| 1104 | | * modified pablo |
| 1105 | | * version 6.0 |
| 1106 | | */ |
| 1107 | | (function(parsers) { |
| 1108 | | var _strings = jwplayer.utils.strings, |
| 1109 | | _xmlAttribute = _strings.xmlAttribute, |
| 1110 | | _localName = parsers.localName, |
| 1111 | | _textContent = parsers.textContent, |
| 1112 | | _numChildren = parsers.numChildren; |
| 1113 | | |
| 1114 | | |
| 1115 | | var mediaparser = parsers.mediaparser = function() {}; |
| 1116 | | |
| 1117 | | /** Prefix for the MRSS namespace. **/ |
| 1118 | | var PREFIX = 'media'; |
| 1119 | | |
| 1120 | | /** |
| 1121 | | * Parse a feeditem for Yahoo MediaRSS extensions. |
| 1122 | | * The 'content' and 'group' elements can nest other MediaRSS elements. |
| 1123 | | * @param {XML} obj The entire MRSS XML object. |
| 1124 | | * @param {Object} itm The playlistentry to amend the object to. |
| 1125 | | * @return {Object} The playlistentry, amended with the MRSS info. |
| 1126 | | **/ |
| 1127 | | mediaparser.parseGroup = function(obj, itm) { |
| 1128 | | for (var i = 0; i < _numChildren(obj); i++) { |
| 1129 | | var node = obj.childNodes[i]; |
| 1130 | | if (node.prefix == PREFIX) { |
| 1131 | | if (!_localName(node)){ |
| 1132 | | continue; |
| 1133 | | } |
| 1134 | | switch (_localName(node).toLowerCase()) { |
| 1135 | | case 'content': |
| 1136 | | itm['file'] = _xmlAttribute(node, 'url'); |
| 1137 | | if (_xmlAttribute(node, 'duration')) { |
| 1138 | | itm['duration'] = _strings.seconds(_xmlAttribute(node, 'duration')); |
| 1139 | | } |
| 1140 | | if (_xmlAttribute(node, 'start')) { |
| 1141 | | itm['start'] = _strings.seconds(_xmlAttribute(node, 'start')); |
| 1142 | | } |
| 1143 | | if (_numChildren(node) > 0) { |
| 1144 | | itm = mediaparser.parseGroup(node, itm); |
| 1145 | | } |
| 1146 | | if (_xmlAttribute(node, 'width') |
| 1147 | | || _xmlAttribute(node, 'bitrate') |
| 1148 | | || _xmlAttribute(node, 'url')) { |
| 1149 | | if (!itm.levels) { |
| 1150 | | itm.levels = []; |
| 1151 | | } |
| 1152 | | itm.levels.push({ |
| 1153 | | width: _xmlAttribute(node, 'width'), |
| 1154 | | bitrate: _xmlAttribute(node, 'bitrate'), |
| 1155 | | file: _xmlAttribute(node, 'url') |
| 1156 | | }); |
| 1157 | | } |
| 1158 | | break; |
| 1159 | | case 'title': |
| 1160 | | itm['title'] = _textContent(node); |
| 1161 | | break; |
| 1162 | | case 'description': |
| 1163 | | itm['description'] = _textContent(node); |
| 1164 | | break; |
| 1165 | | case 'keywords': |
| 1166 | | itm['tags'] = _textContent(node); |
| 1167 | | break; |
| 1168 | | case 'thumbnail': |
| 1169 | | itm['image'] = _xmlAttribute(node, 'url'); |
| 1170 | | break; |
| 1171 | | case 'credit': |
| 1172 | | itm['author'] = _textContent(node); |
| 1173 | | break; |
| 1174 | | case 'player': |
| 1175 | | var url = node.url; |
| 1176 | | break; |
| 1177 | | case 'group': |
| 1178 | | mediaparser.parseGroup(node, itm); |
| 1179 | | break; |
| 1180 | | } |
| 1181 | | } |
| 1182 | | } |
| 1183 | | return itm; |
| 1184 | | } |
| 1185 | | |
| 1186 | | })(jwplayer.html5.parsers); |
| 1187 | | /** |
| 1188 | | * Parse an RSS feed and translate it to a playlist. |
| 1189 | | * |
| 1190 | | * @author zach |
| 1191 | | * @modified pablo |
| 1192 | | * @version 6.0 |
| 1193 | | */ |
| 1194 | | (function(parsers) { |
| 1195 | | var _utils = jwplayer.utils, |
| 1196 | | _textContent = parsers.textContent, |
| 1197 | | _getChildNode = parsers.getChildNode, |
| 1198 | | _numChildren = parsers.numChildren, |
| 1199 | | _localName = parsers.localName; |
| 1200 | | |
| 1201 | | parsers.rssparser = {}; |
| 1202 | | |
| 1203 | | |
| 1204 | | /** |
| 1205 | | * Parse an RSS playlist for feed items. |
| 1206 | | * |
| 1207 | | * @param {XML} dat |
| 1208 | | * @reuturn {Array} playlistarray |
| 1209 | | */ |
| 1210 | | parsers.rssparser.parse = function(dat) { |
| 1211 | | var arr = []; |
| 1212 | | for (var i = 0; i < _numChildren(dat); i++) { |
| 1213 | | var node = _getChildNode(dat, i), |
| 1214 | | localName = _localName(node).toLowerCase(); |
| 1215 | | if (localName == 'channel') { |
| 1216 | | for (var j = 0; j < _numChildren(node); j++) { |
| 1217 | | var subNode = _getChildNode(node, j); |
| 1218 | | if (_localName(subNode).toLowerCase() == 'item') { |
| 1219 | | arr.push(_parseItem(subNode)); |
| 1220 | | } |
| 1221 | | } |
| 1222 | | } |
| 1223 | | } |
| 1224 | | return arr; |
| 1225 | | }; |
| 1226 | | |
| 1227 | | |
| 1228 | | /** |
| 1229 | | * Translate RSS item to playlist item. |
| 1230 | | * |
| 1231 | | * @param {XML} obj |
| 1232 | | * @return {PlaylistItem} PlaylistItem |
| 1233 | | */ |
| 1234 | | function _parseItem(obj) { |
| 1235 | | var itm = {}; |
| 1236 | | for (var i = 0; i < obj.childNodes.length; i++) { |
| 1237 | | var node = obj.childNodes[i]; |
| 1238 | | var localName = _localName(node); |
| 1239 | | if (!localName){ |
| 1240 | | continue; |
| 1241 | | } |
| 1242 | | switch (localName.toLowerCase()) { |
| 1243 | | case 'enclosure': |
| 1244 | | itm['file'] = _utils.strings.xmlAttribute(node, 'url'); |
| 1245 | | break; |
| 1246 | | case 'title': |
| 1247 | | itm['title'] = _textContent(node); |
| 1248 | | break; |
| 1249 | | case 'pubdate': |
| 1250 | | itm['date'] = _textContent(node); |
| 1251 | | break; |
| 1252 | | case 'description': |
| 1253 | | itm['description'] = _textContent(node); |
| 1254 | | break; |
| 1255 | | case 'link': |
| 1256 | | itm['link'] = _textContent(node); |
| 1257 | | break; |
| 1258 | | case 'category': |
| 1259 | | if (itm['tags']) { |
| 1260 | | itm['tags'] += _textContent(node); |
| 1261 | | } else { |
| 1262 | | itm['tags'] = _textContent(node); |
| 1263 | | } |
| 1264 | | break; |
| 1265 | | } |
| 1266 | | } |
| 1267 | | itm = parsers.mediaparser.parseGroup(obj, itm); |
| 1268 | | itm = parsers.jwparser.parseEntry(obj, itm); |
| 1269 | | |
| 1270 | | return new jwplayer.html5.playlistitem(itm); |
| 1271 | | } |
| 1272 | | |
| 1273 | | |
| 1274 | | |
| 1275 | | |
| 1276 | | })(jwplayer.html5.parsers); |
| 1277 | | /** |
| 1278 | | * JW Player HTML5 Controlbar component |
| 1279 | | * |
| 1280 | | * @author pablo |
| 1281 | | * @version 6.0 |
| 1282 | | */ |
| 1283 | | (function(jwplayer) { |
| 1284 | | |
| 1285 | | var _html5 = jwplayer.html5, |
| 1286 | | _utils = jwplayer.utils, |
| 1287 | | _events = jwplayer.events, |
| 1288 | | _states = jwplayer.events.state, |
| 1289 | | _css = _utils.css, |
| 1290 | | |
| 1291 | | /** Controlbar element types **/ |
| 1292 | | CB_BUTTON = "button", |
| 1293 | | CB_TEXT = "text", |
| 1294 | | CB_DIVIDER = "divider", |
| 1295 | | CB_SLIDER = "slider", |
| 1296 | | |
| 1297 | | /** Some CSS constants we should use for minimization **/ |
| 1298 | | JW_CSS_RELATIVE = "relative", |
| 1299 | | JW_CSS_ABSOLUTE = "absolute", |
| 1300 | | JW_CSS_NONE = "none", |
| 1301 | | JW_CSS_BLOCK = "block", |
| 1302 | | JW_CSS_INLINE = "inline", |
| 1303 | | JW_CSS_INLINE_BLOCK = "inline-block", |
| 1304 | | JW_CSS_LEFT = "left", |
| 1305 | | JW_CSS_RIGHT = "right", |
| 1306 | | JW_CSS_100PCT = "100%", |
| 1307 | | JW_CSS_SMOOTH_EASE = "width .25s linear, left .25s linear, opacity .25s, background .25s", |
| 1308 | | |
| 1309 | | CB_CLASS = '.jwcontrolbar', |
| 1310 | | |
| 1311 | | DOCUMENT = document; |
| 1312 | | |
| 1313 | | /** HTML5 Controlbar class **/ |
| 1314 | | _html5.controlbar = function(api, config) { |
| 1315 | | var _api, |
| 1316 | | _skin, |
| 1317 | | _defaults = { |
| 1318 | | // backgroundcolor : "", |
| 1319 | | margin : 10, |
| 1320 | | font : "Arial,sans-serif", |
| 1321 | | fontsize : 10, |
| 1322 | | fontcolor : parseInt("000000", 16), |
| 1323 | | fontstyle : "normal", |
| 1324 | | fontweight : "bold", |
| 1325 | | // buttoncolor : parseInt("ffffff", 16), |
| 1326 | | // position : html5.view.positions.BOTTOM, |
| 1327 | | // idlehide : false, |
| 1328 | | // hideplaylistcontrols : false, |
| 1329 | | // forcenextprev : false, |
| 1330 | | layout : { |
| 1331 | | left: { |
| 1332 | | position: "left", |
| 1333 | | elements: [ { |
| 1334 | | name: "play", |
| 1335 | | type: CB_BUTTON |
| 1336 | | }, { |
| 1337 | | name: "divider", |
| 1338 | | type: CB_DIVIDER |
| 1339 | | }, { |
| 1340 | | name: "prev", |
| 1341 | | type: CB_BUTTON |
| 1342 | | }, { |
| 1343 | | name: "divider", |
| 1344 | | type: CB_DIVIDER |
| 1345 | | }, { |
| 1346 | | name: "next", |
| 1347 | | type: CB_BUTTON |
| 1348 | | }, { |
| 1349 | | name: "divider", |
| 1350 | | type: CB_DIVIDER |
| 1351 | | }, { |
| 1352 | | name: "elapsed", |
| 1353 | | type: CB_TEXT |
| 1354 | | } ] |
| 1355 | | }, |
| 1356 | | center: { |
| 1357 | | position: "center", |
| 1358 | | elements: [ { |
| 1359 | | name: "time", |
| 1360 | | type: CB_SLIDER |
| 1361 | | } ] |
| 1362 | | }, |
| 1363 | | right: { |
| 1364 | | position: "right", |
| 1365 | | elements: [ { |
| 1366 | | name: "duration", |
| 1367 | | type: CB_TEXT |
| 1368 | | }, { |
| 1369 | | name: "blank", |
| 1370 | | type: CB_BUTTON |
| 1371 | | }, { |
| 1372 | | name: "divider", |
| 1373 | | type: CB_DIVIDER |
| 1374 | | }, { |
| 1375 | | name: "mute", |
| 1376 | | type: CB_BUTTON |
| 1377 | | }, { |
| 1378 | | name: "volume", |
| 1379 | | type: CB_SLIDER |
| 1380 | | }, { |
| 1381 | | name: "divider", |
| 1382 | | type: CB_DIVIDER |
| 1383 | | }, { |
| 1384 | | name: "fullscreen", |
| 1385 | | type: CB_BUTTON |
| 1386 | | }] |
| 1387 | | } |
| 1388 | | } |
| 1389 | | }, |
| 1390 | | |
| 1391 | | _settings, |
| 1392 | | _layout, |
| 1393 | | _elements, |
| 1394 | | _controlbar, |
| 1395 | | _id, |
| 1396 | | _duration, |
| 1397 | | _position, |
| 1398 | | _currentVolume, |
| 1399 | | _dragging = false, |
| 1400 | | _lastSeekTime = 0, |
| 1401 | | |
| 1402 | | _toggles = { |
| 1403 | | play: "pause", |
| 1404 | | mute: "unmute", |
| 1405 | | fullscreen: "normalscreen" |
| 1406 | | }, |
| 1407 | | |
| 1408 | | _toggleStates = { |
| 1409 | | play: false, |
| 1410 | | mute: false, |
| 1411 | | fullscreen: false |
| 1412 | | }, |
| 1413 | | |
| 1414 | | _buttonMapping = { |
| 1415 | | play: _play, |
| 1416 | | mute: _mute, |
| 1417 | | fullscreen: _fullscreen, |
| 1418 | | next: _next, |
| 1419 | | prev: _prev |
| 1420 | | }, |
| 1421 | | |
| 1422 | | _sliderMapping = { |
| 1423 | | time: _seek, |
| 1424 | | volume: _volume |
| 1425 | | }; |
| 1426 | | |
| 1427 | | function _init() { |
| 1428 | | _elements = {}; |
| 1429 | | |
| 1430 | | _api = api; |
| 1431 | | |
| 1432 | | _id = _api.id + "_controlbar"; |
| 1433 | | _duration = _position = 0; |
| 1434 | | |
| 1435 | | _controlbar = _createSpan(); |
| 1436 | | _controlbar.id = _id; |
| 1437 | | _controlbar.className = "jwcontrolbar"; |
| 1438 | | |
| 1439 | | // Slider listeners |
| 1440 | | window.addEventListener('mousemove', _sliderMouseEvent, false); |
| 1441 | | window.addEventListener('mouseup', _sliderMouseEvent, false); |
| 1442 | | |
| 1443 | | _skin = _api.skin; |
| 1444 | | |
| 1445 | | _settings = _utils.extend({}, _defaults, _skin.getComponentSettings('controlbar'), config); |
| 1446 | | _layout = _skin.getComponentLayout('controlbar'); |
| 1447 | | if (!_layout) _layout = _defaults.layout; |
| 1448 | | _createStyles(); |
| 1449 | | _buildControlbar(); |
| 1450 | | _addEventListeners(); |
| 1451 | | _playlistHandler(); |
| 1452 | | _volumeHandler(); |
| 1453 | | _muteHandler(); |
| 1454 | | } |
| 1455 | | |
| 1456 | | function _addEventListeners() { |
| 1457 | | _api.jwAddEventListener(jwplayer.events.JWPLAYER_MEDIA_TIME, _timeUpdated); |
| 1458 | | _api.jwAddEventListener(jwplayer.events.JWPLAYER_PLAYER_STATE, _stateHandler); |
| 1459 | | _api.jwAddEventListener(jwplayer.events.JWPLAYER_MEDIA_MUTE, _muteHandler); |
| 1460 | | _api.jwAddEventListener(jwplayer.events.JWPLAYER_MEDIA_VOLUME, _volumeHandler); |
| 1461 | | _api.jwAddEventListener(jwplayer.events.JWPLAYER_MEDIA_BUFFER, _bufferHandler); |
| 1462 | | _api.jwAddEventListener(jwplayer.events.JWPLAYER_FULLSCREEN, _fullscreenHandler); |
| 1463 | | _api.jwAddEventListener(jwplayer.events.JWPLAYER_PLAYLIST_LOADED, _playlistHandler); |
| 1464 | | } |
| 1465 | | |
| 1466 | | function _timeUpdated(evt) { |
| 1467 | | var refreshRequired = false, |
| 1468 | | timeString; |
| 1469 | | |
| 1470 | | if (_elements.elapsed) { |
| 1471 | | timeString = _utils.timeFormat(evt.position); |
| 1472 | | _elements.elapsed.innerHTML = timeString; |
| 1473 | | refreshRequired = (timeString.length != _utils.timeFormat(_position).length); |
| 1474 | | } |
| 1475 | | if (_elements.duration) { |
| 1476 | | timeString = _utils.timeFormat(evt.duration); |
| 1477 | | _elements.duration.innerHTML = timeString; |
| 1478 | | refreshRequired = (refreshRequired || (timeString.length != _utils.timeFormat(_duration).length)); |
| 1479 | | } |
| 1480 | | if (evt.duration > 0) { |
| 1481 | | _setProgress(evt.position / evt.duration); |
| 1482 | | } else { |
| 1483 | | _setProgress(0); |
| 1484 | | } |
| 1485 | | _duration = evt.duration; |
| 1486 | | _position = evt.position; |
| 1487 | | |
| 1488 | | if (refreshRequired) _resize(); |
| 1489 | | } |
| 1490 | | |
| 1491 | | function _stateHandler(evt) { |
| 1492 | | switch (evt.newstate) { |
| 1493 | | case _states.BUFFERING: |
| 1494 | | case _states.PLAYING: |
| 1495 | | _css(_internalSelector('.jwtimeSliderThumb'), { opacity: 1 }); |
| 1496 | | _toggleButton("play", true); |
| 1497 | | break; |
| 1498 | | case _states.PAUSED: |
| 1499 | | if (!_dragging) { |
| 1500 | | _toggleButton("play", false); |
| 1501 | | } |
| 1502 | | break; |
| 1503 | | case _states.IDLE: |
| 1504 | | _toggleButton("play", false); |
| 1505 | | _css(_internalSelector('.jwtimeSliderThumb'), { opacity: 0 }); |
| 1506 | | if (_elements["timeRail"]) { |
| 1507 | | _elements["timeRail"].className = "jwrail"; |
| 1508 | | setTimeout(function() { |
| 1509 | | // Temporarily disable the buffer animation |
| 1510 | | _elements["timeRail"].className += " jwsmooth"; |
| 1511 | | }, 100); |
| 1512 | | } |
| 1513 | | _setBuffer(0); |
| 1514 | | _timeUpdated({ position: 0, duration: 0}); |
| 1515 | | break; |
| 1516 | | case _states.COMPLETED: |
| 1517 | | _css(_internalSelector(), { opacity: 0 }); |
| 1518 | | break; |
| 1519 | | } |
| 1520 | | } |
| 1521 | | |
| 1522 | | function _muteHandler() { |
| 1523 | | var state = _api.jwGetMute(); |
| 1524 | | _toggleButton("mute", state); |
| 1525 | | _setVolume(state ? 0 : _currentVolume) |
| 1526 | | } |
| 1527 | | |
| 1528 | | function _volumeHandler() { |
| 1529 | | _currentVolume = _api.jwGetVolume() / 100; |
| 1530 | | _setVolume(_currentVolume); |
| 1531 | | } |
| 1532 | | |
| 1533 | | function _bufferHandler(evt) { |
| 1534 | | _setBuffer(evt.bufferPercent / 100); |
| 1535 | | } |
| 1536 | | |
| 1537 | | function _fullscreenHandler(evt) { |
| 1538 | | _toggleButton("fullscreen", evt.fullscreen); |
| 1539 | | } |
| 1540 | | |
| 1541 | | function _playlistHandler(evt) { |
| 1542 | | if (_api.jwGetPlaylist().length < 2) { |
| 1543 | | _css(_internalSelector(".jwnext"), { display: "none" }); |
| 1544 | | _css(_internalSelector(".jwprev"), { display: "none" }); |
| 1545 | | } else { |
| 1546 | | _css(_internalSelector(".jwnext"), { display: undefined }); |
| 1547 | | _css(_internalSelector(".jwprev"), { display: undefined }); |
| 1548 | | } |
| 1549 | | _resize(); |
| 1550 | | } |
| 1551 | | |
| 1552 | | /** |
| 1553 | | * Styles specific to this controlbar/skin |
| 1554 | | */ |
| 1555 | | function _createStyles() { |
| 1556 | | _utils.clearCss('#'+_id); |
| 1557 | | |
| 1558 | | _css('#'+_id, { |
| 1559 | | height: _getSkinElement("background").height, |
| 1560 | | bottom: _settings.margin ? _settings.margin : 0, |
| 1561 | | left: _settings.margin ? _settings.margin : 0, |
| 1562 | | right: _settings.margin ? _settings.margin : 0 |
| 1563 | | }); |
| 1564 | | |
| 1565 | | _css(_internalSelector(".jwtext"), { |
| 1566 | | font: _settings.fontsize + "px/" + _getSkinElement("background").height + "px " + _settings.font, |
| 1567 | | color: _settings.fontcolor, |
| 1568 | | 'font-weight': _settings.fontweight, |
| 1569 | | 'font-style': _settings.fontstyle, |
| 1570 | | 'text-align': 'center', |
| 1571 | | padding: '0 5px' |
| 1572 | | }); |
| 1573 | | } |
| 1574 | | |
| 1575 | | |
| 1576 | | function _internalSelector(name) { |
| 1577 | | return '#' + _id + (name ? " " + name : ""); |
| 1578 | | } |
| 1579 | | |
| 1580 | | function _createSpan() { |
| 1581 | | return DOCUMENT.createElement("span"); |
| 1582 | | } |
| 1583 | | |
| 1584 | | function _buildControlbar() { |
| 1585 | | var capLeft = _buildImage("capLeft"); |
| 1586 | | var capRight = _buildImage("capRight"); |
| 1587 | | var bg = _buildImage("background", { |
| 1588 | | position: JW_CSS_ABSOLUTE, |
| 1589 | | left: _getSkinElement('capLeft').width, |
| 1590 | | right: _getSkinElement('capRight').width, |
| 1591 | | 'background-repeat': "repeat-x" |
| 1592 | | }, true); |
| 1593 | | |
| 1594 | | if (bg) _controlbar.appendChild(bg); |
| 1595 | | if (capLeft) _controlbar.appendChild(capLeft); |
| 1596 | | _buildLayout(); |
| 1597 | | if (capRight) _controlbar.appendChild(capRight); |
| 1598 | | } |
| 1599 | | |
| 1600 | | function _buildElement(element) { |
| 1601 | | switch (element.type) { |
| 1602 | | case CB_DIVIDER: |
| 1603 | | return _buildDivider(element); |
| 1604 | | break; |
| 1605 | | case CB_TEXT: |
| 1606 | | return _buildText(element.name); |
| 1607 | | break; |
| 1608 | | case CB_BUTTON: |
| 1609 | | if (element.name != "blank") { |
| 1610 | | return _buildButton(element.name); |
| 1611 | | } |
| 1612 | | break; |
| 1613 | | case CB_SLIDER: |
| 1614 | | return _buildSlider(element.name); |
| 1615 | | break; |
| 1616 | | } |
| 1617 | | } |
| 1618 | | |
| 1619 | | function _buildImage(name, style, stretch, nocenter) { |
| 1620 | | var element = _createSpan(); |
| 1621 | | element.className = 'jw'+name; |
| 1622 | | |
| 1623 | | var center = nocenter ? " left center" : " center"; |
| 1624 | | |
| 1625 | | var skinElem = _getSkinElement(name); |
| 1626 | | element.innerHTML = " "; |
| 1627 | | if (!skinElem || skinElem.src == "") { |
| 1628 | | return; |
| 1629 | | } |
| 1630 | | |
| 1631 | | var newStyle; |
| 1632 | | |
| 1633 | | if (stretch) { |
| 1634 | | newStyle = { |
| 1635 | | background: "url('" + skinElem.src + "') repeat-x " + center |
| 1636 | | }; |
| 1637 | | } else { |
| 1638 | | newStyle = { |
| 1639 | | background: "url('" + skinElem.src + "') no-repeat" + center, |
| 1640 | | width: skinElem.width |
| 1641 | | }; |
| 1642 | | } |
| 1643 | | |
| 1644 | | _css(_internalSelector('.jw'+name), _utils.extend(newStyle, style)); |
| 1645 | | _elements[name] = element; |
| 1646 | | return element; |
| 1647 | | } |
| 1648 | | |
| 1649 | | function _buildButton(name) { |
| 1650 | | if (!_getSkinElement(name + "Button").src) { |
| 1651 | | return null; |
| 1652 | | } |
| 1653 | | |
| 1654 | | var element = DOCUMENT.createElement("button"); |
| 1655 | | element.className = 'jw'+name; |
| 1656 | | element.addEventListener("click", _buttonClickHandler(name), false); |
| 1657 | | |
| 1658 | | var outSkin = _getSkinElement(name + "Button"); |
| 1659 | | var overSkin = _getSkinElement(name + "ButtonOver"); |
| 1660 | | |
| 1661 | | element.innerHTML = " "; |
| 1662 | | |
| 1663 | | _buttonStyle(_internalSelector('.jw'+name), outSkin, overSkin); |
| 1664 | | var toggle = _toggles[name]; |
| 1665 | | if (toggle) { |
| 1666 | | _buttonStyle(_internalSelector('.jw'+name+'.jwtoggle'), _getSkinElement(toggle+"Button"), _getSkinElement(toggle+"ButtonOver")); |
| 1667 | | } |
| 1668 | | |
| 1669 | | _elements[name] = element; |
| 1670 | | |
| 1671 | | return element; |
| 1672 | | } |
| 1673 | | |
| 1674 | | function _buttonStyle(selector, out, over) { |
| 1675 | | if (!out.src) { |
| 1676 | | return; |
| 1677 | | } |
| 1678 | | |
| 1679 | | _css(selector, { |
| 1680 | | width: out.width, |
| 1681 | | background: 'url('+ out.src +') center no-repeat' |
| 1682 | | }); |
| 1683 | | |
| 1684 | | if (over.src) { |
| 1685 | | _css(selector + ':hover', { |
| 1686 | | background: 'url('+ over.src +') center no-repeat' |
| 1687 | | }); |
| 1688 | | } |
| 1689 | | } |
| 1690 | | |
| 1691 | | function _buttonClickHandler(name) { |
| 1692 | | return function() { |
| 1693 | | if (_buttonMapping[name]) { |
| 1694 | | _buttonMapping[name](); |
| 1695 | | } |
| 1696 | | } |
| 1697 | | } |
| 1698 | | |
| 1699 | | |
| 1700 | | function _play() { |
| 1701 | | if (_toggleStates.play) { |
| 1702 | | _api.jwPause(); |
| 1703 | | } else { |
| 1704 | | _api.jwPlay(); |
| 1705 | | } |
| 1706 | | } |
| 1707 | | |
| 1708 | | function _mute() { |
| 1709 | | _api.jwSetMute(); |
| 1710 | | _muteHandler({mute:_toggleStates.mute}); |
| 1711 | | } |
| 1712 | | |
| 1713 | | function _volume(pct) { |
| 1714 | | if (pct < 0.1) pct = 0; |
| 1715 | | if (pct > 0.9) pct = 1; |
| 1716 | | _api.jwSetVolume(pct * 100); |
| 1717 | | _setVolume(pct); |
| 1718 | | } |
| 1719 | | |
| 1720 | | function _seek(pct) { |
| 1721 | | _api.jwSeek(pct * _duration); |
| 1722 | | } |
| 1723 | | |
| 1724 | | function _fullscreen() { |
| 1725 | | _api.jwSetFullscreen(); |
| 1726 | | } |
| 1727 | | |
| 1728 | | function _next() { |
| 1729 | | _api.jwPlaylistNext(); |
| 1730 | | } |
| 1731 | | |
| 1732 | | function _prev() { |
| 1733 | | _api.jwPlaylistNext(); |
| 1734 | | } |
| 1735 | | |
| 1736 | | function _toggleButton(name, state) { |
| 1737 | | if (!_utils.exists(state)) { |
| 1738 | | state = !_toggleStates[name]; |
| 1739 | | } |
| 1740 | | if (_elements[name]) { |
| 1741 | | _elements[name].className = 'jw' + name + (state ? " jwtoggle jwtoggling" : " jwtoggling"); |
| 1742 | | // Use the jwtoggling class to temporarily disable the animation; |
| 1743 | | setTimeout(function() { |
| 1744 | | _elements[name].className = _elements[name].className.replace(" jwtoggling", ""); |
| 1745 | | }, 100); |
| 1746 | | } |
| 1747 | | _toggleStates[name] = state; |
| 1748 | | } |
| 1749 | | |
| 1750 | | function _createElementId(name) { |
| 1751 | | return _id + "_" + name; |
| 1752 | | } |
| 1753 | | |
| 1754 | | function _buildText(name, style) { |
| 1755 | | var element = _createSpan(); |
| 1756 | | element.id = _createElementId(name); |
| 1757 | | element.className = "jwtext jw" + name; |
| 1758 | | |
| 1759 | | var css = {}; |
| 1760 | | |
| 1761 | | var skinElement = _getSkinElement(name+"Background"); |
| 1762 | | if (skinElement.src) { |
| 1763 | | css.background = "url(" + skinElement.src + ") no-repeat center"; |
| 1764 | | css['background-size'] = "100% " + _getSkinElement("background").height + "px"; |
| 1765 | | } |
| 1766 | | |
| 1767 | | _css(_internalSelector('.jw'+name), css); |
| 1768 | | element.innerHTML = "00:00"; |
| 1769 | | _elements[name] = element; |
| 1770 | | return element; |
| 1771 | | } |
| 1772 | | |
| 1773 | | function _buildDivider(divider) { |
| 1774 | | if (divider.width) { |
| 1775 | | var element = _createSpan(); |
| 1776 | | element.className = "jwblankDivider"; |
| 1777 | | _css(element, { |
| 1778 | | width: parseInt(divider.width) |
| 1779 | | }); |
| 1780 | | return element; |
| 1781 | | } else if (divider.element) { |
| 1782 | | return _buildImage(divider.element); |
| 1783 | | } else { |
| 1784 | | return _buildImage(divider.name); |
| 1785 | | } |
| 1786 | | } |
| 1787 | | |
| 1788 | | function _buildSlider(name) { |
| 1789 | | var slider = _createSpan(); |
| 1790 | | slider.className = "jwslider jw" + name; |
| 1791 | | |
| 1792 | | |
| 1793 | | var capLeft = _buildImage(name + "SliderCapLeft"); |
| 1794 | | var capRight = _buildImage(name + "SliderCapRight"); |
| 1795 | | if (capRight) capRight.className += " jwcapRight"; |
| 1796 | | |
| 1797 | | var rail = _buildSliderRail(name); |
| 1798 | | |
| 1799 | | if (capLeft) slider.appendChild(capLeft); |
| 1800 | | slider.appendChild(rail); |
| 1801 | | if (capLeft) slider.appendChild(capRight); |
| 1802 | | |
| 1803 | | _css(_internalSelector(".jw" + name + " .jwrail"), { |
| 1804 | | left: _getSkinElement(name+"SliderCapLeft").width, |
| 1805 | | right: _getSkinElement(name+"SliderCapRight").width, |
| 1806 | | }); |
| 1807 | | |
| 1808 | | _elements[name] = slider; |
| 1809 | | |
| 1810 | | if (name == "time") { |
| 1811 | | _styleTimeSlider(slider); |
| 1812 | | _setProgress(0); |
| 1813 | | _setBuffer(0); |
| 1814 | | } else if (name == "volume") { |
| 1815 | | _styleVolumeSlider(slider); |
| 1816 | | } |
| 1817 | | |
| 1818 | | |
| 1819 | | return slider; |
| 1820 | | } |
| 1821 | | |
| 1822 | | function _buildSliderRail(name) { |
| 1823 | | var rail = _createSpan(); |
| 1824 | | rail.className = "jwrail jwsmooth"; |
| 1825 | | |
| 1826 | | var railElements = ['Rail', 'Buffer', 'Progress']; |
| 1827 | | |
| 1828 | | for (var i=0; i<railElements.length; i++) { |
| 1829 | | var element = _buildImage(name + "Slider" + railElements[i], null, true, (name=="volume")); |
| 1830 | | if (element) { |
| 1831 | | element.className += " jwstretch"; |
| 1832 | | rail.appendChild(element); |
| 1833 | | } |
| 1834 | | } |
| 1835 | | |
| 1836 | | var thumb = _buildImage(name + "SliderThumb"); |
| 1837 | | if (thumb) { |
| 1838 | | _css(_internalSelector('.'+thumb.className), { opacity: 0 }); |
| 1839 | | thumb.className += " jwthumb"; |
| 1840 | | rail.appendChild(thumb); |
| 1841 | | } |
| 1842 | | |
| 1843 | | rail.addEventListener('mousedown', _sliderMouseDown(name), false); |
| 1844 | | |
| 1845 | | _elements[name+'Rail'] = rail; |
| 1846 | | |
| 1847 | | return rail; |
| 1848 | | } |
| 1849 | | |
| 1850 | | function _idle() { |
| 1851 | | var currentState = _api.jwGetState(); |
| 1852 | | return (currentState == _states.IDLE || currentState == _states.COMPLETED); |
| 1853 | | } |
| 1854 | | |
| 1855 | | function _sliderMouseDown(name) { |
| 1856 | | return (function(evt) { |
| 1857 | | if (evt.button != 0) |
| 1858 | | return; |
| 1859 | | |
| 1860 | | _elements[name+'Rail'].className = "jwrail"; |
| 1861 | | |
| 1862 | | if (name == "time") { |
| 1863 | | if (!_idle()) { |
| 1864 | | _api.jwSeekDrag(true); |
| 1865 | | _dragging = name; |
| 1866 | | } |
| 1867 | | } else { |
| 1868 | | _dragging = name; |
| 1869 | | } |
| 1870 | | }); |
| 1871 | | } |
| 1872 | | |
| 1873 | | function _sliderMouseEvent(evt) { |
| 1874 | | if (!_dragging || evt.button != 0) { |
| 1875 | | return; |
| 1876 | | } |
| 1877 | | |
| 1878 | | var rail = _elements[_dragging].getElementsByClassName('jwrail')[0], |
| 1879 | | railRect = _utils.getBoundingClientRect(rail), |
| 1880 | | pct = (evt.clientX - railRect.left) / railRect.width; |
| 1881 | | |
| 1882 | | if (evt.type == 'mouseup') { |
| 1883 | | var name = _dragging; |
| 1884 | | |
| 1885 | | if (name == "time") { |
| 1886 | | _api.jwSeekDrag(false); |
| 1887 | | } |
| 1888 | | |
| 1889 | | _elements[name+'Rail'].className = "jwrail jwsmooth"; |
| 1890 | | _dragging = null; |
| 1891 | | _sliderMapping[name](pct); |
| 1892 | | } else { |
| 1893 | | if (_dragging == "time") { |
| 1894 | | _setProgress(pct); |
| 1895 | | } else { |
| 1896 | | _setVolume(pct); |
| 1897 | | } |
| 1898 | | var currentTime = (new Date()).getTime(); |
| 1899 | | if (currentTime - _lastSeekTime > 500) { |
| 1900 | | _lastSeekTime = currentTime; |
| 1901 | | _sliderMapping[_dragging](pct); |
| 1902 | | } |
| 1903 | | } |
| 1904 | | } |
| 1905 | | |
| 1906 | | |
| 1907 | | function _styleTimeSlider(slider) { |
| 1908 | | if (_elements['timeSliderThumb']) { |
| 1909 | | _css(_internalSelector(".jwtimeSliderThumb"), { |
| 1910 | | 'margin-left': (_getSkinElement("timeSliderThumb").width/-2) |
| 1911 | | }); |
| 1912 | | } |
| 1913 | | |
| 1914 | | _setBuffer(0); |
| 1915 | | _setProgress(0); |
| 1916 | | } |
| 1917 | | |
| 1918 | | |
| 1919 | | function _styleVolumeSlider(slider) { |
| 1920 | | var capLeftWidth = _getSkinElement("volumeSliderCapLeft").width, |
| 1921 | | capRightWidth = _getSkinElement("volumeSliderCapRight").width, |
| 1922 | | railWidth = _getSkinElement("volumeSliderRail").width; |
| 1923 | | |
| 1924 | | _css(_internalSelector(".jwvolume"), { |
| 1925 | | width: (capLeftWidth + railWidth + capRightWidth) |
| 1926 | | }); |
| 1927 | | } |
| 1928 | | |
| 1929 | | var _groups = {}; |
| 1930 | | |
| 1931 | | function _buildLayout() { |
| 1932 | | _buildGroup("left"); |
| 1933 | | _buildGroup("center"); |
| 1934 | | _buildGroup("right"); |
| 1935 | | _controlbar.appendChild(_groups.left); |
| 1936 | | _controlbar.appendChild(_groups.center); |
| 1937 | | _controlbar.appendChild(_groups.right); |
| 1938 | | |
| 1939 | | _css(_internalSelector(".jwright"), { |
| 1940 | | right: _getSkinElement("capRight").width |
| 1941 | | }); |
| 1942 | | } |
| 1943 | | |
| 1944 | | |
| 1945 | | function _buildGroup(pos) { |
| 1946 | | var elem = _createSpan(); |
| 1947 | | elem.className = "jwgroup jw" + pos; |
| 1948 | | _groups[pos] = elem; |
| 1949 | | if (_layout[pos]) { |
| 1950 | | _buildElements(_layout[pos], _groups[pos]); |
| 1951 | | } |
| 1952 | | } |
| 1953 | | |
| 1954 | | function _buildElements(group, container) { |
| 1955 | | if (group && group.elements.length > 0) { |
| 1956 | | for (var i=0; i<group.elements.length; i++) { |
| 1957 | | var element = _buildElement(group.elements[i]); |
| 1958 | | if (element) { |
| 1959 | | container.appendChild(element); |
| 1960 | | } |
| 1961 | | } |
| 1962 | | } |
| 1963 | | } |
| 1964 | | |
| 1965 | | var _resize = this.resize = function(width, height) { |
| 1966 | | _css(_internalSelector('.jwgroup.jwcenter'), { |
| 1967 | | left: Math.round(_utils.parseDimension(_groups.left.offsetWidth) + _getSkinElement("capLeft").width), |
| 1968 | | right: Math.round(_utils.parseDimension(_groups.right.offsetWidth) + _getSkinElement("capRight").width) |
| 1969 | | }); |
| 1970 | | } |
| 1971 | | |
| 1972 | | this.getDisplayElement = function() { |
| 1973 | | return _controlbar; |
| 1974 | | }; |
| 1975 | | |
| 1976 | | function _setBuffer(pct) { |
| 1977 | | pct = Math.min(Math.max(0, pct), 1); |
| 1978 | | //_css(_internalSelector('.jwtimeSliderBuffer'), { width: pct * 100 + "%" }); |
| 1979 | | if (_elements.timeSliderBuffer) { |
| 1980 | | _elements.timeSliderBuffer.style.width = pct * 100 + "%"; |
| 1981 | | } |
| 1982 | | } |
| 1983 | | |
| 1984 | | function _sliderPercent(name, pct, fixedWidth) { |
| 1985 | | var width = 100 * Math.min(Math.max(0, pct), 1) + "%"; |
| 1986 | | |
| 1987 | | //_css(_internalSelector(prefix+'Progress'), { width: width }); |
| 1988 | | //_css(_internalSelector(prefix+'Thumb'), { left: width }); |
| 1989 | | |
| 1990 | | // Set style directly on the elements; Using the stylesheets results in some flickering in Chrome. |
| 1991 | | if (_elements[name+'SliderProgress']) { |
| 1992 | | _elements[name+'SliderProgress'].style.width = width; |
| 1993 | | } |
| 1994 | | if (_elements[name+'SliderThumb']) { |
| 1995 | | _elements[name+'SliderThumb'].style.left = width; |
| 1996 | | } |
| 1997 | | } |
| 1998 | | |
| 1999 | | function _setVolume (pct) { |
| 2000 | | _sliderPercent('volume', pct, true); |
| 2001 | | } |
| 2002 | | |
| 2003 | | function _setProgress(pct) { |
| 2004 | | _sliderPercent('time', pct); |
| 2005 | | } |
| 2006 | | |
| 2007 | | function _getSkinElement(name) { |
| 2008 | | var elem = _skin.getSkinElement('controlbar', name); |
| 2009 | | if (elem) { |
| 2010 | | return elem; |
| 2011 | | } else { |
| 2012 | | return { |
| 2013 | | width: 0, |
| 2014 | | height: 0, |
| 2015 | | src: "", |
| 2016 | | image: undefined, |
| 2017 | | ready: false |
| 2018 | | } |
| 2019 | | } |
| 2020 | | } |
| 2021 | | |
| 2022 | | this.show = function() { |
| 2023 | | _css(_internalSelector(), { opacity: 1 }); |
| 2024 | | } |
| 2025 | | |
| 2026 | | this.hide = function() { |
| 2027 | | _css(_internalSelector(), { opacity: 0 }); |
| 2028 | | } |
| 2029 | | |
| 2030 | | // Call constructor |
| 2031 | | _init(); |
| 2032 | | |
| 2033 | | } |
| 2034 | | |
| 2035 | | /************************************************************* |
| 2036 | | * Player stylesheets - done once on script initialization; * |
| 2037 | | * These CSS rules are used for all JW Player instances * |
| 2038 | | *************************************************************/ |
| 2039 | | |
| 2040 | | _css(CB_CLASS, { |
| 2041 | | position: JW_CSS_ABSOLUTE, |
| 2042 | | overflow: 'hidden', |
| 2043 | | opacity: 0, |
| 2044 | | '-webkit-transition': JW_CSS_SMOOTH_EASE, |
| 2045 | | '-moz-transition': JW_CSS_SMOOTH_EASE, |
| 2046 | | '-o-transition': JW_CSS_SMOOTH_EASE |
| 2047 | | }) |
| 2048 | | |
| 2049 | | _css(CB_CLASS+' span',{ |
| 2050 | | height: JW_CSS_100PCT, |
| 2051 | | '-webkit-user-select': JW_CSS_NONE, |
| 2052 | | '-webkit-user-drag': JW_CSS_NONE, |
| 2053 | | 'user-select': JW_CSS_NONE, |
| 2054 | | 'user-drag': JW_CSS_NONE |
| 2055 | | }); |
| 2056 | | |
| 2057 | | _css(CB_CLASS+' .jwgroup', { |
| 2058 | | display: JW_CSS_INLINE |
| 2059 | | }); |
| 2060 | | |
| 2061 | | _css(CB_CLASS+' span, '+CB_CLASS+' .jwgroup button,'+CB_CLASS+' .jwleft', { |
| 2062 | | position: JW_CSS_RELATIVE, |
| 2063 | | 'float': JW_CSS_LEFT |
| 2064 | | }); |
| 2065 | | |
| 2066 | | _css(CB_CLASS+' .jwright', { |
| 2067 | | position: JW_CSS_ABSOLUTE |
| 2068 | | }); |
| 2069 | | |
| 2070 | | _css(CB_CLASS+' .jwcenter', { |
| 2071 | | position: JW_CSS_ABSOLUTE |
| 2072 | | }); |
| 2073 | | |
| 2074 | | _css(CB_CLASS+' button', { |
| 2075 | | display: JW_CSS_INLINE_BLOCK, |
| 2076 | | height: JW_CSS_100PCT, |
| 2077 | | border: JW_CSS_NONE, |
| 2078 | | cursor: 'pointer', |
| 2079 | | '-webkit-transition': JW_CSS_SMOOTH_EASE, |
| 2080 | | '-moz-transition': JW_CSS_SMOOTH_EASE, |
| 2081 | | '-o-transition': JW_CSS_SMOOTH_EASE |
| 2082 | | }); |
| 2083 | | |
| 2084 | | _css(CB_CLASS+' .jwcapRight', { |
| 2085 | | right: 0, |
| 2086 | | position: JW_CSS_ABSOLUTE |
| 2087 | | }); |
| 2088 | | |
| 2089 | | _css(CB_CLASS+' .jwtime,' + CB_CLASS + ' .jwgroup span.jwstretch', { |
| 2090 | | position: JW_CSS_ABSOLUTE, |
| 2091 | | height: JW_CSS_100PCT, |
| 2092 | | width: JW_CSS_100PCT, |
| 2093 | | left: 0 |
| 2094 | | }); |
| 2095 | | |
| 2096 | | |
| 2097 | | |
| 2098 | | _css(CB_CLASS+' .jwrail,' + CB_CLASS + ' .jwthumb', { |
| 2099 | | position: JW_CSS_ABSOLUTE, |
| 2100 | | height: JW_CSS_100PCT, |
| 2101 | | cursor: 'pointer' |
| 2102 | | }); |
| 2103 | | |
| 2104 | | _css(CB_CLASS + ' .jwtime .jwsmooth span', { |
| 2105 | | '-webkit-transition': JW_CSS_SMOOTH_EASE, |
| 2106 | | '-moz-transition': JW_CSS_SMOOTH_EASE, |
| 2107 | | '-o-transition': JW_CSS_SMOOTH_EASE |
| 2108 | | }); |
| 2109 | | |
| 2110 | | _css(CB_CLASS + ' .jwdivider+.jwdivider', { |
| 2111 | | display: JW_CSS_NONE |
| 2112 | | }); |
| 2113 | | |
| 2114 | | _css(CB_CLASS + ' .jwtext', { |
| 2115 | | padding: '0 5px', |
| 2116 | | 'text-align': 'center' |
| 2117 | | }); |
| 2118 | | |
| 2119 | | _css(CB_CLASS + ' .jwtoggling', { |
| 2120 | | '-webkit-transition': JW_CSS_NONE, |
| 2121 | | '-moz-transition': JW_CSS_NONE, |
| 2122 | | '-o-transition': JW_CSS_NONE |
| 2123 | | }); |
| 2124 | | |
| 2125 | | })(jwplayer);/** |
| 2126 | | * jwplayer.html5 API |
| 2127 | | * |
| 2128 | | * @author pablo |
| 2129 | | * @version 6.0 |
| 2130 | | */ |
| 2131 | | (function(html5) { |
| 2132 | | var _jw = jwplayer, |
| 2133 | | _utils = _jw.utils, |
| 2134 | | _events = _jw.events, |
| 2135 | | _states = _events.state; |
| 2136 | | |
| 2137 | | html5.controller = function(model, view) { |
| 2138 | | var _model = model, |
| 2139 | | _view = view, |
| 2140 | | _video = model.getVideo(), |
| 2141 | | _controller = this, |
| 2142 | | _eventDispatcher = new _events.eventdispatcher(_model.id, _model.config.debug); |
| 2143 | | |
| 2144 | | _utils.extend(this, _eventDispatcher); |
| 2145 | | |
| 2146 | | function _init() { |
| 2147 | | _model.addEventListener(_events.JWPLAYER_MEDIA_BUFFER_FULL, _bufferFullHandler); |
| 2148 | | _model.addEventListener(_events.JWPLAYER_MEDIA_COMPLETE, function(evt) { |
| 2149 | | // Insert a small delay here so that other complete handlers can execute |
| 2150 | | setTimeout(_completeHandler, 25); |
| 2151 | | }); |
| 2152 | | } |
| 2153 | | |
| 2154 | | function _playerReady(evt) { |
| 2155 | | _view.completeSetup(); |
| 2156 | | _eventDispatcher.sendEvent(evt.type, evt); |
| 2157 | | _eventDispatcher.sendEvent(jwplayer.events.JWPLAYER_PLAYLIST_LOADED, {playlist: _model.playlist}); |
| 2158 | | _eventDispatcher.sendEvent(jwplayer.events.JWPLAYER_PLAYLIST_ITEM, {index: _model.item}); |
| 2159 | | _model.addGlobalListener(_forward); |
| 2160 | | _load(); |
| 2161 | | if (_model.autostart && !_utils.isMobile()) { |
| 2162 | | _play(); |
| 2163 | | } |
| 2164 | | } |
| 2165 | | |
| 2166 | | function _forward(evt) { |
| 2167 | | _eventDispatcher.sendEvent(evt.type, evt); |
| 2168 | | } |
| 2169 | | |
| 2170 | | function _bufferFullHandler(evt) { |
| 2171 | | _video.play(); |
| 2172 | | } |
| 2173 | | |
| 2174 | | function _load(item) { |
| 2175 | | _stop(); |
| 2176 | | |
| 2177 | | switch (_utils.typeOf(item)) { |
| 2178 | | case "string": |
| 2179 | | _model.setPlaylist(new html5.playlist({file:item})); |
| 2180 | | _model.setItem(0); |
| 2181 | | break; |
| 2182 | | case "object": |
| 2183 | | case "array": |
| 2184 | | _model.setPlaylist(new html5.playlist(item)); |
| 2185 | | _model.setItem(0); |
| 2186 | | break; |
| 2187 | | case "number": |
| 2188 | | _model.setItem(item); |
| 2189 | | break; |
| 2190 | | } |
| 2191 | | } |
| 2192 | | |
| 2193 | | var _preplay, _actionOnAttach, _interruptPlay; |
| 2194 | | |
| 2195 | | function _play() { |
| 2196 | | try { |
| 2197 | | _actionOnAttach = _play; |
| 2198 | | if (!_preplay) { |
| 2199 | | _preplay = true; |
| 2200 | | _eventDispatcher.sendEvent(_events.JWPLAYER_MEDIA_BEFOREPLAY); |
| 2201 | | _preplay = false; |
| 2202 | | if (_interruptPlay) { |
| 2203 | | _interruptPlay = false; |
| 2204 | | _actionOnAttach = null; |
| 2205 | | return; |
| 2206 | | } |
| 2207 | | } |
| 2208 | | |
| 2209 | | if (_isIdle()) { |
| 2210 | | _video.load(_model.playlist[_model.item]); |
| 2211 | | } else if (_model.state == _states.PAUSED) { |
| 2212 | | _video.play(); |
| 2213 | | } |
| 2214 | | |
| 2215 | | return true; |
| 2216 | | } catch (err) { |
| 2217 | | _eventDispatcher.sendEvent(_events.JWPLAYER_ERROR, err); |
| 2218 | | _actionOnAttach = null; |
| 2219 | | } |
| 2220 | | return false; |
| 2221 | | } |
| 2222 | | |
| 2223 | | function _stop() { |
| 2224 | | _actionOnAttach = null; |
| 2225 | | try { |
| 2226 | | if (!_isIdle()) { |
| 2227 | | _video.stop(); |
| 2228 | | } |
| 2229 | | if (_preplay) { |
| 2230 | | _interruptPlay = true; |
| 2231 | | } |
| 2232 | | return true; |
| 2233 | | } catch (err) { |
| 2234 | | _eventDispatcher.sendEvent(_events.JWPLAYER_ERROR, err); |
| 2235 | | } |
| 2236 | | return false; |
| 2237 | | |
| 2238 | | } |
| 2239 | | |
| 2240 | | function _pause() { |
| 2241 | | try { |
| 2242 | | switch (_model.state) { |
| 2243 | | case _states.PLAYING: |
| 2244 | | case _states.BUFFERING: |
| 2245 | | _video.pause(); |
| 2246 | | break; |
| 2247 | | default: |
| 2248 | | if (_preplay) { |
| 2249 | | _interruptPlay = true; |
| 2250 | | } |
| 2251 | | } |
| 2252 | | return true; |
| 2253 | | } catch (err) { |
| 2254 | | _eventDispatcher.sendEvent(_events.JWPLAYER_ERROR, err); |
| 2255 | | } |
| 2256 | | return false; |
| 2257 | | |
| 2258 | | |
| 2259 | | if (_model.state == _states.PLAYING || _model.state == _states.BUFFERING) { |
| 2260 | | _video.pause(); |
| 2261 | | } |
| 2262 | | } |
| 2263 | | |
| 2264 | | function _isIdle() { |
| 2265 | | return (_model.state == _states.IDLE || _model.state == _states.COMPLETED); |
| 2266 | | } |
| 2267 | | |
| 2268 | | function _seek(pos) { |
| 2269 | | _video.seek(pos); |
| 2270 | | } |
| 2271 | | |
| 2272 | | function _setFullscreen(state) { |
| 2273 | | _view.fullscreen(state); |
| 2274 | | } |
| 2275 | | |
| 2276 | | function _setStretching(stretching) { |
| 2277 | | _model.stretching = stretching; |
| 2278 | | _view.resize(); |
| 2279 | | } |
| 2280 | | |
| 2281 | | function _item(index) { |
| 2282 | | _load(index); |
| 2283 | | _play(); |
| 2284 | | } |
| 2285 | | |
| 2286 | | function _prev() { |
| 2287 | | _item(_model.item - 1); |
| 2288 | | } |
| 2289 | | |
| 2290 | | function _next() { |
| 2291 | | _item(_model.item + 1); |
| 2292 | | } |
| 2293 | | |
| 2294 | | function _completeHandler() { |
| 2295 | | if (!_isIdle()) { |
| 2296 | | // Something has made an API call before the complete handler has fired. |
| 2297 | | return; |
| 2298 | | } |
| 2299 | | _actionOnAttach = _completeHandler; |
| 2300 | | switch (_model.repeat.toLowerCase()) { |
| 2301 | | case "single": |
| 2302 | | _play(); |
| 2303 | | break; |
| 2304 | | case "always": |
| 2305 | | _next(); |
| 2306 | | break; |
| 2307 | | case "list": |
| 2308 | | if (_model.item == _model.playlist.length - 1) { |
| 2309 | | _load(0); |
| 2310 | | _model.setState(_states.COMPLETED); |
| 2311 | | } else { |
| 2312 | | _next(); |
| 2313 | | } |
| 2314 | | break; |
| 2315 | | default: |
| 2316 | | _model.setState(_states.COMPLETED); |
| 2317 | | // _stop(); |
| 2318 | | break; |
| 2319 | | } |
| 2320 | | } |
| 2321 | | |
| 2322 | | |
| 2323 | | // TODO: implement waitForReady; either in Controller or in API |
| 2324 | | function _waitForReady(func) { |
| 2325 | | return function() { |
| 2326 | | func.apply(this, arguments); |
| 2327 | | } |
| 2328 | | } |
| 2329 | | |
| 2330 | | /** Used for the InStream API **/ |
| 2331 | | function _detachMedia() { |
| 2332 | | try { |
| 2333 | | return _model.getVideo().detachMedia(); |
| 2334 | | } catch (err) { |
| 2335 | | return null; |
| 2336 | | } |
| 2337 | | } |
| 2338 | | |
| 2339 | | function _attachMedia() { |
| 2340 | | try { |
| 2341 | | var ret = _model.getVideo().attachMedia(); |
| 2342 | | if (typeof _actionOnAttach == "function") { |
| 2343 | | _actionOnAttach(); |
| 2344 | | } |
| 2345 | | } catch (err) { |
| 2346 | | return null; |
| 2347 | | } |
| 2348 | | } |
| 2349 | | |
| 2350 | | /** Controller API / public methods **/ |
| 2351 | | this.play = _waitForReady(_play); |
| 2352 | | this.pause = _waitForReady(_pause); |
| 2353 | | this.seek = _waitForReady(_seek); |
| 2354 | | this.stop = _waitForReady(_stop); |
| 2355 | | this.load = _waitForReady(_load); |
| 2356 | | this.next = _waitForReady(_next); |
| 2357 | | this.prev = _waitForReady(_prev); |
| 2358 | | this.item = _waitForReady(_item); |
| 2359 | | this.setVolume = _waitForReady(_model.setVolume); |
| 2360 | | this.setMute = _waitForReady(_model.setMute); |
| 2361 | | this.setFullscreen = _waitForReady(_setFullscreen); |
| 2362 | | this.setStretching = _waitForReady(_setStretching); |
| 2363 | | this.detachMedia = _detachMedia; |
| 2364 | | this.attachMedia = _attachMedia; |
| 2365 | | |
| 2366 | | this.playerReady = _playerReady; |
| 2367 | | |
| 2368 | | _init(); |
| 2369 | | } |
| 2370 | | |
| 2371 | | })(jwplayer.html5); |
| 2372 | | |
| 2373 | | /** |
| 2374 | | * JW Player Default skin |
| 2375 | | * |
| | 1658 | * Internal plugin model |
| 2501 | | |
| 2502 | | _icons[iconName] = button; |
| 2503 | | } |
| 2504 | | } |
| 2505 | | } |
| 2506 | | |
| 2507 | | function _hoverButton(button) { |
| 2508 | | return function(evt) { |
| 2509 | | if (button.className.indexOf("jwhover") < 0) |
| 2510 | | button.className += " jwhover"; |
| 2511 | | if (button.childNodes[0].className.indexOf("jwhover") < 0) |
| 2512 | | button.childNodes[0].className += " jwhover"; |
| 2513 | | } |
| 2514 | | } |
| 2515 | | |
| 2516 | | function _hoverOutButton(button) { |
| 2517 | | return function(evt) { |
| 2518 | | button.className = button.className.replace(" jwhover", ""); |
| 2519 | | button.childNodes[0].className = button.childNodes[0].className.replace(" jwhover", ""); |
| 2520 | | } |
| 2521 | | } |
| 2522 | | |
| 2523 | | function _buttonStyle(selector, out, over) { |
| 2524 | | if (!(out && out.src)) { |
| 2525 | | return; |
| 2526 | | } |
| 2527 | | |
| 2528 | | _css(selector, { |
| 2529 | | width: out.width, |
| 2530 | | height: out.height, |
| 2531 | | 'margin-left': out.width / -2, |
| 2532 | | 'margin-top': out.height / -2, |
| 2533 | | background: 'url('+ out.src +') center no-repeat' |
| 2534 | | }); |
| 2535 | | |
| 2536 | | if (over && over.src) { |
| 2537 | | _css(selector + ".jwhover", { |
| 2538 | | background: 'url('+ over.src +') center no-repeat' |
| 2539 | | }); |
| 2540 | | } |
| 2541 | | } |
| 2542 | | |
| 2543 | | function _setIcon(name) { |
| 2544 | | if (!_config.showicons) return; |
| 2545 | | |
| 2546 | | if (_button) { |
| 2547 | | _display.removeChild(_button); |
| 2548 | | } |
| 2549 | | _button = _icons[name]; |
| 2550 | | if (_button) { |
| 2551 | | _display.appendChild(_button); |
| 2552 | | } |
| 2553 | | |
| 2554 | | if (name == "buffer") { |
| 2555 | | _degreesRotated = 0; |
| 2556 | | _rotationInterval = setInterval(function() { |
| 2557 | | _degreesRotated += _bufferRotation; |
| 2558 | | _rotate(_button.childNodes[0], _degreesRotated % 360); |
| 2559 | | }, _bufferInterval); |
| 2560 | | } |
| 2561 | | } |
| 2562 | | |
| 2563 | | function _itemHandler() { |
| 2564 | | var item = _api.jwGetPlaylist()[_api.jwGetPlaylistIndex()]; |
| 2565 | | var newImage = item ? item.image : ""; |
| 2566 | | if (_image != newImage) { |
| 2567 | | _image = newImage; |
| 2568 | | _setVisibility(D_PREVIEW_CLASS, false); |
| 2569 | | _getImage(); |
| 2570 | | } |
| 2571 | | } |
| 2572 | | |
| 2573 | | var _stateTimeout; |
| 2574 | | |
| 2575 | | function _stateHandler(evt) { |
| 2576 | | clearTimeout(_stateTimeout); |
| 2577 | | _stateTimeout = setTimeout(function() { |
| 2578 | | _updateDisplay(evt.newstate); |
| 2579 | | }, 100); |
| 2580 | | } |
| 2581 | | |
| 2582 | | function _updateDisplay(state) { |
| 2583 | | clearInterval(_rotationInterval); |
| 2584 | | |
| 2585 | | switch(state) { |
| 2586 | | case _states.COMPLETED: |
| 2587 | | case _states.IDLE: |
| 2588 | | _setIcon('play'); |
| 2589 | | _setVisibility(D_PREVIEW_CLASS, true); |
| 2590 | | break; |
| 2591 | | case _states.BUFFERING: |
| 2592 | | _setIcon('buffer'); |
| 2593 | | break; |
| 2594 | | case _states.PLAYING: |
| 2595 | | _setIcon(); |
| 2596 | | _setVisibility(D_PREVIEW_CLASS, false); |
| 2597 | | break; |
| 2598 | | case _states.PAUSED: |
| 2599 | | _setIcon('play'); |
| 2600 | | break; |
| 2601 | | } |
| 2602 | | } |
| 2603 | | |
| 2604 | | this.getDisplayElement = function() { |
| 2605 | | return _display; |
| 2606 | | } |
| 2607 | | |
| 2608 | | function _internalSelector(selector) { |
| 2609 | | return '#' + _display.id + ' ' + selector; |
| 2610 | | } |
| 2611 | | |
| 2612 | | function _getImage() { |
| 2613 | | if (_image) { |
| 2614 | | // Find image size and stretch exactfit if close enough |
| 2615 | | var img = new Image(); |
| 2616 | | img.addEventListener('load', function() { |
| 2617 | | _imageWidth = img.width; |
| 2618 | | _imageHeight = img.height; |
| 2619 | | _resize(); |
| 2620 | | _css(_internalSelector(D_PREVIEW_CLASS), { |
| 2621 | | 'background-image': _image ? ('url('+_image+')') : '', |
| 2622 | | }); |
| 2623 | | _setVisibility(D_PREVIEW_CLASS, true); |
| 2624 | | }, false); |
| 2625 | | img.src = _image; |
| 2626 | | } else { |
| 2627 | | _setVisibility(D_PREVIEW_CLASS, false); |
| 2628 | | _imageWidth = _imageHeight = 0; |
| 2629 | | } |
| 2630 | | } |
| 2631 | | |
| 2632 | | function _getSkinElement(name) { |
| 2633 | | var elem = _skin.getSkinElement('display', name); |
| 2634 | | if (elem) { |
| 2635 | | return elem; |
| 2636 | | } |
| 2637 | | return null; |
| 2638 | | } |
| 2639 | | |
| 2640 | | function _resize() { |
| 2641 | | _utils.stretch(_api.jwGetStretching(), _preview, _display.clientWidth, _display.clientHeight, _imageWidth, _imageHeight); |
| 2642 | | } |
| 2643 | | |
| 2644 | | this.resize = _resize; |
| 2645 | | |
| 2646 | | function _setVisibility(selector, state) { |
| 2647 | | _css(_internalSelector(selector), { |
| 2648 | | opacity: state ? 1 : 0 |
| 2649 | | }); |
| 2650 | | } |
| 2651 | | |
| 2652 | | this.show = function() { |
| 2653 | | _setVisibility('', true); |
| 2654 | | } |
| 2655 | | |
| 2656 | | this.hide = function() { |
| 2657 | | _setVisibility('', false); |
| 2658 | | } |
| 2659 | | |
| 2660 | | this.getBGColor = function() { |
| 2661 | | return _config.backgroundcolor; |
| 2662 | | } |
| 2663 | | |
| 2664 | | /** NOT SUPPORTED : Using this for now to hack around instream API **/ |
| 2665 | | this.setAlternateClickHandler = function(handler) { |
| 2666 | | _alternateClickHandler = handler; |
| 2667 | | } |
| 2668 | | this.revertAlternateClickHandler = function() { |
| 2669 | | _alternateClickHandler = undefined; |
| 2670 | | } |
| 2671 | | |
| 2672 | | _init(); |
| 2673 | | }; |
| 2674 | | |
| 2675 | | _css(D_CLASS, { |
| 2676 | | position: JW_CSS_ABSOLUTE, |
| 2677 | | cursor: "pointer", |
| 2678 | | width: JW_CSS_100PCT, |
| 2679 | | height: JW_CSS_100PCT, |
| 2680 | | overflow: 'hidden', |
| 2681 | | opacity: 0 |
| 2682 | | }); |
| 2683 | | |
| 2684 | | _css(D_CLASS + ' .jwpreview', { |
| 2685 | | position: JW_CSS_ABSOLUTE, |
| 2686 | | width: JW_CSS_100PCT, |
| 2687 | | height: JW_CSS_100PCT, |
| 2688 | | 'background-repeat': 'no-repeat', |
| 2689 | | 'background-position': 'center', |
| 2690 | | overflow: 'hidden' |
| 2691 | | }); |
| 2692 | | |
| 2693 | | _css(D_CLASS +', '+D_CLASS + ' *', { |
| 2694 | | '-webkit-transition': JW_CSS_SMOOTH_EASE, |
| 2695 | | '-moz-transition': JW_CSS_SMOOTH_EASE, |
| 2696 | | '-o-transition': JW_CSS_SMOOTH_EASE |
| 2697 | | }); |
| 2698 | | |
| 2699 | | _css(D_CLASS+' button, ' + D_CLASS+' .jwicon', { |
| 2700 | | border: JW_CSS_NONE, |
| 2701 | | position: JW_CSS_ABSOLUTE, |
| 2702 | | left: "50%", |
| 2703 | | top: "50%", |
| 2704 | | padding: 0, |
| 2705 | | cursor: 'pointer' |
| 2706 | | }); |
| 2707 | | |
| 2708 | | })(jwplayer.html5);/** |
| 2709 | | * API to control instream playback without interrupting currently playing video |
| 2710 | | * |
| 2711 | | * @author pablo |
| 2712 | | * @version 6.0 |
| 2713 | | */ |
| 2714 | | (function(html5) { |
| 2715 | | var _jw = jwplayer, |
| 2716 | | _utils = _jw.utils, |
| 2717 | | _events = _jw.events, |
| 2718 | | _states = _events.state; |
| 2719 | | |
| 2720 | | html5.instream = function(api, model, view, controller) { |
| 2721 | | var _defaultOptions = { |
| 2722 | | controlbarseekable:"always", |
| 2723 | | controlbarpausable:true, |
| 2724 | | controlbarstoppable:true, |
| 2725 | | playlistclickable:true |
| 2726 | | }; |
| 2727 | | |
| 2728 | | var _item, |
| 2729 | | _options, |
| 2730 | | _api=api, _model=model, _view=view, _controller=controller, |
| 2731 | | _video, _oldsrc, _oldsources, _oldpos, _oldstate, _olditem, |
| 2732 | | _provider, _cbar, _disp, _instreamMode = false, |
| 2733 | | _dispatcher, _instreamContainer, |
| 2734 | | _self = this; |
| 2735 | | |
| 2736 | | |
| 2737 | | /***************************************** |
| 2738 | | ***** Public instream API methods ***** |
| 2739 | | *****************************************/ |
| 2740 | | |
| 2741 | | /** Load an instream item and initialize playback **/ |
| 2742 | | this.load = function(item, options) { |
| 2743 | | // Update the instream player's model |
| 2744 | | _copyModel(); |
| 2745 | | // Sets internal instream mode to true |
| 2746 | | _instreamMode = true; |
| 2747 | | // Instream playback options |
| 2748 | | _options = _utils.extend(_defaultOptions, options); |
| 2749 | | // Copy the playlist item passed in and make sure it's formatted as a proper playlist item |
| 2750 | | _item = html5.playlistitem(item); |
| 2751 | | // Create (or reuse) video media provider. No checks right now to make sure it's a valid playlist item (i.e. provider="video"). |
| 2752 | | _setupProvider(); |
| 2753 | | // Create the container in which the controls will be placed |
| 2754 | | _instreamContainer = document.createElement("div"); |
| 2755 | | _instreamContainer.id = _self.id + "_instream_container"; |
| 2756 | | // Make sure the original player's provider stops broadcasting events (pseudo-lock...) |
| 2757 | | _controller.detachMedia(); |
| 2758 | | // Get the video tag |
| 2759 | | _video = _provider.getTag(); |
| 2760 | | // Store this to compare later (in case the main player switches to the next playlist item when we switch out of instream playback mode |
| 2761 | | _olditem = _model.playlist[_model.item]; |
| 2762 | | // Keep track of the original player state |
| 2763 | | _oldstate = _api.jwGetState(); |
| 2764 | | // If the player's currently playing, pause the video tag |
| 2765 | | if (_oldstate == _states.BUFFERING || _oldstate == _states.PLAYING) { |
| 2766 | | _video.pause(); |
| 2767 | | } |
| 2768 | | |
| 2769 | | // Copy the video src/sources tags and store the current playback time |
| 2770 | | _oldsrc = _video.src ? _video.src : _video.currentSrc; |
| 2771 | | _oldsources = _video.innerHTML; |
| 2772 | | _oldpos = _video.currentTime; |
| 2773 | | |
| 2774 | | // Instream display component |
| 2775 | | _disp = new html5.display(_self); |
| 2776 | | _disp.setAlternateClickHandler(function(evt) { |
| 2777 | | if (_fakemodel.state == _states.PAUSED) { |
| 2778 | | _self.jwInstreamPlay(); |
| 2779 | | } else { |
| 2780 | | _sendEvent(_events.JWPLAYER_INSTREAM_CLICK, evt); |
| 2781 | | } |
| 2782 | | }); |
| 2783 | | _instreamContainer.appendChild(_disp.getDisplayElement()); |
| 2784 | | |
| 2785 | | // Instream controlbar (if not iOS/Android) |
| 2786 | | if (!_utils.isMobile()) { |
| 2787 | | // _cbar = new html5.controlbar(_self, _utils.extend({},_model.plugins.config.controlbar, {})); |
| 2788 | | _cbar = new html5.controlbar(_self); |
| 2789 | | // if (_model.plugins.config.controlbar.position == html5.view.positions.OVER) { |
| 2790 | | _instreamContainer.appendChild(_cbar.getDisplayElement()); |
| 2791 | | // } else { |
| 2792 | | // var cbarParent = _model.plugins.object.controlbar.getDisplayElement().parentNode; |
| 2793 | | // cbarParent.appendChild(_cbar.getDisplayElement()); |
| 2794 | | // } |
| 2795 | | } |
| 2796 | | |
| 2797 | | // Show the instream layer |
| 2798 | | _view.setupInstream(_instreamContainer, _video); |
| 2799 | | // Resize the instream components to the proper size |
| 2800 | | _resize(); |
| 2801 | | // Load the instream item |
| 2802 | | _provider.load(_item); |
| 2803 | | |
| 2804 | | } |
| 2805 | | |
| 2806 | | /** Stop the instream playback and revert the main player back to its original state **/ |
| 2807 | | this.jwInstreamDestroy = function(complete) { |
| 2808 | | if (!_instreamMode) return; |
| 2809 | | // We're not in instream mode anymore. |
| 2810 | | _instreamMode = false; |
| 2811 | | if (_oldstate != _states.IDLE) { |
| 2812 | | // Load the original item into our provider, which sets up the regular player's video tag |
| 2813 | | _provider.load(_olditem, false); |
| 2814 | | // We don't want the position interval to be running anymore |
| 2815 | | //_provider.stop(false); |
| 2816 | | } else { |
| 2817 | | _provider.stop(true); |
| 2818 | | } |
| 2819 | | // We don't want the instream provider to be attached to the video tag anymore |
| 2820 | | _provider.detachMedia(); |
| 2821 | | // Return the view to its normal state |
| 2822 | | _view.destroyInstream(); |
| 2823 | | // If we added the controlbar anywhere, let's get rid of it |
| 2824 | | if (_cbar) try { _cbar.getDisplayElement().parentNode.removeChild(_cbar.getDisplayElement()); } catch(e) {} |
| 2825 | | // Let listeners know the instream player has been destroyed, and why |
| 2826 | | _sendEvent(_events.JWPLAYER_INSTREAM_DESTROYED, {reason:(complete ? "complete":"destroyed")}, true); |
| 2827 | | // Re-attach the controller |
| 2828 | | _controller.attachMedia(); |
| 2829 | | if (_oldstate == _states.BUFFERING || _oldstate == _states.PLAYING) { |
| 2830 | | // Model was already correct; just resume playback |
| 2831 | | _video.play(); |
| 2832 | | if (_model.playlist[_model.item] == _olditem) { |
| 2833 | | // We need to seek using the player's real provider, since the seek may have to be delayed |
| 2834 | | //_model.getMedia().seek(_oldpos); |
| 2835 | | _model.getVideo().seek(_oldpos); |
| 2836 | | } |
| 2837 | | } |
| 2838 | | return; |
| 2839 | | }; |
| 2840 | | |
| 2841 | | /** Forward any calls to add and remove events directly to our event dispatcher **/ |
| 2842 | | this.jwInstreamAddEventListener = function(type, listener) { |
| 2843 | | _dispatcher.addEventListener(type, listener); |
| 2844 | | } |
| 2845 | | this.jwInstreamRemoveEventListener = function(type, listener) { |
| 2846 | | _dispatcher.removeEventListener(type, listener); |
| 2847 | | } |
| 2848 | | |
| 2849 | | /** Start instream playback **/ |
| 2850 | | this.jwInstreamPlay = function() { |
| 2851 | | if (!_instreamMode) return; |
| 2852 | | _provider.play(true); |
| 2853 | | } |
| 2854 | | |
| 2855 | | /** Pause instream playback **/ |
| 2856 | | this.jwInstreamPause = function() { |
| 2857 | | if (!_instreamMode) return; |
| 2858 | | _provider.pause(true); |
| 2859 | | } |
| 2860 | | |
| 2861 | | /** Seek to a point in instream media **/ |
| 2862 | | this.jwInstreamSeek = function(position) { |
| 2863 | | if (!_instreamMode) return; |
| 2864 | | _provider.seek(position); |
| 2865 | | } |
| 2866 | | |
| 2867 | | /** Get the current instream state **/ |
| 2868 | | this.jwInstreamGetState = function() { |
| 2869 | | if (!_instreamMode) return undefined; |
| 2870 | | return _fakemodel.state; |
| 2871 | | } |
| 2872 | | |
| 2873 | | /** Get the current instream playback position **/ |
| 2874 | | this.jwInstreamGetPosition = function() { |
| 2875 | | if (!_instreamMode) return undefined; |
| 2876 | | return _fakemodel.position; |
| 2877 | | } |
| 2878 | | |
| 2879 | | /** Get the current instream media duration **/ |
| 2880 | | this.jwInstreamGetDuration = function() { |
| 2881 | | if (!_instreamMode) return undefined; |
| 2882 | | return _fakemodel.duration; |
| 2883 | | } |
| 2884 | | |
| 2885 | | this.playlistClickable = function() { |
| 2886 | | return (!_instreamMode || _options.playlistclickable.toString().toLowerCase()=="true"); |
| 2887 | | } |
| 2888 | | |
| 2889 | | |
| 2890 | | /***************************** |
| 2891 | | ****** Private methods ****** |
| 2892 | | *****************************/ |
| 2893 | | |
| 2894 | | function _init() { |
| 2895 | | // Initialize the instream player's model copied from main player's model |
| 2896 | | //_fakemodel = new html5.model(this, _model.getMedia() ? _model.getMedia().getDisplayElement() : _model.container, _model); |
| 2897 | | _fakemodel = new html5.model({}); |
| 2898 | | // Create new event dispatcher |
| 2899 | | _dispatcher = new _events.eventdispatcher(); |
| 2900 | | // Listen for player resize events |
| 2901 | | _api.jwAddEventListener(_events.JWPLAYER_RESIZE, _resize); |
| 2902 | | _api.jwAddEventListener(_events.JWPLAYER_FULLSCREEN, _resize); |
| 2903 | | } |
| 2904 | | |
| 2905 | | function _copyModel() { |
| 2906 | | _controller.setMute(_model.mute); |
| 2907 | | _controller.setVolume(_model.volume); |
| 2908 | | } |
| 2909 | | |
| 2910 | | function _setupProvider() { |
| 2911 | | if (!_provider) { |
| 2912 | | // _provider = new html5.mediavideo(_fakemodel, _model.getMedia() ? _model.getMedia().getDisplayElement() : _model.container); |
| 2913 | | _provider = new html5.video(_model.getVideo().getTag()); |
| 2914 | | _provider.addGlobalListener(_forward); |
| 2915 | | _provider.addEventListener(_events.JWPLAYER_MEDIA_META, _metaHandler); |
| 2916 | | _provider.addEventListener(_events.JWPLAYER_MEDIA_COMPLETE, _completeHandler); |
| 2917 | | _provider.addEventListener(_events.JWPLAYER_MEDIA_BUFFER_FULL, _bufferFullHandler); |
| 2918 | | } |
| 2919 | | _provider.attachMedia(); |
| 2920 | | } |
| 2921 | | |
| 2922 | | /** Forward provider events to listeners **/ |
| 2923 | | function _forward(evt) { |
| 2924 | | if (_instreamMode) { |
| 2925 | | _sendEvent(evt.type, evt); |
| 2926 | | } |
| 2927 | | } |
| 2928 | | |
| 2929 | | /** Handle the JWPLAYER_MEDIA_BUFFER_FULL event **/ |
| 2930 | | function _bufferFullHandler(evt) { |
| 2931 | | if (_instreamMode) { |
| 2932 | | _provider.play(); |
| 2933 | | } |
| 2934 | | } |
| 2935 | | |
| 2936 | | /** Handle the JWPLAYER_MEDIA_COMPLETE event **/ |
| 2937 | | function _completeHandler(evt) { |
| 2938 | | if (_instreamMode) { |
| 2939 | | setTimeout(function() { |
| 2940 | | _self.jwInstreamDestroy(true); |
| 2941 | | }, 10); |
| 2942 | | } |
| 2943 | | } |
| 2944 | | |
| 2945 | | /** Handle the JWPLAYER_MEDIA_META event **/ |
| 2946 | | function _metaHandler(evt) { |
| 2947 | | // If we're getting video dimension metadata from the provider, allow the view to resize the media |
| 2948 | | if (evt.metadata.width && evt.metadata.height) { |
| 2949 | | _view.resizeMedia(); |
| 2950 | | } |
| 2951 | | } |
| 2952 | | |
| 2953 | | function _sendEvent(type, data, forceSend) { |
| 2954 | | if (_instreamMode || forceSend) { |
| 2955 | | _dispatcher.sendEvent(type, data); |
| 2956 | | } |
| 2957 | | } |
| 2958 | | |
| 2959 | | // Resize handler; resize the components. |
| 2960 | | function _resize() { |
| 2961 | | // var originalDisp = _model.plugins.object.display.getDisplayElement().style; |
| 2962 | | // |
| 2963 | | if (_cbar) { |
| 2964 | | // var originalBar = _model.plugins.object.controlbar.getDisplayElement().style; |
| 2965 | | _cbar.resize(); |
| 2966 | | //_cbar.resize(_utils.parseDimension(originalDisp.width), _utils.parseDimension(originalDisp.height)); |
| 2967 | | // _css(_cbar.getDisplayElement(), _utils.extend({}, originalBar, { zIndex: 1001, opacity: 1 })); |
| 2968 | | } |
| 2969 | | if (_disp) { |
| 2970 | | // |
| 2971 | | // _disp.resize(_utils.parseDimension(originalDisp.width), _utils.parseDimension(originalDisp.height)); |
| 2972 | | _disp.resize(); |
| 2973 | | // _css(_disp.getDisplayElement(), _utils.extend({}, originalDisp, { zIndex: 1000 })); |
| 2974 | | } |
| 2975 | | // if (_view) { |
| 2976 | | // _view.resizeMedia(); |
| 2977 | | // } |
| 2978 | | } |
| 2979 | | |
| 2980 | | |
| 2981 | | /************************************** |
| 2982 | | ***** Duplicate main html5 api ***** |
| 2983 | | **************************************/ |
| 2984 | | |
| 2985 | | this.jwPlay = function(state) { |
| 2986 | | if (_options.controlbarpausable.toString().toLowerCase()=="true") { |
| 2987 | | this.jwInstreamPlay(); |
| 2988 | | } |
| 2989 | | }; |
| 2990 | | |
| 2991 | | this.jwPause = function(state) { |
| 2992 | | if (_options.controlbarpausable.toString().toLowerCase()=="true") { |
| 2993 | | this.jwInstreamPause(); |
| 2994 | | } |
| 2995 | | }; |
| 2996 | | |
| 2997 | | this.jwStop = function() { |
| 2998 | | if (_options.controlbarstoppable.toString().toLowerCase()=="true") { |
| 2999 | | this.jwInstreamDestroy(); |
| 3000 | | _api.jwStop(); |
| 3001 | | } |
| 3002 | | }; |
| 3003 | | |
| 3004 | | this.jwSeek = function(position) { |
| 3005 | | switch(_options.controlbarseekable.toLowerCase()) { |
| 3006 | | case "always": |
| 3007 | | this.jwInstreamSeek(position); |
| 3008 | | break; |
| 3009 | | case "backwards": |
| 3010 | | if (_fakemodel.position > position) { |
| 3011 | | this.jwInstreamSeek(position); |
| 3012 | | } |
| 3013 | | break; |
| 3014 | | } |
| 3015 | | }; |
| 3016 | | |
| 3017 | | this.jwGetPosition = function() {}; |
| 3018 | | this.jwGetDuration = function() {}; |
| 3019 | | this.jwGetWidth = _api.jwGetWidth; |
| 3020 | | this.jwGetHeight = _api.jwGetHeight; |
| 3021 | | this.jwGetFullscreen = _api.jwGetFullscreen; |
| 3022 | | this.jwSetFullscreen = _api.jwSetFullscreen; |
| 3023 | | this.jwGetVolume = function() { return _model.volume; }; |
| 3024 | | this.jwSetVolume = function(vol) { |
| 3025 | | _provider.volume(vol); |
| 3026 | | _api.jwSetVolume(vol); |
| 3027 | | } |
| 3028 | | this.jwGetMute = function() { return _model.mute; }; |
| 3029 | | this.jwSetMute = function(state) { |
| 3030 | | _provider.mute(state); |
| 3031 | | _api.jwSetMute(state); |
| 3032 | | } |
| 3033 | | this.jwGetState = function() { return _fakemodel.state; }; |
| 3034 | | this.jwGetPlaylist = function() { return [_item]; }; |
| 3035 | | this.jwGetPlaylistIndex = function() { return 0; }; |
| 3036 | | this.jwGetStretching = function() { return _model.config.stretching; }; |
| 3037 | | this.jwAddEventListener = function(type, handler) { _dispatcher.addEventListener(type, handler); }; |
| 3038 | | this.jwRemoveEventListener = function(type, handler) { _dispatcher.removeEventListener(type, handler); }; |
| 3039 | | |
| 3040 | | this.skin = _api.skin; |
| 3041 | | this.id = _api.id + "_instream"; |
| 3042 | | |
| 3043 | | _init(); |
| 3044 | | return this; |
| 3045 | | }; |
| 3046 | | })(jwplayer.html5); |
| 3047 | | |
| 3048 | | /** |
| 3049 | | * jwplayer.html5 model |
| 3050 | | * |
| 3051 | | * @author pablo |
| 3052 | | * @version 6.0 |
| 3053 | | */ |
| 3054 | | (function(html5) { |
| 3055 | | var _utils = jwplayer.utils, |
| 3056 | | _events = jwplayer.events, |
| 3057 | | UNDEF = undefined; |
| 3058 | | |
| 3059 | | html5.model = function(config) { |
| 3060 | | var _model = this, |
| 3061 | | // Video provider |
| 3062 | | _video, |
| 3063 | | // HTML5 <video> tag |
| 3064 | | _videoTag, |
| 3065 | | // Saved settings |
| 3066 | | _cookies = _utils.getCookies(), |
| 3067 | | // Sub-component configurations |
| 3068 | | _componentConfigs = {}; |
| 3069 | | // Defaults |
| 3070 | | _defaults = { |
| 3071 | | autostart: false, |
| 3072 | | controls: true, |
| 3073 | | debug: UNDEF, |
| 3074 | | height: 320, |
| 3075 | | icons: true, |
| 3076 | | item: 0, |
| 3077 | | mute: false, |
| 3078 | | playlist: [], |
| 3079 | | playlistposition: "right", |
| 3080 | | playlistsize: 0, |
| 3081 | | repeat: "list", |
| 3082 | | skin: UNDEF, |
| 3083 | | stretching: _utils.stretching.UNIFORM, |
| 3084 | | volume: 90, |
| 3085 | | width: 480 |
| | 1841 | } |
| | 1842 | |
| | 1843 | if (incomplete == 0) { |
| | 1844 | _complete(); |
| | 1845 | } |
| | 1846 | } |
| | 1847 | } |
| | 1848 | |
| | 1849 | this.setupPlugins = function(api, config, resizer) { |
| | 1850 | var flashPlugins = { |
| | 1851 | length: 0, |
| | 1852 | plugins: {} |
| 3334 | | })(jwplayer.html5); |
| 3335 | | /** |
| 3336 | | * jwplayer Playlist component for the JW Player. |
| 3337 | | * |
| 3338 | | * @author pablo |
| 3339 | | * @version 6.0 |
| 3340 | | */ |
| 3341 | | (function(html5) { |
| 3342 | | var _defaults = { |
| 3343 | | size: 180, |
| 3344 | | //position: html5.view.positions.NONE, |
| 3345 | | itemheight: 60, |
| 3346 | | thumbs: true, |
| 3347 | | |
| 3348 | | fontcolor: "#000000", |
| 3349 | | overcolor: "", |
| 3350 | | activecolor: "", |
| 3351 | | backgroundcolor: "#f8f8f8", |
| 3352 | | font: "_sans", |
| 3353 | | fontsize: "", |
| 3354 | | fontstyle: "", |
| 3355 | | fontweight: "" |
| 3356 | | }, |
| 3357 | | |
| 3358 | | _fonts = { |
| 3359 | | '_sans': "Arial, Helvetica, sans-serif", |
| 3360 | | '_serif': "Times, Times New Roman, serif", |
| 3361 | | '_typewriter': "Courier New, Courier, monospace" |
| 3362 | | }, |
| 3363 | | |
| 3364 | | _utils = jwplayer.utils, |
| 3365 | | _css = _utils.css, |
| 3366 | | _events = jwplayer.events, |
| 3367 | | |
| 3368 | | PL_CLASS = '.jwplaylist', |
| 3369 | | DOCUMENT = document, |
| 3370 | | |
| 3371 | | /** Some CSS constants we should use for minimization **/ |
| 3372 | | JW_CSS_ABSOLUTE = "absolute", |
| 3373 | | JW_CSS_NONE = "none", |
| 3374 | | JW_CSS_100PCT = "100%"; |
| 3375 | | |
| 3376 | | html5.playlistcomponent = function(api, config) { |
| 3377 | | var _api = api, |
| 3378 | | _skin = _api.skin, |
| 3379 | | _settings = _utils.extend({}, _defaults, _api.skin.getComponentSettings("playlist"), config), |
| 3380 | | _wrapper, |
| 3381 | | _width, |
| 3382 | | _height, |
| 3383 | | _playlist, |
| 3384 | | _items, |
| 3385 | | _ul, |
| 3386 | | _lastCurrent = -1, |
| 3387 | | _elements = { |
| 3388 | | 'background': undefined, |
| 3389 | | 'item': undefined, |
| 3390 | | 'itemOver': undefined, |
| 3391 | | 'itemImage': undefined, |
| 3392 | | 'itemActive': undefined |
| 3393 | | }; |
| 3394 | | |
| 3395 | | this.getDisplayElement = function() { |
| 3396 | | return _wrapper; |
| 3397 | | }; |
| 3398 | | |
| 3399 | | this.resize = function(width, height) { |
| 3400 | | _width = width; |
| 3401 | | _height = height; |
| 3402 | | }; |
| 3403 | | |
| 3404 | | this.show = function() { |
| 3405 | | _show(_wrapper); |
| 3406 | | } |
| 3407 | | |
| 3408 | | this.hide = function() { |
| 3409 | | _hide(_wrapper); |
| 3410 | | } |
| 3411 | | |
| 3412 | | |
| 3413 | | function _setup() { |
| 3414 | | _wrapper = _createElement("div", "jwplaylist"); |
| 3415 | | _wrapper.id = _api.id + "_jwplayer_playlistcomponent"; |
| 3416 | | _populateSkinElements(); |
| 3417 | | if (_elements.item) { |
| 3418 | | _settings.itemheight = _elements.item.height; |
| 3419 | | } |
| 3420 | | |
| 3421 | | _setupStyles(); |
| 3422 | | |
| 3423 | | _api.jwAddEventListener(jwplayer.events.JWPLAYER_PLAYLIST_LOADED, _rebuildPlaylist); |
| 3424 | | _api.jwAddEventListener(jwplayer.events.JWPLAYER_PLAYLIST_ITEM, _itemHandler); |
| 3425 | | } |
| 3426 | | |
| 3427 | | function _internalSelector(className) { |
| 3428 | | return '#' + _wrapper.id + (className ? ' .' + className : ""); |
| 3429 | | } |
| 3430 | | |
| 3431 | | function _setupStyles() { |
| 3432 | | var imgPos = 0, imgWidth = 0, imgHeight = 0, |
| 3433 | | itemheight = _settings.itemheight, |
| 3434 | | fontsize = _settings.fontsize |
| 3435 | | |
| 3436 | | _utils.clearCss(_internalSelector()); |
| 3437 | | |
| 3438 | | _css(_internalSelector("jwlist"), { |
| 3439 | | 'background-color': _settings.backgroundcolor, |
| 3440 | | 'background-image': _elements.background ? "url("+_elements.background.src+")" : "", |
| 3441 | | color: _settings.fontcolor, |
| 3442 | | 'font-family': _fonts[_settings.font] ? _fonts[_settings.font] : _fonts['_sans'], |
| 3443 | | 'font-size': (fontsize ? fontsize : 11) + "px", |
| 3444 | | 'font-style': _settings.fontstyle, |
| 3445 | | 'font-weight': _settings.fontweight |
| 3446 | | }); |
| 3447 | | |
| 3448 | | if (_elements.itemImage) { |
| 3449 | | imgPos = (itemheight - _elements.itemImage.height) / 2; |
| 3450 | | imgWidth = _elements.itemImage.width; |
| 3451 | | imgHeight = _elements.itemImage.height; |
| 3452 | | } else { |
| 3453 | | imgWidth = itemheight * 4 / 3; |
| 3454 | | imgHeight = itemheight |
| 3455 | | } |
| 3456 | | |
| 3457 | | _css(_internalSelector("jwplaylistimg"), { |
| 3458 | | height: imgHeight, |
| 3459 | | width: imgWidth, |
| 3460 | | margin: imgPos |
| 3461 | | }); |
| 3462 | | |
| 3463 | | _css(_internalSelector("jwlist li"), { |
| 3464 | | 'background-image': _elements.item ? "url("+_elements.item.src+")" : "", |
| 3465 | | height: itemheight, |
| 3466 | | 'background-size': JW_CSS_100PCT + " " + itemheight + "px" |
| 3467 | | }); |
| 3468 | | |
| 3469 | | var activeStyle = { overflow: 'hidden' }; |
| 3470 | | if (_settings.activecolor !== "") activeStyle.color = _settings.activecolor; |
| 3471 | | if (_elements.itemActive) activeStyle['background-image'] = "url("+_elements.itemActive.src+")"; |
| 3472 | | _css(_internalSelector("jwlist li.active"), activeStyle); |
| 3473 | | |
| 3474 | | var overStyle = { overflow: 'hidden' }; |
| 3475 | | if (_settings.overcolor !== "") overStyle.color = _settings.overcolor; |
| 3476 | | if (_elements.itemOver) overStyle['background-image'] = "url("+_elements.itemOver.src+")"; |
| 3477 | | _css(_internalSelector("jwlist li:hover"), overStyle); |
| 3478 | | |
| 3479 | | |
| 3480 | | _css(_internalSelector("jwtextwrapper"), { |
| 3481 | | padding: "5px 5px 0 " + (imgPos ? 0 : "5px"), |
| 3482 | | height: itemheight - 5, |
| 3483 | | position: "relative" |
| 3484 | | }); |
| 3485 | | |
| 3486 | | _css(_internalSelector("jwtitle"), { |
| 3487 | | height: fontsize ? fontsize + 10 : 20, |
| 3488 | | 'line-height': fontsize ? fontsize + 10 : 20, |
| 3489 | | overflow: 'hidden', |
| 3490 | | display: "inline-block", |
| 3491 | | width: JW_CSS_100PCT, |
| 3492 | | 'font-size': fontsize ? fontsize : 13, |
| 3493 | | 'font-weight': _settings.fontweight ? _settings.fontweight : "bold" |
| 3494 | | }); |
| 3495 | | |
| 3496 | | _css(_internalSelector("jwdescription"), { |
| 3497 | | display: 'block', |
| 3498 | | 'line-height': fontsize ? fontsize + 4 : 16, |
| 3499 | | overflow: 'hidden', |
| 3500 | | height: itemheight, |
| 3501 | | position: "relative" |
| 3502 | | }); |
| 3503 | | |
| 3504 | | _css(_internalSelector("jwduration"), { |
| 3505 | | position: "absolute", |
| 3506 | | right: 5 |
| 3507 | | }); |
| 3508 | | } |
| 3509 | | |
| 3510 | | function _createList() { |
| 3511 | | var ul = _createElement("ul", "jwlist"); |
| 3512 | | ul.id = _wrapper.id + "_ul" + Math.round(Math.random()*10000000); |
| 3513 | | return ul; |
| 3514 | | } |
| 3515 | | |
| 3516 | | |
| 3517 | | function _createItem(index) { |
| 3518 | | var item = _playlist[index], |
| 3519 | | li = _createElement("li", "jwitem"); |
| 3520 | | |
| 3521 | | li.id = _ul.id + '_item_' + index; |
| 3522 | | |
| 3523 | | _css(li,{ |
| 3524 | | height: _settings.itemheight, |
| 3525 | | display: 'block', |
| 3526 | | cursor: 'pointer', |
| 3527 | | backgroundImage: _elements.item ? "url("+_elements.item.src+")" : "", |
| 3528 | | backgroundSize: "100% " + _settings.itemheight + "px" |
| 3529 | | }); |
| 3530 | | |
| 3531 | | var imageWrapper = _createElement("div", "jwplaylistimg jwfill"); |
| 3532 | | |
| 3533 | | if (_showThumbs() && (item.image || item['playlist.image'] || _elements.itemImage) ) { |
| 3534 | | var imageSrc; |
| 3535 | | if (item['playlist.image']) { |
| 3536 | | imageSrc = item['playlist.image']; |
| 3537 | | } else if (item.image) { |
| 3538 | | imageSrc = item.image; |
| 3539 | | } else if (_elements.itemImage) { |
| 3540 | | imageSrc = _elements.itemImage.src; |
| 3541 | | } |
| 3542 | | |
| 3543 | | _css('#'+li.id+' .jwplaylistimg', { |
| 3544 | | 'background-image': imageSrc ? 'url('+imageSrc+')': null |
| 3545 | | }); |
| 3546 | | |
| 3547 | | _appendChild(li, imageWrapper); |
| 3548 | | } |
| 3549 | | |
| 3550 | | var textWrapper = _createElement("div", "jwtextwrapper"); |
| 3551 | | var title = _createElement("span", "jwtitle"); |
| 3552 | | title.innerHTML = item ? item.title : ""; |
| 3553 | | _appendChild(textWrapper, title); |
| 3554 | | |
| 3555 | | if (item.description) { |
| 3556 | | var desc = _createElement("span", "jwdescription"); |
| 3557 | | desc.innerHTML = item.description; |
| 3558 | | _appendChild(textWrapper, desc); |
| 3559 | | } |
| 3560 | | |
| 3561 | | if (item.duration > 0) { |
| 3562 | | var dur = _createElement("span", "jwduration"); |
| 3563 | | dur.innerHTML = _utils.timeFormat(item.duration); |
| 3564 | | _appendChild(title, dur); |
| 3565 | | } |
| 3566 | | |
| 3567 | | _appendChild(li, textWrapper); |
| 3568 | | return li; |
| 3569 | | } |
| 3570 | | |
| 3571 | | function _createElement(type, className) { |
| 3572 | | var elem = DOCUMENT.createElement(type); |
| 3573 | | if (className) elem.className = className; |
| 3574 | | return elem; |
| 3575 | | } |
| 3576 | | |
| 3577 | | function _appendChild(parent, child) { |
| 3578 | | parent.appendChild(child); |
| 3579 | | } |
| 3580 | | |
| 3581 | | function _rebuildPlaylist(evt) { |
| 3582 | | _wrapper.innerHTML = ""; |
| 3583 | | |
| 3584 | | _playlist = _getPlaylist(); |
| 3585 | | if (!_playlist) { |
| 3586 | | return; |
| 3587 | | } |
| 3588 | | items = []; |
| 3589 | | _ul = _createList(); |
| 3590 | | |
| 3591 | | for (var i=0; i<_playlist.length; i++) { |
| 3592 | | var li = _createItem(i); |
| 3593 | | li.onclick = _clickHandler(i); |
| 3594 | | _appendChild(_ul, li); |
| 3595 | | items.push(li); |
| 3596 | | } |
| 3597 | | |
| 3598 | | _lastCurrent = _api.jwGetPlaylistIndex(); |
| 3599 | | |
| 3600 | | _appendChild(_wrapper, _ul); |
| 3601 | | |
| 3602 | | if (_utils.isIOS() && window.iScroll) { |
| 3603 | | _ul.style.height = _settings.itemheight * _playlist.length + "px"; |
| 3604 | | var myscroll = new iScroll(_wrapper.id); |
| 3605 | | } |
| 3606 | | |
| 3607 | | } |
| 3608 | | |
| 3609 | | function _getPlaylist() { |
| 3610 | | var list = _api.jwGetPlaylist(); |
| 3611 | | var strippedList = []; |
| 3612 | | for (var i=0; i<list.length; i++) { |
| 3613 | | if (!list[i]['ova.hidden']) { |
| 3614 | | strippedList.push(list[i]); |
| 3615 | | } |
| 3616 | | } |
| 3617 | | return strippedList; |
| 3618 | | } |
| 3619 | | |
| 3620 | | function _clickHandler(index) { |
| 3621 | | return function() { |
| 3622 | | _api.jwPlaylistItem(index); |
| 3623 | | _api.jwPlay(true); |
| 3624 | | } |
| 3625 | | } |
| 3626 | | |
| 3627 | | function _scrollToItem() { |
| 3628 | | _ul.scrollTop = _api.jwGetPlaylistIndex() * _settings.itemheight; |
| 3629 | | } |
| 3630 | | |
| 3631 | | function _showThumbs() { |
| 3632 | | return _settings.thumbs.toString().toLowerCase() == "true"; |
| 3633 | | } |
| 3634 | | |
| 3635 | | function _itemHandler(evt) { |
| 3636 | | if (_lastCurrent >= 0) { |
| 3637 | | DOCUMENT.getElementById(_ul.id + '_item_' + _lastCurrent).className = "jwitem"; |
| 3638 | | _lastCurrent = evt.index; |
| 3639 | | } |
| 3640 | | DOCUMENT.getElementById(_ul.id + '_item_' + evt.index).className = "jwitem active"; |
| 3641 | | _scrollToItem(); |
| 3642 | | } |
| 3643 | | |
| 3644 | | |
| 3645 | | function _populateSkinElements() { |
| 3646 | | for (var i in _elements) { |
| 3647 | | _elements[i] = _getElement(i); |
| 3648 | | } |
| 3649 | | } |
| 3650 | | |
| 3651 | | function _getElement(name) { |
| 3652 | | return _skin.getSkinElement("playlist", name); |
| 3653 | | } |
| 3654 | | |
| 3655 | | _setup(); |
| 3656 | | return this; |
| 3657 | | }; |
| 3658 | | |
| 3659 | | /** Global playlist styles **/ |
| 3660 | | |
| 3661 | | _css(PL_CLASS, { |
| 3662 | | overflow: 'hidden', |
| 3663 | | position: 'absolute', |
| 3664 | | width: JW_CSS_100PCT, |
| 3665 | | height: JW_CSS_100PCT |
| 3666 | | }); |
| 3667 | | |
| 3668 | | _css(PL_CLASS + ' .jwplaylistimg', { |
| 3669 | | position: "relative", |
| 3670 | | width: JW_CSS_100PCT, |
| 3671 | | 'float': 'left', |
| 3672 | | margin: '0 5px 0 0', |
| 3673 | | background: 'black', |
| 3674 | | overflow: 'hidden' |
| 3675 | | }); |
| 3676 | | |
| 3677 | | _css(PL_CLASS+' .jwlist', { |
| 3678 | | width: JW_CSS_100PCT, |
| 3679 | | height: JW_CSS_100PCT, |
| 3680 | | 'list-style': 'none', |
| 3681 | | margin: 0, |
| 3682 | | padding: 0, |
| 3683 | | 'overflow-y': 'auto' |
| 3684 | | }); |
| 3685 | | |
| 3686 | | _css(PL_CLASS+' .jwlist li', { |
| 3687 | | width: JW_CSS_100PCT |
| 3688 | | }); |
| 3689 | | |
| 3690 | | _css(PL_CLASS+' .jwtextwrapper', { |
| 3691 | | overflow: "hidden" |
| 3692 | | }); |
| 3693 | | |
| 3694 | | |
| 3695 | | })(jwplayer.html5); |
| | 1939 | })(jwplayer); |