player/js/player.js
author veltr
Thu, 27 Jun 2013 15:04:31 +0200
changeset 74 0405878fde82
parent 71 af98a6dc9381
child 80 c587eca9152e
permissions -rwxr-xr-x
Slideshow fixes

IriSP.player = function(url) {

var myDir = new IriSP.Model.Directory(),
    myProject = myDir.remoteSource({
            url: url,
            serializer: IriSP.serializers.ldt
        });

myProject.onLoad(function() {
    
    $(".project-title").text(myProject.title);
    
    var myMedia = myProject.getCurrentMedia();
    
    IriSP.htmlPlayer(
        myMedia,
        $(".video-container"),
        {
            autostart: true,
            url_transform: function(src) {
                return [{
                    type: "video/mp4",
                    src: src.replace(/\.[\d\w]+$/,'.mp4')
                }, {
                    type: "video/webm",
                    src: src.replace(/\.[\d\w]+$/,'.webm')
                }];
            }
        }
    );
    
    function preventRightClick(selector) {
        selector.on("contextmenu", function() {
            return false;
        });
    }
    
    preventRightClick($(".video-container video"));
        
    $(".media-duration").text(myMedia.duration);
    
    myMedia.on("timeupdate", function(t) {
        var pos = (100 * t / myMedia.duration) + "%";
        $(".media-position").text(t);
        $(".progress-indicator").css("left",pos);
        $(".elapsed").css("width", pos);
    });
    myMedia.on("play", function() {
        $(".play-button").addClass("pause");
    });
    myMedia.on("pause", function() {
        $(".play-button").removeClass("pause");
    });
    
    function showAtMousePos(evt) {
        var pos = evt.pageX - $(".timeline").offset().left;
        $(".mouse-progress-indicator").css("left", pos);
        var t = new IriSP.Model.Time(pos * myMedia.duration / $(".timeline").width());
        $(".time-at-mouse").text(t);
        return t;
    }
    
    $(".timeline").mouseenter(function(e) {
        $(".mouse-progress-indicator").show();
        showAtMousePos(e);
    }).mouseleave(function(e) {
        $(".mouse-progress-indicator").hide();
    }).mousemove(showAtMousePos)
    .click(function(e) {
        myMedia.setCurrentTime( showAtMousePos(e) );
    });
    
    var tags = myProject.getTags().sortBy(function(t) {
            return - t.getRelated("annotation").length;
        }).slice(0,20).sortBy(function(t) {
            return t.title;
        }),
        tagTemplate = _.template('<li data-tag-id="<%- id %>" class="tag"><%- title %></li>'),
        clickedTag = null,
        lastTag = null;
    
    $(".tags-list").html(tags.map(tagTemplate).join(""));
    
    $(".tags-title").mouseenter(function() {
        $(".tags-list").stop().slideDown();
    }).click(function() {
        if (clickedTag) {
            clickedTag = null;
            showTag(null);
        }
        return false;
    });
    $(".tags").mouseleave(function() {
        $(".tags-list").stop().slideUp();
    });
    
    function showTag(tagId) {
        $(".found").removeClass("found");
        var tag = myProject.getElement(tagId);
        if (tag) {
            $("body").addClass("searching");
            $(".tags-title").text(tag.title);
            tag.getRelated("annotation").forEach(function(a) {
                a.trigger("found-tags");
            });
            $(".tag[data-tag-id="+tagId+"]").addClass("found");
        } else {
            $("body").removeClass("searching");
            $(".tags-title").text("Mots-clés");
        }
        lastTag = tagId;
    }
    
    $(".tag").hover(function() {
        showTag($(this).attr("data-tag-id"));
    }, function() {
        showTag(clickedTag);
    }).click(function() {
        var tag = $(this).attr("data-tag-id");
        if (clickedTag === tag) {
            clickedTag = null;
        } else {
            clickedTag = tag;
        }
        showTag(clickedTag);
        return false;
    });
    
    
    var chapters = myProject.getAnnotationsByTypeTitle("chapitrage"),
        chapterTemplate = _.template(
            '<li class="chapter" style="left: <%- 100*begin/getMedia().duration %>%; width: <%- 100*getDuration()/getMedia().duration %>%;">'
            + '<div class="chapter-block"></div><div class="chapter-title"><%- title %></div></li>'
        ),
        chapterList = $(".chapters-list"),
        hoveredChapter = null,
        currentChapter = null,
        currentChapterI = 0,
        slideInterval;
    
    function highlightChapter() {
        $(".chapter").removeClass("active");
        if (hoveredChapter || currentChapter) {
            (hoveredChapter || currentChapter).addClass("active");
        }
    }
    
    chapters.forEach(function(chapter, i) {
        var element = $(chapterTemplate(chapter));
        element.click(function() {
           myMedia.setCurrentTime(chapter.begin); 
           return false;
        }).hover(function() {
            hoveredChapter = element;
            highlightChapter();
        }, function() {
            hoveredChapter = null;
            highlightChapter();
        });
        chapter.on("enter", function() {
            currentChapter = element;
            currentChapterI = i;
            if (i) {
                $(".prev-chapter").removeClass("inactive");
            } else {
                $(".prev-chapter").addClass("inactive");
            }
            if (i < chapters.length - 1) {
                $(".next-chapter").removeClass("inactive");
            } else {
                $(".next-chapter").addClass("inactive");
            }
            highlightChapter();
        });
        chapter.on("leave", function() {
            currentChapter = null;
            highlightChapter();
        });
        chapter.on("found-tags", function() {
            element.addClass("found");
        });
        chapterList.append(element);
    });
    
    $(".prev-chapter").click(function() {
        if (currentChapterI) {
            myMedia.setCurrentTime(chapters[currentChapterI - 1].begin);
        }
        return false;
    });
    $(".next-chapter").click(function() {
        if (currentChapterI < chapters.length - 1) {
            myMedia.setCurrentTime(chapters[currentChapterI + 1].begin);
        }
        return false;
    });
    
    $(".play-button").click(function() {
        if (myMedia.paused) {
            myMedia.play();
        } else {
            myMedia.pause();
        }
        return false;
    });
        
    var pictoTemplate = _.template(
        '<li class="<%- type %>"><span class="picto"><a href="#"></a></span>'
        + '<span class="picto-title"><%- annotation.title %></span></li>'
    );
    
    var chipTemplate = _.template(
        '<li class="chip <%- type %><%- left %>" style="left: <%- pos %>%"><div class="chip-circle">'
        + '</div><div class="chip-pole"></div><div class="chip-title"><%- annotation.title %></div></li>'
    );
    
    var annotations = myProject.getAnnotationsByTypeTitle("annotations").sortBy(function(a) {
        return a.begin;
    });
    
    var annotationinfos = annotations.map(function(annotation) {
        var annotationinfo = {
            annotation: annotation,
            open: false,
            pos: 100 * annotation.begin / annotation.getMedia().duration
        };
        annotationinfo.left = (annotationinfo.pos > 80 ? " left": "");
        switch(annotation.content.mimetype) {
            case "application/x-ldt-slideshow":
                annotationinfo.type = "slideshow";
            break;
            case "application/x-ldt-video":
                annotationinfo.type = "video";
            break;
            case "application/x-ldt-audio":
                annotationinfo.type = "audio";
            break;
            case "application/x-ldt-links":
                annotationinfo.type = "link";
            break;
            default:
                annotationinfo.type = "text";
        }
        annotationinfo.picto = $(pictoTemplate(annotationinfo)).appendTo(".pictolist");
        annotationinfo.chip = $(chipTemplate(annotationinfo)).appendTo(".chips-list");
        annotationinfo.both = annotationinfo.picto.add(annotationinfo.chip);
        annotationinfo.both.click(function() {
                openAnnotation(annotationinfo);
                return false;
            })
            .hover(function() {
                annotationinfo.both.addClass("hover");
            }, function() {
                annotationinfo.both.removeClass("hover");
            });
        annotation.on("enter", function() {
            annotationinfo.picto.show().animate({
                height: "38px",
                opacity: 1
            }, 800);
        });
        annotation.on("leave", function() {
            annotationinfo.picto.animate({
                height: 0,
                opacity: 0
            }, 800, function() {
                annotationinfo.picto.hide();
            });
        });
        annotation.on("found-tags", function() {
            annotationinfo.both.addClass("found");
        });
        return annotationinfo;
    });
    
    currentAnnotation = null;
    
    function openAnnotation(annotationinfo) {
        
        if (currentAnnotation === annotationinfo) {
            closeAnnotation(true);
            return;
        }
        
        if (myMedia.currentTime < annotationinfo.annotation.begin || myMedia.currentTime > annotationinfo.annotation.end) {
            myMedia.setCurrentTime(annotationinfo.annotation.begin);
        }
        
        myMedia.pause();
        closeAnnotation(false);
        
        currentAnnotation = annotationinfo;
        
        annotationinfo.both.addClass("current");
        
        $(".timelines").addClass("annotation-onscreen");
        
        var annotationDiv = $(".annotation-templates ." + annotationinfo.type + "-annotation").clone();
        
        annotationDiv.appendTo($(".main-video"));
        annotationDiv.find(".close-annotation").click(closeAnnotation);
        annotationDiv.find(".annotation-title").text(annotationinfo.annotation.title);
        
        annotationinfo.positionDiv = function() {
            var mainH = $(".main-video").height()
            switch (annotationinfo.type) {
                case "video":
                    var mediaW = annotationDiv.find(".media-frame").width(),
                        mediaH = Math.floor(Math.min(mainH - 70, mediaW * 9 / 16));
                    annotationDiv.find("iframe, video").attr({
                        width: mediaW,
                        height: mediaH
                    });
                    annotationDiv.find(".media-description").css({
                       height: mediaH 
                    });
                break;
                case "text":
                    annotationDiv.find(".text-contents").css({
                        "max-height": mainH - 140
                    });
                break;
            }
            annotationDiv.css({
                top: Math.floor((mainH - annotationDiv.height())/2)+"px"
            });
        }
        
        switch (annotationinfo.type) {
            
            case "slideshow":
                
                var currentslide = 0,
                    playing = false,
                    loaded = false,
                    currentSlideLoaded = false,
                    slides = annotationinfo.annotation.content.images;
                
                var showCurrentImage = function() {
                    $(".slideshow-image").remove();
                    var slide = slides[currentslide],
                        srcimg = slide.image,
                        imgel = $("<img>");
                    imgel.addClass("slideshow-image");
                    var wcont = 650, hcont = 452, wsrc = srcimg.width, hsrc = srcimg.height, scale = Math.min(1, Math.min(wcont/wsrc, hcont/hsrc)), h = hsrc * scale;
                    imgel.attr({
                        src: srcimg.src,
                        title: slide.title,
                        alt: slide.title,
                        width: wsrc * scale,
                        height: h
                    });
                    imgel.css({
                        opacity: 0,
                        "margin-top": (h < hcont ? Math.floor((hcont-h)/2)+"px": 0)
                    });
                    annotationDiv.find(".slideshow-frame").prepend(imgel);
                    annotationDiv.find(".slideshow-title").text(slide.title);
                    annotationDiv.find(".slideshow-description").html(
                        slide.description.split(/\n/gm).map(function(l) {
                            return '<p>' + _.escape(l) + '</p>';
                        }).join("")
                    );
                    imgel.fadeTo(400, 1);
                    preventRightClick(imgel);
                }
                
                var nextImage = function() {
                    currentslide = (currentslide + 1) % slides.length;
                    annotationDiv.find(".slideshow-image").fadeTo(400, 0, showCurrentImage);
                    return false;
                }
                
                var togglePlay = function() {
                    playing = !playing;
                    clearInterval(slideInterval);
                    if (playing) {
                        slideInterval = setInterval(nextImage,Math.max(1000,annotationinfo.annotation.content.slideduration || 0));
                        annotationDiv.find(".slideshow-play-pause").addClass("pause");
                    } else {
                        annotationDiv.find(".slideshow-play-pause").removeClass("pause");
                    }
                    return false;
                }
                
                var checkloaded = function() {
                    if (loaded) {
                        return;
                    }
                    if (!currentSlideLoaded) {
                        if (!!slides[currentslide].image && !!slides[currentslide].image.height) {
                            currentSlideLoaded = true;
                            showCurrentImage();
                        }
                    }
                    loaded = slides.reduce(function(mem, slide) {
                        return (mem && !!slide.image && !!slide.image.height);
                    }, true);
                    if (loaded) {
                        if (annotationinfo.annotation.content.autostart && slides.length > 1) {
                            togglePlay();
                        }
                    }
                }
                
                slides.forEach(function(slide) {
                    slide.image = new Image();
                    slide.image.onload = checkloaded;
                    slide.image.src = slide.url + "?maxwidth=650&maxheight=452";
                });
                
                checkloaded();
                
                if (slides.length > 1) {
                    annotationDiv.find(".slideshow-next").click(function() {
                        if (playing) {
                            playing = false;
                            togglePlay();
                        }
                        nextImage();
                    });
                    annotationDiv.find(".slideshow-previous").click(function() {
                        if (playing) {
                            playing = false;
                            togglePlay();
                        }
                        currentslide = (currentslide ? currentslide : slides.length) - 1;
                        annotationDiv.find(".slideshow-image").fadeTo(400, 0, showCurrentImage);
                    });
                    annotationDiv.find(".slideshow-play-pause").click(togglePlay);
                } else {
                    annotationDiv.find(".slideshow-next, .slideshow-previous, .slideshow-play-pause").hide();
                }
                
            break;
            
            case "audio":
            case "video":
            
                var src = annotationinfo.annotation.content.url;
            
                var youtubeTemplate = _.template(
                    '<iframe width="<%- width %>" height="<%- height %>" src="http://www.youtube.com/embed/<%- ytid %>?rel=0&autoplay=<%- autoplay %>" frameborder="0"></iframe>'
                );
                
                var htmlTemplate = _.template(
                    '<<%- type %> width="<%- width %>" height="<%- height %>" controls="true" autoplay="<%- autoplay %>" src="<%- src %>"/>'
                );
                
                var mediaW = (annotationinfo.type === "audio" ? "100%" : annotationDiv.find(".media-frame").width()),
                    mediaH = (annotationinfo.type === "audio" ? "60" : Math.floor(Math.min($(".main-video").height() - 70, mediaW * 9 / 16)));
        
                annotationDiv.find(".media-description").html(
                    annotationinfo.annotation.description.split(/\n/gm).map(function(l) {
                        return '<p>' + _.escape(l) + '</p>';
                    }).join("")
                );
                
                if (/^(https?:\/\/)?(www\.)?youtu\.?be/.test(src)) {
                    var urlparts = src.split(/[?&]/g),
                        ytid = "",
                        vtest = /^v=/;
                    urlparts.slice(1).forEach(function(p) {
                        if (/^v=/.test(p)) {
                            ytid = p.replace(vtest,"");
                        }
                    });
                    if (!ytid) {
                        ytid = (urlparts[0].match(/[^\/]+$/) || [""])[0];
                    }
                    annotationDiv.find(".media-frame").html(youtubeTemplate({
                        ytid: ytid,
                        width: mediaW,
                        height: mediaH,
                        autoplay: +annotationinfo.annotation.content.autostart
                    }));
                    break;
                }
                
                if (/^(https?:\/\/)?(www\.)?vimeo/.test(src)) {
                    $.ajax({
                        url: "http://vimeo.com/api/oembed.json",
                        dataType: "jsonp",
                        data: {
                            width: mediaW,
                            height: mediaH,
                            url: src,
                            autoplay: annotationinfo.annotation.content.autostart,
                            color: "B8155F",
                            portrait: false,
                            title: false,
                            byline: false
                        },
                        success: function(data) {
                            annotationDiv.find(".media-frame").html(data.html);
                            annotationinfo.positionDiv();
                        }
                    });
                    break;
                }
                
                if (/^(https?:\/\/)?(www\.)?dailymotion/.test(src)) {
                    $.ajax({
                        url: "http://www.dailymotion.com/services/oembed",
                        dataType: "jsonp",
                        data: {
                            format: "json",
                            maxwidth: mediaW,
                            maxheight: mediaH,
                            url: src
                        },
                        success: function(data) {
                            annotationDiv.find(".media-frame").html(data.html);
                            annotationinfo.positionDiv();
                        }
                    });
                    break;
                }
                
                if (/^(https?:\/\/)?(www\.)?soundcloud\.com/.test(src)) {
                    $.ajax({
                        url: "http://soundcloud.com/oembed",
                        dataType: "jsonp",
                        data: {
                            format: "js",
                            show_comments: false,
                            auto_play: annotationinfo.annotation.content.autostart,
                            show_artwork: false,
                            url: src,
                            color: "B8155F"
                        },
                        success: function(data) {
                            annotationDiv.find(".media-frame").html(data.html);
                            annotationinfo.positionDiv();
                        }
                    });
                    break;
                }
                
                var extension = (src.match(/\.([\d\w]+)$/) || ["",""])[1],
                    mimetype = annotationinfo.type + "/" + extension,
                    fallbacks = { "video/webm": "mp4", "video/mp4": "webm", "audio/ogg": "mp3", "audio/mp3": "ogg" },
                    canPlay = document.createElement("video").canPlayType(mimetype);
                
                if (!canPlay) {
                    src = src.replace(/\.[\d\w]+$/,"." + fallbacks[mimetype]);
                }
                
                var media = $(htmlTemplate({
                    type: annotationinfo.type,
                    src: src,
                    width: mediaW,
                    height: mediaH,
                    autoplay: "" + annotationinfo.annotation.content.autostart
                }));
                
                media.on("loadedmetadata", function() {
                    annotationinfo.positionDiv();
                });
                
                preventRightClick(media);
                
                annotationDiv.find(".media-frame").html(media);
                
            break;
            
            case "text":
                
                var text = annotationinfo.annotation.content.text || annotationinfo.annotation.description;
                
                switch (annotationinfo.annotation.content.markup) {
                    case "html":
                        annotationDiv.find(".text-contents").html(text);
                    break;
                    default:
                        annotationDiv.find(".text-contents").html(
                            text.split(/\n/gm).map(function(l) {
                                return '<p>' + _.escape(l) + '</p>';
                            }).join("")
                        );
                    break;
                }
                annotationDiv.find(".text-contents a").attr("target","_blank");
                
            break;
            
            case "link":
            
                var linkTemplate = _.template('<p><a href="<%- url %>" target="_blank"><%- title %></a></p>');
                
                annotationDiv.find(".link-contents").html(
                    annotationinfo.annotation.content.links.map(linkTemplate).join("")
                );
                
            break;
        }
        
        annotationinfo.positionDiv();
        
    }
    
    $(".video-container").click(function() {
        if (currentAnnotation) {
            closeAnnotation(true);
        }
        return false;
    });
    
    function fullScreen() {
        var isFull = document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen || false,
            el = document.querySelector("body"),
            requestMethods = ["requestFullScreen","mozRequestFullScreen","webkitRequestFullScreen"],
            cancelMethods = ["cancelFullScreen","mozCancelFullScreen","webkitCancelFullScreen"];
        if (isFull) {
            for (var i = 0; i < cancelMethods.length; i++) {
                if (typeof document[cancelMethods[i]] === "function") {
                    document[cancelMethods[i]]();
                    break;
                }
            }
        } else {
            for (var i = 0; i < requestMethods.length; i++) {
                if (typeof el[requestMethods[i]] === "function") {
                    el[requestMethods[i]]();
                    break;
                }
            }
        }
        return false;
    }
    
    $(".full-screen").click(fullScreen);
    $(".top-bar").dblclick(fullScreen);
           
    if ( typeof document.fullScreen === "undefined"
        && typeof document.mozFullScreen === "undefined"
        && typeof document.webkitIsFullScreen === "undefined") {
        $(".full-screen").remove();
    }
            
    $(".about").click(function() {
        closeAnnotation();
        var aboutBox = $(".annotation-templates .about-box").clone().appendTo($(".main-video"));
        aboutBox.find(".close-annotation").click(closeAnnotation);
        aboutBox.css({ top: Math.floor(($(".main-video").height() - aboutBox.height())/2)+"px" });
    });
   
    function closeAnnotation(e) {
        clearInterval(slideInterval);
        currentAnnotation = null;
        $(".chip, .pictolist li").removeClass("current");
        $(".timelines").removeClass("annotation-onscreen");
        $(".annotation audio, .annotation video").each(function() {
            try {
                this.pause();
            } catch(err) { }
        });
        $(".main-video .annotation").hide().remove();
        if (!!e) {
            myMedia.play();
        }
        return false;
    }
    
    var videoRatio = null;
    
    function repositionElements() {
        var videoel = $(".video-container video");
        if (!videoRatio) {
            videoRatio = videoel.width() / videoel.height();
        }
        if (!videoRatio) {
            return;
        }
        var container = $(".main-video"),
            ch = container.height(),
            cw = container.width(),
            vw = Math.min(cw, ch * videoRatio),
            vh = vw / videoRatio,
            dw = (cw - vw) / 2,
            dh = (ch - vh) / 2;
        videoel.css({
            width: vw,
            height: vh,
            "margin-top": dh
        });
        $(".pictolist").css({
            left: dw,
            bottom: dh
        });
        if (currentAnnotation) {
            currentAnnotation.positionDiv();
        }
    }
    
    $(".video-container video").on("loadedmetadata",repositionElements);
    
    $(window).resize(repositionElements);
    
    $(document).keydown(function(e) {
        if (e.keyCode === 122) { // F11
            fullScreen();
            return false;
        }
        if (e.keyCode === 32) { // Space
            myMedia[myMedia.paused ? "play" : "pause"]();
            return false;
        }
    });
      
});

};