未捕获的TypeError:undefined不是player.getCurrentTime()的函数;

时间:2015-02-19 05:36:44

标签: javascript youtube youtube-api

我正在开发一个YouTube章节播放器,并尝试使用上述功能突出显示当前播放章节。我正在使用getCurrentTime()功能获取YouTube视频的当前播放时间,并且我在player.getCurrentTime()功能上遇到控制台错误:

Uncaught TypeError: undefined is not a function for player.getCurrentTime();

如何解决此错误?

相关代码:

var values = [];
var contentDiv, chapterEl, parentEl;
var chapters = {};
var index;

function loadplayer(youtubeId){

$(document).ready(function() {
    $.ajax({
        type: "GET",
        url: "ChapterVideo.xml",
        dataType: "xml",
        success: function(xml) {

            $(xml).find("video[id='" + youtubeId + "'] chapter").each(function() {
                var sTitle = $(this).find('name').text();                   
                var sValue = parseFloat($(this).find('time').text());

                values.push([sTitle, sValue]);

            });
            chapterplayer(values);

        },
        error: function() {
            alert("An error occurred while processing XML file.");
        }
    });
});

function chapterplayer(values) {

    for (index = 0; index < values.length; ++index) {
        chapters[values[index][1]] = '<span style="display: inline-block; width: 88%; margin-top: 1.5%;">' + values[index][0] + '</span>';
    }
    //chapters[times] = '<span style="display: inline-block; width: 88%; margin-top: 1.5%;">' + names + '</span>';
    // BEGIN_INCLUDE(namespace)
    window.ChapterMarkerPlayer = { 
        // Inserts a new YouTube iframe player and chapter markers as a child of an
        // existing HTML element on a page.
        insert: function(params) {
            // END_INCLUDE(namespace)
            // We need to reserve 30px for the player's control bar when automatically sizing the player.
            var YOUTUBE_CONTROLS_HEIGHT = 30;
            // Assume a 9:16 (width:height) ratio when we need to calculate a player's height.
            var PLAYER_HEIGHT_TO_WIDTH_RATIO = 11 / 16;
            var DEFAULT_PLAYER_WIDTH = 400;
            // BEGIN_INCLUDE(validation1)
            // params contains the following required and optional parameter names and values:
            //   videoId: (required) The YouTube video id of the video to be embedded.
            //   chapters: (required) Mapping of times (seconds since the video's start) to chapter titles.
            //   width: (optional) The width of the embedded player. 400px is used by default.
            //   playerOptions: (optional) An object corresponding to the options that can be passed to the
            //                  YT.Player constructor. See https://developers.google.com/youtube/iframe_api_reference#Loading_a_Video_Player
            if (!('videoId' in params)) {
                throw 'The "videoId" parameter must be set to the YouTube video id to be embedded.';
            }
            if (!('chapters' in params)) {
                throw 'The "chapters" parameter must be set to the mapping of times to chapter titles.';
            }
            // END_INCLUDE(validation1)
            // BEGIN_INCLUDE(time_sort)
            var times = [];
            for (var time in params.chapters) {
                if (params.chapters.hasOwnProperty(time)) {
                    times.push(time);
                }
            }
            // Sort the times numerically for display purposes.
            // See https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/sort#Examples
            times.sort(function(a, b) {
                return a - b;
            });
            // END_INCLUDE(time_sort)
            var width = params.width || DEFAULT_PLAYER_WIDTH;
            if ('YT' in window && 'Player' in window.YT) {
                // If the iframe player API is already available, proceed to loading the player using the API.
                insertPlayerAndAddChapterMarkers(params);
            } else {
                // Load the API, and add a callback to the queue to load the player once the API is available.
                if (!('onYouTubePlayerAPIReady' in window)) {
                    // BEGIN_INCLUDE(invoke_callbacks)
                    window.onYouTubePlayerAPIReady = function() {
                        for (var i = 0; i < window.ChapterMarkerPlayer.onYouTubePlayerAPIReadyCallbacks.length; i++) {
                            window.ChapterMarkerPlayer.onYouTubePlayerAPIReadyCallbacks[i]();
                        }
                    };
                    // END_INCLUDE(invoke_callbacks)
                    // BEGIN_INCLUDE(load_api)
                    // Dynamic <script> tag insertion will effectively load the iframe Player API on demand.
                    // We only want to do this once, so it's protected by the
                    // !('onYouTubePlayerAPIReady' in window) check.
                    var scriptTag = document.createElement('script');
                    // This scheme-relative URL will use HTTPS if the host page is accessed via HTTPS,
                    // and HTTP otherwise.
                    scriptTag.src = 'https://www.youtube.com/player_api';
                    var firstScriptTag = document.getElementsByTagName('script')[0];
                    firstScriptTag.parentNode.insertBefore(scriptTag, firstScriptTag);
                    // END_INCLUDE(load_api)
                }
                // BEGIN_INCLUDE(queue_callbacks)
                // We need to handle the situation where multiple ChapterMarkerPlayer.insert() calls are made
                // before the YT.Player API is loaded. We do this by maintaining an array of functions, each
                // of which adds a specific player and chapters. The functions will be executed when
                // onYouTubePlayerAPIReady() is invoked by the YT.Player API.
                window.ChapterMarkerPlayer.onYouTubePlayerAPIReadyCallbacks.push(function() {
                    insertPlayerAndAddChapterMarkers(params);
                });
                // END_INCLUDE(queue_callbacks)
            }
            // BEGIN_INCLUDE(load_player)
            // Calls the YT.Player constructor with the appropriate options to add the iframe player
            // instance to a parent element.
            // This is a private method that isn't exposed via the ChapterMarkerPlayer namespace.
            function initializePlayer(containerElement, params) {
                    var playerContainer = document.createElement('div');
                    containerElement.appendChild(playerContainer);
                    // Attempt to use any custom player options that were passed in via params.playerOptions.
                    // Fall back to reasonable defaults as needed.
                    var playerOptions = params.playerOptions || {};
                    return new YT.Player(playerContainer, {
                        // Maintain a 16:9 aspect ratio for the player based on the width passed in via params.
                        // Override can be done via params.playerOptions if needed
                        height: playerOptions.height || width * PLAYER_HEIGHT_TO_WIDTH_RATIO + YOUTUBE_CONTROLS_HEIGHT,
                        width: playerOptions.width || width,
                        // Unless playerVars are explicitly provided, use a reasonable default of { autohide: 1 },
                        // which hides the controls when the mouse isn't over the player.
                        playerVars: playerOptions.playerVars || {
                            autohide: 1
                        },
                        videoId: params.videoId,
                        events: {
                            onReady: playerOptions.onReady,
                            onStateChange: playerOptions.onStateChange,
                            onPlaybackQualityChange: playerOptions.onPlaybackQualityChange,
                            onError: playerOptions.onError
                        }
                    });
                }
                // END_INCLUDE(load_player)
                // BEGIN_INCLUDE(format_timestamp)
                // Takes a number of seconds and returns a #h##m##s string.

            function formatTimestamp(timestamp) {
                    var hours = Math.floor(timestamp / 3600);
                    var minutes = Math.floor((timestamp - (hours * 3600)) / 60);
                    var seconds = timestamp % 60;
                    var formattedTimestamp = (seconds < 10 ? '0' : '') + seconds;
                    if (minutes == 0) {
                        formattedTimestamp = "00:" + formattedTimestamp;
                    }
                    if (minutes > 0) {
                        formattedTimestamp = (minutes < 10 ? '0' : '') + minutes + ':' + formattedTimestamp;
                    }
                    if (hours > 0) {
                        formattedTimestamp = hours + 'h' + formattedTimestamp;
                    }
                    return formattedTimestamp;
                }
                // END_INCLUDE(format_timestamp)
                // BEGIN_INCLUDE(add_chapter_markers)
                // Adds a sorted list of chapters below the player. Each chapter has an onclick handler that
                // calls the iframe player API to seek to a specific timestamp in the video.
                // This is a private method that isn't exposed via the ChapterMarkerPlayer namespace.

            function hightlightChapters(player) {

            }

            function addChapterMarkers(containerElement, player) {

                    // Initialize chapter markers for highlight
                    var active = 'background:url(http://www.russell.com/resources/images/play_btn_active.png) #5d5e5e no-repeat 3% center; color: #FFF;';
                    var ol = document.createElement('ol');
                    ol.setAttribute('class', 'chapter-list');
                    ol.setAttribute('style', 'width: ' + width + 'px');
                    containerElement.appendChild(ol);
                    contentDiv = document.querySelector('.content-detail');
                    parentEl = contentDiv.parentElement;
                    chapterEl = parentEl.querySelector('.chapter-list');
                    parentEl.insertBefore(contentDiv, chapterEl);

                    for (var i = 0; i < times.length; i++) {
                        var time = times[i];
                        var chapterTitle = params.chapters[time];
                        var liElements = document.getElementsByTagName('li'),
                            x;
                        var li = document.createElement('li');
                        li.setAttribute('data-time', time);
                        li.innerHTML = chapterTitle + "<span style='float: right; margin-top: 1.5%;'>" + formatTimestamp(time) + "</span>";
                        li.setAttribute('id', time);

                        //player.playVideo();

                        setInterval(function() {

                            var curtime = player.getCurrentTime();

                            document.getElementById('timer').innerHTML = player.getCurrentTime();       

                            for (index = 0; index < values.length; ++index) {

                                if (curtime > values[index][1] && curtime < values[index+1][1]) {

                                    //remove all the in-line styles from the elements
                                    for (x = 0; x < liElements.length; x++) {
                                        liElements[x].setAttribute('style', '');
                                    };
                                    document.getElementById(values[index][1]).setAttribute("style", active);

                                }else if (curtime > values[values.length-1][1]) {

                                    //remove all the in-line styles from the elements
                                    for (x = 0; x < liElements.length; x++) {
                                        liElements[x].setAttribute('style', '');
                                    };
                                    document.getElementById(values[values.length-1][1]).setAttribute("style", active);

                                }
                            }
                        }, 1000); //polling frequency in miliseconds

                        li.onclick = function() {   

                            player.playVideo(); 

                            // 'this' will refer to the element that was clicked
                            //get the ID of the clicked element 
                            document.getElementById('timer').innerHTML = player.getCurrentTime();           
                            var chapId = this.getAttribute('id');

                            //player.playVideo();
                                //remove all the in-line styles from the elements
                            for (x = 0; x < liElements.length; x++) {
                                liElements[x].setAttribute('style', '');
                            };
                            var d = document.getElementById(chapId);
                            d.setAttribute("style", active);
                            player.seekTo(this.getAttribute('id'));
                        };
                        ol.appendChild(li);
                    }
                }
                // END_INCLUDE(add_chapter_markers)s
                // Convenience method to call both initializePlayer and addChapterMarkers.
                // This is a private method that isn't exposed via the ChapterMarkerPlayer namespace.

            function insertPlayerAndAddChapterMarkers(params) {
                // BEGIN_INCLUDE(validation2)
                var containerElement = document.getElementById(params.container);
                if (!containerElement) {
                    throw 'The "container" parameter must be set to the id of a existing HTML element.';
                }
                // END_INCLUDE(validation2)
                var player = initializePlayer(containerElement, params);
                addChapterMarkers(containerElement, player);
                console.log(player);
            }
        },
        // BEGIN_INCLUDE(callback_array)
        // This is used to keep track of the callback functions that need to be invoked when the iframe
        // API has been loaded. It avoids a race condition that would lead to issues if multiple
        // ChapterMarkerPlayer.insert() calls are made before the API is available.
        onYouTubePlayerAPIReadyCallbacks: []
            // END_INCLUDE(callback_array)
    }
    ChapterMarkerPlayer.insert({
        container: 'captions-session-player',
        videoId: youtubeId + '?wmode=opaque&theme=light&autohide=0&modestbranding=1&rel=0&autoplay=0',
        width: 469,
        chapters: chapters
    });

    //values.length=0;
}

}

控制台日志结果

    chapter_marker_player.js:220 X {j: rb, d: iframe#widget2, t: div, closure_uid_350236415: 1, L: 1…}
    chapter_marker_player.js:220 X {j: rb, d: iframe#widget2, t: div, closure_uid_350236415: 1, L: 1…}
    chapter_marker_player.js:220 X {j: rb, d: iframe#widget2, t: div, closure_uid_350236415: 1, L: 1…}
    chapter_marker_player.js:220 X {j: rb, d: iframe#widget2, t: div, closure_uid_350236415: 1, L: 1…}
    chapter_marker_player.js:220 X {j: rb, d: iframe#widget2, t: div, closure_uid_350236415: 1, L: 1…}
    chapter_marker_player.js:220 X {j: rb, d: iframe#widget2, t: div, closure_uid_350236415: 1, L: 1…}
    chapter_marker_player.js:220 X {j: rb, d: iframe#widget2, t: div, closure_uid_350236415: 1, L: 1…}
    chapter_marker_player.js:220 X {j: rb, d: iframe#widget2, t: div, closure_uid_350236415: 1, L: 1…}
    chapter_marker_player.js:220 X {j: rb, d: iframe#widget2, t: div, closure_uid_350236415: 1, L: 1…}
    chapter_marker_player.js:220 X {j: rb, d: iframe#widget2, t: div, closure_uid_350236415: 1, L: 1…}
    chapter_marker_player.js:220 X {j: rb, d: iframe#widget2, t: div, closure_uid_350236415: 1, L: 1…}
    53 chapter_marker_player.js:223 Uncaught TypeError: undefined is not a function

0 个答案:

没有答案