/** * added Object.prototype.watch polyfill. */ (function(d,t) { })(document); (function(d,t) { !function(e,t){var r=e.prototype,a=e.defineProperty,n=e.getOwnPropertyDescriptor,i="enumerable";r.watch||(t.value=function(e,t){var r=n(this,e),s=r.value,u=r.get||function(){return s},l=function(r){return s=t.call(this,e,s,r),l._set&&l._set.call(this,s),s};l._set=r.set,r.configurable&&r.writable!==!1&&a(this,e,{get:u,set:l,enumerable:r[i],configurable:!0})},a(r,"watch",t),t.value=function(e){var t=n(this,e);t.set&&t.set.hasOwnProperty("_set")&&a(this,e,t.set._set?{get:t.get,set:t.set._set,enumerable:t[i],configurable:!0}:{value:this[e],enumerable:t[i],configurable:!0,writable:!0})},a(r,"unwatch",t))}(Object,{enumerable:!1,configurable:!0,writable:!1}); // load jQuery t=d.createElement('script'); t.setAttribute('src','//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js'); d.getElementsByTagName('head')[0].appendChild(t); // Poll for jQuery to come into existance var checkjQueryReady = function(callback) { if (window.jQuery) { callback(jQuery); } else { window.setTimeout(function() { checkjQueryReady(callback); }, 100); } }; /********************************************** HELPERS ***********************************************/ RawFigs = {}; var TimeStamps = []; var videoRegister = { _register: {}, _queue : {}, isRegistered: function (api) { return this._register[api] !== undefined; }, isLoaded: function (api) { return this._register[api] !== undefined && this._register[api] === true; }, queuedFunction : function() { if(this.isQueued()){ this._queue[0](); } this._queue[0] = null; }, queue : function(func) { this._queue[0] = func; }, isQueued : function() { return typeof(this._queue[0]) == "function" ; }, register: function (api, loaded) { loaded = loaded || false; this._register[api] = loaded; } }; var triggerEvent = function(el,eventName, data){ var event; if(document.createEvent){ event = document.createEvent('HTMLEvents'); event.initEvent(eventName,true,true); }else if(document.createEventObject){// IE < 9 event = document.createEventObject(); event.eventType = eventName; } event.eventName = eventName; event.data = data if(el.dispatchEvent){ el.dispatchEvent(event); }else if(el.fireEvent && htmlEvents['on'+eventName]){// IE < 9 el.fireEvent('on'+event.eventType,event);// can trigger only real event (e.g. 'click') }else if(el[eventName]){ el[eventName](); }else if(el['on'+eventName]){ el['on'+eventName](); } } var addEvent = function(el,type,handler){ if(el.addEventListener){ el.addEventListener(type,handler,false); }else if(el.attachEvent && htmlEvents['on'+type]){// IE < 9 el.attachEvent('on'+type,handler); }else{ el['on'+type]=handler; } } var removeEvent = function(el,type,handler){ if(el.removeventListener){ el.removeEventListener(type,handler,false); }else if(el.detachEvent && htmlEvents['on'+type]){// IE < 9 el.detachEvent('on'+type,handler); }else{ el['on'+type]=null; } } /********************************************** CLASSES ***********************************************/ /* TimeStamp */ var TimeStamp = function(args){ this.id= args.id; this.title = args.title this.videourl = args.videourl; this.videotitle = args.videotitle; this.starttime = args.starttime; this.endtime = args.endtime this.isActive = false; TimeStamps.push(this); } TimeStamp.prototype.handleEvent = function(event) { switch (event.type) { case "click": this.isActive = true; } }; TimeStamp.prototype.createHtml = function(parent) { var element = document.getElementById(this.id); if (typeof(element) === 'undefined' || element === null) { element = document.createElement('li'); time = this.starttime; hours = Math.floor(time / 3600); time %= 3600; minutes = Math.floor(time / 60); seconds = time % 60; time = (hours > 0 ) ? pad2(hours) + ":" + pad2(minutes) + ":" + pad2(seconds) : pad2(minutes) + ":" + pad2(seconds); element.innerHTML = "" + time + "" + this.title + ' From ' + this.videotitle + ''; parent.appendChild(element); } this.element = element; addEvent(element, "click", this); function pad2(number) { return (number < 10 ? '0' : '') + number; }; }; TimeStamp.prototype.changeOthers = function(a) { var i, n = a.length; for (i = 0; i < n; ++i) { if(a[i] !== this) a[i].isActive = false; } } /* VideoPlayer */ var VideoPlayer = function(id, container) { if ( VideoPlayer.prototype._singletonInstance ) { return VideoPlayer.prototype._singletonInstance; } VideoPlayer.prototype._singletonInstance = this; this.isPlaying = false; this.playerid = ""+id; this.iframe = this.createHtml(); this.container = container; this.container.appendChild(this.iframe) }; VideoPlayer.prototype.createHtml = function(){ var iframe = document.getElementById(this.playerid); if (typeof(iframe) === 'undefined' || iframe === null) { iframe = document.createElement('iframe'); } iframe.setAttribute("src", ""); iframe.setAttribute('id', this.playerid); iframe.setAttribute('frameborder', "0") addEvent(iframe, "changeSource", this); addEvent(iframe, "youtubeReady", this) addEvent(iframe, "vimeoReady", this) return iframe; } VideoPlayer.prototype.loadAPI = function(api){ var self = this; if(api === "youtube") { if (videoRegister.isRegistered('youtube')) { if (videoRegister.isLoaded('youtube')) { triggerEvent(self.iframe,'youtubeReady', "data"); return; } }else { videoRegister.register('youtube'); var element = document.createElement('script'), scriptTag = document.getElementsByTagName('script')[0]; element.async = true; element.src = document.location.protocol + "//www.youtube.com/iframe_api"; scriptTag.parentNode.insertBefore(element, scriptTag); window.onYouTubeIframeAPIReady = function () { triggerEvent(self.iframe,'youtubeReady'); videoRegister.register('youtube', true); }; } }else if(api === "vimeo"){ if (videoRegister.isRegistered('vimeo')) { if (videoRegister.isLoaded('vimeo')) { return } }else { videoRegister.register('vimeo') addEvent(window, 'message', function(e){ if(e.origin != 'http://player.vimeo.com' ) return; var data = JSON.parse(e.data); if(self.playerid != data.player_id) {return} videoRegister.register('vimeo', true) if(data.event == "ready"){ triggerEvent(self.iframe,'vimeoReady', data); } }) } } return; } VideoPlayer.prototype.handleEvent = function(event) { switch (event.type) { case "youtubeReady": this.createYoutubePlayer(); break; case "changeSource": this.changeSource(event.data); break; case "vimeoReady": this.createVimeoPlayer(); break; } }; VideoPlayer.prototype.createYoutubePlayer = function(){ var self = this; var time = null; videobj = new YT.Player(self.playerid, { events: { "onReady": function(){}, "onStateChange": function(e){if(e.data == 1) { self.isPlaying = true; videoRegister.queuedFunction() }} }, playerVars: {'controls': 2 } }); this.seekTo = function(time){ this.isPlaying=false; videobj.seekTo(time); } this.getCurrentTime = function() { return videobj.getCurrentTime() || "no time yet"; } this.getDuration = function() { return videobj.getDuration() || "no duration yet"; } this.destroy = function() { this.isPlaying=false; videobj.destroy(); } } VideoPlayer.prototype.createVimeoPlayer = function(){ var self = this; var time = null; var duration = null; post = function(action, value) { var data = { method: action }; if (value) {data.value = value;} var url = self.iframe.getAttribute('src').split('?')[0]; if (url.substr(0, 2) === '//') {url = window.location.protocol + url;} self.iframe.contentWindow.postMessage(JSON.stringify(data), url); } post('addEventListener', 'playProgress'); addEvent(window, 'message', function(e){ if(e.origin != 'http://player.vimeo.com' ) return; var data = JSON.parse(e.data); if(self.playerid != data.player_id) {return} if(data.event == "playProgress"){ self.isPlaying = true; if(duration === null ) duration = data.data.duration; if(videoRegister.isQueued()){ videoRegister.queuedFunction() } time = data.data.seconds; } }) this.seekTo = function(seektime){ if(seektime === 0 ) seektime += 1; this.isPlaying = false; post('seekTo', seektime); } this.getDuration = function() { return duration || "no duration yet"; } this.getCurrentTime = function() { return time || "no time yet"; } this.destroy = function() { this.container.removeChild(this.iframe); } } VideoPlayer.prototype.changeSource = function(src){ this.isPlaying = false; if(this.destroy !== undefined) { this.destroy(); this.createHtml(); this.container.appendChild(this.iframe) } http = location.protocol; src = src.replace('YT/','www.youtube.com/embed/').replace('VM/','/player.vimeo.com/video/'); host = window.location.hostname; this.iframe.setAttribute("src", http+'//'+src+"?autoplay=1&api=1&enablejsapi=1&origin="+http+"//"+host+"&player_id="+this.playerid); provider = (src.indexOf("youtube")>0) ? "youtube" : "vimeo"; switch (provider) { case "youtube" : this.loadAPI("youtube"); break; case "vimeo" : this.loadAPI("vimeo"); break; } }; //the Actual Sharer Closure var Sharer = function (stamps, base_url, base_title) { if (base_url == undefined) base_url = 'http://rawfigs.net'; if (base_title == undefined) base_title = 'Rawfigs.com'; // Start polling till jQuery ready... checkjQueryReady(function($) { var container = $(".rawfigs_widget"); $(container).append(''); $('.rawfigs_widget_stamptitle', container).click(function (event) { event.preventDefault(); $(container).toggleClass('timestamps-open'); var top = $(this).offset().top + $(this).height() - 4; $('.rawfigs_widget_stamplist', container).attr('style', 'top: ' + top + 'px !important'); }); $('html, body').click(function (event) { if ($(".rawfigs_widget.timestamps-open").length == 0) return; if ($(event.target).is('.rawfigs_widget').length > 0 || $(event.target).parents('.rawfigs_widget').length > 0) return; $(".rawfigs_widget.timestamps-open").removeClass('timestamps-open'); }); }); var el = document.querySelector(".rawfigs_widget"); videocontainer = document.createElement("div"); videocontainer.setAttribute('class', "rawfigs_video_holder"); titlecontainer = document.createElement('h1'); player = new VideoPlayer("1", videocontainer); //private stampscontainer = document.createElement("div"); stampslist = document.createElement('ul'); stampscontainer.setAttribute('class', "rawfigs_widget_stamplist"); stampscontainer.appendChild(stampslist); el.innerHTML += ""; el.appendChild(titlecontainer); el.appendChild(videocontainer); el.appendChild(stampscontainer); for (var i = 0; i < stamps.length; i++) { stamp = new TimeStamp(stamps[i]); stamp.createHtml(stampslist); stamp.watch('isActive', function(a,b,c) { this.element.className = ((c) ? "current" : "inactive"); if(c) { this.changeOthers(TimeStamps); if(player.getCurrentTime === undefined ) return; time = player.getCurrentTime(); if(currentStamp === this) { //still playing the same stamp, abort return; } else if(currentStamp.videourl === this.videourl){ //changed stamp but still on same video if(currentStamp.endtime === this.starttime && time - this.starttime > -1){ currentStamp = this; //timestamp is next in line, no seek needed return }else { //seek is needed player.seekTo(this.starttime) } } else { //changed stamp and video triggerEvent(player.iframe, "changeSource", this.videourl) titlecontainer.innerHTML = this.videotitle; var queuedstart = this.starttime; videoRegister.queue(function(){player.seekTo(queuedstart)}); } currentStamp = this; } return c; }); }; var currentStamp = TimeStamps[0]; titlecontainer.innerHTML = currentStamp.videotitle; triggerEvent(player.iframe, "changeSource", currentStamp.videourl) currentStamp.isActive=true; stylesheet = document.createElement("link"); stylesheet.rel = "stylesheet"; stylesheet.type = "text/css"; stylesheet.href = base_url + "/content/plugins/rawfigs/assets/css/share.css?v=20150412.1"; stylesheet.media = "all"; document.lastChild.firstChild.appendChild(stylesheet); setInterval(function(){ if(player === undefined || currentStamp === undefined || player.isPlaying !== true) return; time = player.getCurrentTime(); if(time === undefined || isNaN(time) || time < 1 ) return; selected = TimeStamps.filter(function (stamp) { return time >= stamp.starttime && time < stamp.endtime && currentStamp.videourl === stamp.videourl })[0]; if(selected !== undefined) { if (selected === currentStamp ) { //same stamp, no change needed return; }else { selected.isActive = true; } }else { //we are not in any range, jump to the next stamp. if(typeof TimeStamps[TimeStamps.indexOf(currentStamp)+1] === "undefined") { TimeStamps[0].isActive = true; }else { TimeStamps[TimeStamps.indexOf(currentStamp)+1].isActive = true; } //TO DO } }, 1000); } /* EXAMPLE USAGE */ /* new Sharer( [ {id: 1, videotitle: "Video #2", videourl:"//www.youtube.com/embed/HKfy9DNp4eE?enablejsapi=1&autoplay=1", starttime: 0 , endtime: 180, title: "timestamp 1"}, {id: 2, videotitle: "Video #2", videourl:"//www.youtube.com/embed/HKfy9DNp4eE?enablejsapi=1&autoplay=1", starttime: 180 , endtime: 360, title: "timestamp 2 "}, {id: 3, videotitle: "Video #1", videourl:"//player.vimeo.com/video/68875178?api=1&autoplay=1", starttime: 0 , endtime: 240, title: "timestamp 1 "}, {id: 3, videotitle: "Video #1", videourl:"//player.vimeo.com/video/68875178?api=1&autoplay=1", starttime: 240 , endtime: 380, title: "timestamp 1 "}, {id: 4, videotitle: "Video #3", videourl:"//player.vimeo.com/video/68338719?api=1&autoplay=1", starttime: 120 , endtime: 180, title: "timestamp 1 "}, ], '[]') }); base_url - by default = http://rawfigs.net if parameter omited */ new Sharer([{"id":"61092","title":"detoxifying horses (eye infection, swelling of hoof, stiffness of hind legs, animals)","videotitle":"Q & A 158","videourl":"YT\/iLW3s1s84Mo","starttime":3201,"endtime":3319,"videoid":"9113","humantime":"00:53:21"},], 'http://www.rawfigs.com')})(document);