Add passive listeners - javascript

So Google PageSpeed Insights is complaining about "Does not use passive listeners to improve scrolling performance", the complaint is more specifically about:
https://www.youtube.com/s/player/54668ca9/player_ias.vflset/en_US/base.js
and on line 5402, which would be this:
g.h.dump=function(){var a=[],b;for(b in Gr)a.push(b+"="+encodeURIComponent(String(Gr[b])));return a.join("&")};
I have my youtube video in HTML in an iframe-tag
<iframe src="https://www.youtube.com/embed/..........." width="373" height="200" frameborder="0" allowfullscreen="allowfullscreen"></iframe>
The question is what should I do. I found the javascript code below which supposedly should resolve the issue, but I do not know where to put it. Should i put something in my functions.php-file?
The https://www.youtube.com/s/player/54668ca9/player_ias.vflset/en_US/base.js
is not a property of my domain so I do not have this js-file in my files (my Wordpress public_html), so I can not modify it.
The javascript that I found at
Wordpress and best practice with passive event listeners
and could work:
(function() {
var supportsPassive = eventListenerOptionsSupported();
if (supportsPassive) {
var addEvent = EventTarget.prototype.addEventListener;
overwriteAddEvent(addEvent);
}
function overwriteAddEvent(superMethod) {
var defaultOptions = {
passive: true,
capture: false
};
EventTarget.prototype.addEventListener = function(type, listener, options) {
var usesListenerOptions = typeof options === 'object';
var useCapture = usesListenerOptions ? options.capture : options;
options = usesListenerOptions ? options : {};
options.passive = options.passive !== undefined ? options.passive : defaultOptions.passive;
options.capture = useCapture !== undefined ? useCapture : defaultOptions.capture;
superMethod.call(this, type, listener, options);
};
}
function eventListenerOptionsSupported() {
var supported = false;
try {
var opts = Object.defineProperty({}, 'passive', {
get: function() {
supported = true;
}
});
window.addEventListener("test", null, opts);
} catch (e) {}
return supported;
}
})();

Related

Javascript classes and Customevents

I want to know how to add a custom event to a instance of a class and call it for that instance.
My code right now:
var event = document.createEvent('event');
event.initEvent('build', true, true);
class link {
constructor(Href, Text = "Click me", Target = "__blank") {
this.href = Href;
this.text = Text
this.target = Target;
this.eventElm = document.createElement("event");
//this.event = document.createEvent('event');
//this.event.initEvent('build', true, true);
}
}
class creator {
constructor(Objs) {
for(var i in Objs) {
window.document.body.innerHTML += ""+Objs[i].text+"<br>";
if(Objs[i].href == "#") {
Objs[i].eventElm.dispatchEvent(event);
}
}
}
}
var l = new link("#");
var lo = new link("#");
var ar = [];
ar.push(l);
ar.push(lo);
l.eventElm.addEventListener('build', function(e) {
console.log(e);
}, false);
//l.eventElm.dispatchEvent(event);
window.onload = function () {
var crea = new creator(ar);
console.log(l.href);
}
This code returns the error
eventtest.html:24 Uncaught DOMException: Failed to execute 'dispatchEvent' on 'EventTarget': The event is already being dispatched.
at new creator (http://localhost/eventtest.html:24:25)
at window.onload (http://localhost/eventtest.html:44:16)
I want to do this in plain javascript no jquery. Thanks for taking the time to read this and hopefully help me.
You're declaring a global event variable. But most browsers (IE, Edge, Chrome) already have a global event variable (the currently-being-dispatched event). So you end up trying to re-dispatch the load event that's being handled.
This is one of the many reasons not to put your code at global scope. Instead, wrap it in a scoping function:
(function() {
// Your code here...
})();
Now, your event variable isn't conflicting with the global event.
Live Example:
(function() {
var event = document.createEvent('event');
event.initEvent('build', true, true);
class link {
constructor(Href, Text = "Click me", Target = "__blank") {
this.href = Href;
this.text = Text
this.target = Target;
this.eventElm = document.createElement("event");
//this.event = document.createEvent('event');
//this.event.initEvent('build', true, true);
}
}
class creator {
constructor(Objs) {
for(var i in Objs) {
window.document.body.innerHTML += ""+Objs[i].text+"<br>";
if(Objs[i].href == "#") {
Objs[i].eventElm.dispatchEvent(event);
}
}
}
}
var l = new link("#");
var lo = new link("#");
var ar = [];
ar.push(l);
ar.push(lo);
l.eventElm.addEventListener('build', function(e) {
console.log(e);
}, false);
//l.eventElm.dispatchEvent(event);
window.onload = function () {
var crea = new creator(ar);
console.log(l.href);
}
})();
Separately: You probably want to create a new event object each time you dispatch your event, rather than having that single global-to-your-code event variable.

Cannot detect if window is loaded

I'm currently working on counting the number of opened tabs on my application. but my problem is it seems that my script won't detect events onload. Here is my code.
I'm using HTML5 web storage and native js. I'm not using jQuery to understand more on native js.
(function(w) {
function Tabz(win, key) {
this.name = '';
this.storageKey = key;
if(win.name != '')
this.name = win.name;
else {
var windowArr = JSON.parse(localStorage.getItem(key)) || [];
this.name = "tabz_"+ windowArr.length;
win.name = this.name;
windowArr.push(this.name);
localStorage.setItem(this.storageKey, JSON.stringify(windowArr) );
}
}
Tabz.prototype.getStorage = function() {
return localStorage.getItem(this.storageKey);
}
Tabz.prototype.removeWindow = function() {
//remove window function here
}
var newWindow = new Tabz(w, 'counter');
window.load = function() {
var count = JSON.parse(newWindow.getStorage()).length;
alert(count!); // this wont execute so that I can check the count.
}
})(window);
Your issue is on this line:
window.load = function() {
This will add a load property to the window, not add an event listener. I think you are looking for onload.
window.onload = function() {
Incidentally, using event properties is considered bad-practice. Using addEventListener would be better.
window.addEventListener("load", function(){
//Do stuff...
});

Is there a way to disable a dojox.mobile.switch?

Is there a way to disable a dojox.mobile.Switch so that it is visible but greyed out and unclickable/untouchable? I can't see anything in the standard API doc.
Edit: I should add that I am working with Dojo 1.7.
I had to do this today. I extended the Switch module. Works well for me, but I'm sure it could be improved.
define([
"dojo/_base/declare",
"dojox/mobile/Switch"
], function(declare, Switch){
return declare("my.package.Switch", [Switch], {
disabled: false,
events: {},
disableSwitch: function() {
//remove events (but hold on to them for later).. there may be a better dojo way of doing this
this.events._onClick = this._onClick;
this.events.onClick = this.onClick;
this.events.onTouchStart = this.onTouchStart;
this.events.onTouchMove = this.onTouchMove;
this._onClick = function(){};
this.onClick = function(){};
this.onTouchStart = function(){};
this.onTouchMove = function(){};
//TODO: better styling to make it look disabled?
// this.domNode.style.opacity = '0.5';
this.domNode.style['-webkit-filter'] = 'grayscale(1)';
this.disabled = true;
},
enableSwitch: function() {
//reattach events
this._onClick = this.events._onClick;
this.onClick = this.events.onClick;
this.onTouchStart = this.events.onTouchStart;
this.onTouchMove = this.events.onTouchMove;
// this.domNode.style.opacity = '1';
this.domNode.style['-webkit-filter'] = 'grayscale(0)';
this.disabled = false;
}
});
});

webkitmutationobserver does not work in Safari?

I need to monitor the display state of an element. I'm using the following code
if WebKitMutationObserver?
observer = new WebKitMutationObserver observerFunc
observer.observe el, {attributes:true}
else
el.addEventListener "DOMAttrModified",(event)->
wrapper.style.display = el.style.display
return
However this does not work in Safari.
Also, typing "WebKitMutationObserver" in developer tools immediate window in Chrome gives the output
function WebKitMutationObserver() { [native code] }
while in Safari (v 5.1.7), this gives an error with the message
"Can't find variable: WebKitMutationObserver"
Could it be that Safari does not support WebkitMutationObserver? And if so, is there an alternative which I could use for this?
The newest Safari (6.0) does include WebKitMutationObserver. For older Safari's, here's some code we have used that fakes a DOMAttrModified event when you use setAttribute or removeAttribute to change an attribute. Note that this doesn't work if the browser itself changes an attribute internally.
var win = window;
var doc = win.document;
var attrModifiedWorks = false;
var listener = function () { attrModifiedWorks = true; };
doc.documentElement.addEventListener("DOMAttrModified", listener, false);
doc.documentElement.setAttribute("___TEST___", true);
doc.documentElement.removeAttribute("___TEST___", true);
doc.documentElement.removeEventListener("DOMAttrModified", listener, false);
if (!attrModifiedWorks)
{
This.DOMAttrModifiedUnsupported = true;
win.HTMLElement.prototype.__setAttribute = win.HTMLElement.prototype.setAttribute;
win.HTMLElement.prototype.setAttribute = function fixDOMAttrModifiedSetAttr (attrName, newVal)
{
var prevVal = this.getAttribute(attrName);
this.__setAttribute(attrName, newVal);
newVal = this.getAttribute(attrName);
if (newVal != prevVal)
{
var evt = doc.createEvent("MutationEvent");
evt.initMutationEvent
( "DOMAttrModified"
, true
, false
, this
, prevVal || ""
, newVal || ""
, attrName
, (prevVal == null) ? win.MutationEvent.ADDITION : win.MutationEvent.MODIFICATION
);
this.dispatchEvent(evt);
}
}
win.HTMLElement.prototype.__removeAttribute = win.HTMLElement.prototype.removeAttribute;
win.HTMLElement.prototype.removeAttribute = function fixDOMAttrModifiedRemoveAttr (attrName)
{
var prevVal = this.getAttribute(attrName);
this.__removeAttribute(attrName);
var evt = doc.createEvent("MutationEvent");
evt.initMutationEvent("DOMAttrModified", true, false, this, prevVal, "", attrName, win.MutationEvent.REMOVAL);
this.dispatchEvent(evt);
}
}
}

Adding a jQuery style event handler of iPhone OS events

I'm looking for a super simple jQuery extension. Basically I need to use some events that jQuery does not explicitly support. These events are the iPhone touch events like ontouchstart, ontouchend, and ontouchmove.
I have it working via this:
// Sucks
$('.clickable').each(function() {
this.ontouchstart = function(event) {
//do stuff...
};
}
Which kind of sucks and is unjqueryish. Here is what I would like:
// Better
$('.clickable').touchstart(function() {
//do stuff...
}
Or even better with 1.4
// Awesome
$('.clickable').live('touchstart', function() {
//.. do stuff
}
These events need no special handling and should work just like any other events, but I can't seem to figure out how to extend jquery to make them work just like all the other events do.
I wrote the plugin, if the user does have touch available, use, otherwise, call click
jQuery.event.special.tabOrClick = {
setup: function (data, namespaces) {
var elem = this, $elem = jQuery(elem);
if (window.Touch) {
$elem.bind('touchstart', jQuery.event.special.tabOrClick.onTouchStart);
$elem.bind('touchmove', jQuery.event.special.tabOrClick.onTouchMove);
$elem.bind('touchend', jQuery.event.special.tabOrClick.onTouchEnd);
} else {
$elem.bind('click', jQuery.event.special.tabOrClick.click);
}
},
click: function (event) {
event.type = "tabOrClick";
jQuery.event.handle.apply(this, arguments);
},
teardown: function (namespaces) {
var elem = this, $elem = jQuery(elem);
if (window.Touch) {
$elem.unbind('touchstart', jQuery.event.special.tabOrClick.onTouchStart);
$elem.unbind('touchmove', jQuery.event.special.tabOrClick.onTouchMove);
$elem.unbind('touchend', jQuery.event.special.tabOrClick.onTouchEnd);
} else {
$elem.unbind('click', jQuery.event.special.tabOrClick.click);
}
},
onTouchStart: function (e) {
this.moved = false;
},
onTouchMove: function (e) {
this.moved = true;
},
onTouchEnd: function (event) {
if (!this.moved) {
event.type = "tabOrClick";
jQuery.event.handle.apply(this, arguments)
}
}
};
$("#xpto").bind("tabOrClick", function () {
alert("aaaa");
});
I've made a small update to Alexandre's plugin to include Android support. Android's browser does not currently support the window.Touch method of detecting touch support.
I love how Alexandre's script waits to ensure movement didn't occur to prevent triggering the event when the user swipes to scroll across the screen. However a downfall of that approach is that it causes its own delay by waiting for the user to lift their finger off of the screen before triggering. I've updated his plugin to include a "touchactive" class that gets applied to items that a user is currently touching. If you take advantage of that class you can provide immediate visual feedback to users without causing an actual event to get triggered until after movement check has completed.
jQuery.event.special.touchclick = {
setup: function (data, namespaces) {
var elem = this, $elem = jQuery(elem);
var ua = navigator.userAgent.toLowerCase();
var isAndroid = ua.indexOf("android") > -1;
if (window.Touch || isAndroid) {
$elem.bind('touchstart', jQuery.event.special.touchclick.onTouchStart);
$elem.bind('touchmove', jQuery.event.special.touchclick.onTouchMove);
$elem.bind('touchend', jQuery.event.special.touchclick.onTouchEnd);
} else {
$elem.bind('click', jQuery.event.special.touchclick.click);
}
},
click: function (event) {
event.type = "touchclick";
jQuery.event.handle.apply(this, arguments);
},
teardown: function (namespaces) {
var elem = this, $elem = jQuery(elem);
if (window.Touch) {
$elem.unbind('touchstart', jQuery.event.special.touchclick.onTouchStart);
$elem.unbind('touchmove', jQuery.event.special.touchclick.onTouchMove);
$elem.unbind('touchend', jQuery.event.special.touchclick.onTouchEnd);
} else {
$elem.unbind('click', jQuery.event.special.touchclick.click);
}
},
onTouchStart: function (e) {
this.moved = false;
$(this).addClass('touchactive');
},
onTouchMove: function (e) {
this.moved = true;
$(this).removeClass('touchactive');
},
onTouchEnd: function (event) {
if (!this.moved) {
event.type = "touchclick";
jQuery.event.handle.apply(this, arguments)
}
$(this).removeClass('touchactive');
}
};
I've also posted this to github in case there are further caveats that are discovered https://github.com/tuxracer/jquery-touchclick
This now works, just like it's stubbed out above, on the latest jQuery release. Go jQuery!
Here's a start:
$.fn.touchstart = function(fn) { return this[fn ? "bind" : "trigger"]("touchstart", fn); };
$.event.special.touchstart = {
setup: function() {
$.event.add(this, "mouseenter", extendedClickHandler, {});
},
teardown: function() {
$.event.remove(this, "mouseenter", extendedClickHandler);
}
};
Where extendedClickHandler is the function that does what it's suppose to do.
More info here: http://brandonaaron.net/blog/2009/03/26/special-events
jQuery.com is a great source of information like this.
If you build your own plugin you'll be able to use whatever naming you like on your method calls.

Categories