diff --git a/plugins/lazyYT/assets/javascripts/initializers/lazyYT.js.es6 b/plugins/lazyYT/assets/javascripts/initializers/lazyYT.js.es6 index 34950f184df..29d5c10060f 100644 --- a/plugins/lazyYT/assets/javascripts/initializers/lazyYT.js.es6 +++ b/plugins/lazyYT/assets/javascripts/initializers/lazyYT.js.es6 @@ -1,18 +1,32 @@ import { withPluginApi } from 'discourse/lib/plugin-api'; +const returnFalse = () => false; + export default { name: "apply-lazyYT", initialize() { withPluginApi('0.1', api => { - api.decorateCooked($elem => $('.lazyYT', $elem).lazyYT({ - onPlay(e, $el) { - // don't cloak posts that have playing videos in them - const postId = parseInt($el.closest('article').data('post-id')); - if (postId) { - api.preventCloak(postId); + api.decorateCooked($elem => { + + // We use this because watching videos fullscreen in Chrome was super buggy + // otherwise. Thanks to arrendek from q23 for the technique. + $elem.iframeTracker({ blurCallback: () => { + $(document).on("scroll.discourse-youtube", returnFalse); + window.setTimeout(() => $(document).off('scroll.discourse-youtube', returnFalse), 1500); + $(document).scroll(); + }}); + + $('.lazyYT', $elem).lazyYT({ + onPlay(e, $el) { + // don't cloak posts that have playing videos in them + const postId = parseInt($el.closest('article').data('post-id')); + if (postId) { + api.preventCloak(postId); + } } - } - })); + }); + + }); }); } }; diff --git a/plugins/lazyYT/assets/javascripts/jquery.iframetracker.js b/plugins/lazyYT/assets/javascripts/jquery.iframetracker.js new file mode 100644 index 00000000000..595633ea81b --- /dev/null +++ b/plugins/lazyYT/assets/javascripts/jquery.iframetracker.js @@ -0,0 +1,165 @@ +/** + * jQuery iframe click tracking plugin + * + * @author Vincent Paré (www.finalclap.com) + * @copyright © 2013-2015 Vincent Paré + * @license http://opensource.org/licenses/Apache-2.0 + * @version 1.1.0 + */ +(function($){ + // Tracking handler manager + $.fn.iframeTracker = function(handler){ + var target = this.get(); + if (handler === null || handler === false) { + $.iframeTracker.untrack(target); + } else if (typeof handler == "object") { + $.iframeTracker.track(target, handler); + } else { + throw new Error("Wrong handler type (must be an object, or null|false to untrack)"); + } + }; + + // Iframe tracker common object + $.iframeTracker = { + // State + focusRetriever: null, // Element used for restoring focus on window (element) + focusRetrieved: false, // Says if the focus was retrived on the current page (bool) + handlersList: [], // Store a list of every trakers (created by calling $(selector).iframeTracker...) + isIE8AndOlder: false, // true for Internet Explorer 8 and older + + // Init (called once on document ready) + init: function(){ + // Determine browser version (IE8-) ($.browser.msie is deprecated since jQuery 1.9) + try { + if ($.browser.msie == true && $.browser.version < 9) { + this.isIE8AndOlder = true; + } + } catch(ex) { + try { + var matches = navigator.userAgent.match(/(msie) ([\w.]+)/i); + if (matches[2] < 9) { + this.isIE8AndOlder = true; + } + } catch(ex2) {} + } + + // Listening window blur + $(window).focus(); + $(window).blur(function(e){ + $.iframeTracker.windowLoseFocus(e); + }); + + // Focus retriever (get the focus back to the page, on mouse move) + $('body').append('
'); + this.focusRetriever = $('#focus_retriever'); + this.focusRetrieved = false; + $(document).mousemove(function(e){ + if (document.activeElement && document.activeElement.tagName == 'IFRAME') { + $.iframeTracker.focusRetriever.focus(); + $.iframeTracker.focusRetrieved = true; + } + }); + + // Special processing to make it work with my old friend IE8 (and older) ;) + if (this.isIE8AndOlder) { + // Blur doesn't works correctly on IE8-, so we need to trigger it manually + this.focusRetriever.blur(function(e){ + e.stopPropagation(); + e.preventDefault(); + $.iframeTracker.windowLoseFocus(e); + }); + + // Keep focus on window (fix bug IE8-, focusable elements) + $('body').click(function(e){ $(window).focus(); }); + $('form').click(function(e){ e.stopPropagation(); }); + + // Same thing for "post-DOMready" created forms (issue #6) + try { + $('body').on('click', 'form', function(e){ e.stopPropagation(); }); + } catch(ex) { + console.log("[iframeTracker] Please update jQuery to 1.7 or newer. (exception: " + ex.message + ")"); + } + } + }, + + + // Add tracker to target using handler (bind boundary listener + register handler) + // target: Array of target elements (native DOM elements) + // handler: User handler object + track: function(target, handler){ + // Adding target elements references into handler + handler.target = target; + + // Storing the new handler into handler list + $.iframeTracker.handlersList.push(handler); + + // Binding boundary listener + $(target) + .bind('mouseover', {handler: handler}, $.iframeTracker.mouseoverListener) + .bind('mouseout', {handler: handler}, $.iframeTracker.mouseoutListener); + }, + + // Remove tracking on target elements + // target: Array of target elements (native DOM elements) + untrack: function(target){ + if (typeof Array.prototype.filter != "function") { + console.log("Your browser doesn't support Array filter, untrack disabled"); + return; + } + + // Unbinding boundary listener + $(target).each(function(index){ + $(this) + .unbind('mouseover', $.iframeTracker.mouseoverListener) + .unbind('mouseout', $.iframeTracker.mouseoutListener); + }); + + // Handler garbage collector + var nullFilter = function(value){ + return value === null ? false : true; + }; + for (var i in this.handlersList) { + // Prune target + for (var j in this.handlersList[i].target) { + if ($.inArray(this.handlersList[i].target[j], target) !== -1) { + this.handlersList[i].target[j] = null; + } + } + this.handlersList[i].target = this.handlersList[i].target.filter(nullFilter); + + // Delete handler if unused + if (this.handlersList[i].target.length == 0) { + this.handlersList[i] = null; + } + } + this.handlersList = this.handlersList.filter(nullFilter); + }, + + // Target mouseover event listener + mouseoverListener: function(e){ + e.data.handler.over = true; + try {e.data.handler.overCallback(this);} catch(ex) {} + }, + + // Target mouseout event listener + mouseoutListener: function(e){ + e.data.handler.over = false; + $.iframeTracker.focusRetriever.focus(); + try {e.data.handler.outCallback(this);} catch(ex) {} + }, + + // Calls blurCallback for every handler with over=true on window blur + windowLoseFocus: function(event){ + for (var i in this.handlersList) { + if (this.handlersList[i].over == true) { + try {this.handlersList[i].blurCallback();} catch(ex) {} + } + } + } + }; + + // Init the iframeTracker on document ready + $(document).ready(function(){ + $.iframeTracker.init(); + }); +})(jQuery); \ No newline at end of file diff --git a/plugins/lazyYT/plugin.rb b/plugins/lazyYT/plugin.rb index 70475b73afa..dc1e7da2567 100644 --- a/plugins/lazyYT/plugin.rb +++ b/plugins/lazyYT/plugin.rb @@ -6,6 +6,7 @@ # javascript register_asset "javascripts/lazyYT.js" +register_asset "javascripts/jquery.iframetracker.js" # stylesheet register_asset "stylesheets/lazyYT.css"