I'm trying to use the window.matchMedia event listener to detect if the user is on a touch device or not. But im just seems to be only activate when the chrome DevTools window is resized, and not actually detect if it is a touch device (for example, on my pixel 3a).
here is the code i used for the event listener
if (matchMedia) {
let mql = window.matchMedia('(pointer: fine)');
mql.addListener(touchChange)
}
and the function which it runs
function touchChange (event) {
if (event.matches) {
touchcontrols = true;
console.log("Touch Controls");
console.log(window.innerWidth);
document.getElementById("lives").innerHTML = "Touch Events!";
}
}
If you just want to see if it matches once you can use:
let matches = window.matchMedia('(pointer: fine)').matches;
window.matchMedia returns an object with a matches property which indicates if it's currently matching your query and an addListener to register a callback which will be called in response to the media query status changing.
More on this: https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList/addListener
Question
How can I initialize dash.js with the correct quality before the stream is initialized?
Problem:
While setting a quality with dash.js, I get green artifacts when playback starts (see image below). Quality is set after stream initialization by responding to the STREAM_INITIALIZED event.
Context: I am trying to create an application with a dash where the user should be able to select a playback quality. This selection is will be set by using a cookie like this: cookies.set('preferredQuality', quality.value);, where value corresponds to either 0, 1, 2 or 3 (set in dash.js with setQualityFor and setAutoSwitchQualityFor set to false).
Then in the logic for creating the dash instance, I listen for the STREAM_INITIALIZED event and try to set the quality there
this.dashJsInstance.on(dashjs.MediaPlayer.events.STREAM_INITIALIZED, this.onStreamInitialized, this);
onStreamInitialized: function() {
const quality = cookies.get('preferredQuality');
if (quality !== -1) {
this.dashJsInstance.setAutoSwitchQualityFor('video', false);
this.dashJsInstance.setQualityFor('video', quality);
}
},
This results in the green artifacts shown in the image.
Not sure if this is the correct answer, but solved it by listening to the onFragmentLoaded event. This is by no means the best answer, but it works. We implemented it by doing something like this:
onFragmentLoaded: function(e) {
if (e.request && e.request.type === 'InitializationSegment') {
const preferredQuality = quality // Preferred quality;
const currentQuality = current // Current quality;
if (currentQuality !== preferredQuality) {
this.dashJsInstance.setQualityFor('video', preferredQuality);
this.dashJsInstance.setAutoSwitchQualityFor('video', false);
}
}
},
I have a video streaming app I'm working on that lets me select a year of videos from a listTemplate, where each year is then a catalogTemplate with links to video resources. Navigation between the listTemplate and catalogTemplate works fine, but when I select a video from one of the catalogTemplates, the video plays behind the template, rather than going to the foreground. How can I fix what I presume is a navigation stack error like this? Below is the code I use to actually present stuff, taken partly from Apple's documentation.
load: function(event) {
console.log(event);
var self = this,
ele = event.target,
templateURL = ele.getAttribute("template"),
presentation = ele.getAttribute("presentation"),
videoURL = ele.getAttribute("videoURL");
if(videoURL) {
//2
var player = new Player();
var playlist = new Playlist();
var mediaItem = new MediaItem("video", videoURL);
player.playlist = playlist;
player.playlist.push(mediaItem);
player.present();
};
/*
Check if the selected element has a 'template' attribute. If it does then we begin
the process to present the template to the user.
*/
if (templateURL) {
/*
Whenever a user action is taken you need to visually indicate to the user that
you are processing their action. When a users action indicates that a new document
should be presented you should first present a loadingIndicator. This will provide
the user feedback if the app is taking a long time loading the data or the next
document.
*/
self.showLoadingIndicator(presentation);
/*
Here we are retrieving the template listed in the templateURL property.
*/
resourceLoader.loadResource(templateURL,
function(resource) {
if (resource) {
/*
The XML template must be turned into a DOMDocument in order to be
presented to the user. See the implementation of makeDocument below.
*/
var doc = self.makeDocument(resource);
/*
Event listeners are used to handle and process user actions or events. Listeners
can be added to the document or to each element. Events are bubbled up through the
DOM heirarchy and can be handled or cancelled at at any point.
Listeners can be added before or after the document has been presented.
For a complete list of available events, see the TVMLKit DOM Documentation.
*/
doc.addEventListener("select", self.load.bind(self));
// doc.addEventListener("highlight", self.load.bind(self));
/*
This is a convenience implementation for choosing the appropriate method to
present the document.
*/
if (self[presentation] instanceof Function) {
self[presentation].call(self, doc, ele);
} else {
self.defaultPresenter.call(self, doc);
}
}
}
);
}
},
One idea: templateURL is still pointing to a valid address, thus the lower portion of your shown function will directly add an overlay to your video?
Verify (or make sure) to have only one of the two options (videoURL, templateURL) set. Or only run the loadResource() part if no videoURL was seen before. Like...
if(videoURL) {
...
} else if (templateURL) {
...
}
The problem is with the behaviour of the event "visibilitychange".
It's triggered:
- When I switch to a different tab inside the browser window.
When I click in minimize / restore buttons for the browser window.
(this is ok)
It's not triggered:
- When I switch to a different window/program using ALT+TAB.
When I switch to a different window/program clicking on taskbar.
(this SHOULD trigger, because, just like when minimizing, the window's visibility may change)
W3 Page Visibility API Documentation: http://www.w3.org/TR/page-visibility/
There is no definition of "page visibility" regarding ALT+TAB/program switching in the spec sheet. I'm guessing it has something to do in between the OS and the Browser.
TESTED IN
Browsers:
Chrome 40.0.2214.115 m / Firefox 36.0.1 / Internet Explorer 11.0.9600.17107
OS: Windows 8.1
Is there a workaround to fix this behaviour? The implementation is fairly simple, I listen to the "visibilitychange" event using jQuery, and then in its callback, I check for the value of "document.visibilityState", but the problem is that the event is not firing when expected.
$(document).on('visibilitychange', function() {
if(document.visibilityState == 'hidden') {
// page is hidden
} else {
// page is visible
}
});
This can be done without jQuery too, but the ALT+TAB and taskbar switch hide/show expected behaviour is still missing:
if(document.addEventListener){
document.addEventListener("visibilitychange", function() {
// check for page visibility
});
}
I've also tried the ifvisible.js module (https://github.com/serkanyersen/ifvisible.js) but the behaviour is the same.
ifvisible.on('blur', function() {
// page is hidden
});
ifvisible.on('focus', function() {
// page is visible
});
I haven't tested in other browsers because if I can't make it work in Chrome on Windows I really don't care about the other browsers yet.
Any help or suggestions?
UPDATE
I tried using different vendor prefixes for the event name (visibilitychange, webkitvisibilitychange, mozvisibilitychange, msvisibilitychange) but but still the event is not triggered when I switch to a different program in the taskbar or ALT+TAB, or even if I open the start menu thing in windows with the windows key, which covers the whole screen.
I can reproduce the exact same issue in Chrome, Firefox and Internet Explorer.
UPDATE #2
Here's a roundup post I wrote for this issue and a workaround in pure Javascript to solve the encountered problems.
UPDATE #3
Edited to include a copy of the sourced blog post. (see accepted answer)
Here's a roundup post I wrote for this issue and a workaround in pure JavaScript to solve the encountered problems.
Edited to include a copy of the sourced blog post:
In any kind of javascript application we develop there may be a
feature or any change in the application which reacts according to the
current user visibility state, this could be to pause a playing video
when the user ALT+TABs to a different window, tracking stats about how
the users interact with our application, how often does him switch to
a different tab, how long does it take him to return and a lot of
performance improvements that can benefit from this kind of API.
The Page Visibility API provides us with two top-level attributes:
document.hidden (boolean) and document.visibilityState (which could be
any of these strings: “hidden”, “visible”, “prerender”, “unloaded”).
This would not be not good enough without an event we could listen to
though, that’s why the API also provides the useful visibilitychange
event.
So, here’s a basic example on how we could take action on a visibility
change:
function handleVisibilityChange() {
if(document.hidden) {
// the page is hidden
} else {
// the page is visible
}
}
document.addEventListener("visibilitychange", handleVisibilityChange, false);
We could also check for document.visibilityState value.
Dealing with vendor issues George Berkeley by John Smibert
Some of the implementations on some browsers still need that the
attributes or even the event name is vendor-prefixed, this means we
may need to listen to the msvisibilitychange event or check for the
document.webkitHidden or the document.mozHidden attributes. In order
to do so, we should check if any vendor-prefixed attribute is set, and
once we know which one is the one used in the current browser (only if
there’s the need for a prefix), we can name the event and attributes
properly.
Here’s an example approach on how to handle these prefixes:
var browserPrefixes = ['moz', 'ms', 'o', 'webkit'];
// get the correct attribute name
function getHiddenPropertyName(prefix) {
return (prefix ? prefix + 'Hidden' : 'hidden');
}
// get the correct event name
function getVisibilityEvent(prefix) {
return (prefix ? prefix : '') + 'visibilitychange';
}
// get current browser vendor prefix
function getBrowserPrefix() {
for (var i = 0; i < browserPrefixes.length; i++) {
if(getHiddenPropertyName(browserPrefixes[i]) in document) {
// return vendor prefix
return browserPrefixes[i];
}
}
// no vendor prefix needed
return null;
}
// bind and handle events
var browserPrefix = getBrowserPrefix();
function handleVisibilityChange() {
if(document[getHiddenPropertyName(browserPrefix )]) {
// the page is hidden
console.log('hidden');
} else {
// the page is visible
console.log('visible');
}
}
document.addEventListener(getVisibilityEvent(browserPrefix), handleVisibilityChange, false);
Other issues There is a challenging issue around the “Page Visibility”
definition: how to determine if the application is visible or not if
the window focus is lost for another window, but not the actual
visibility on the screen? what about different kinds of visibility
lost, like ALT+TAB, WIN/MAC key (start menu / dash), taskbar/dock
actions, WIN+L (lock screen), window minimize, window close, tab
switching. What about the behaviour on mobile devices?
There’s lots of ways in which we may lose or gain visibility and a lot
of possible interactions between the browser and the OS, therefore I
don’t think there’s a proper and complete “visible page” definition in
the W3C spec. This is the definition we get for the document.hidden
attribute:
HIDDEN ATTRIBUTE On getting, the hidden attribute MUST return true if
the Document contained by the top level browsing context (root window
in the browser’s viewport) [HTML5] is not visible at all. The
attribute MUST return false if the Document contained by the top level
browsing context is at least partially visible on at least one screen.
If the defaultView of the Document is null, on getting, the hidden
attribute MUST return true.
To accommodate accessibility tools that are typically full screen but
still show a view of the page, when applicable, this attribute MAY
return false when the User Agent is not minimized but is fully
obscured by other applications.
I’ve found several inconsistencies on when the event is actually
fired, for example (Chrome 41.0.2272.101 m, on Windows 8.1) the event
is not fired when I ALT+TAB to a different window/program nor when I
ALT+TAB again to return, but it IS fired if I CTRL+TAB and then
CTRL+SHIFT+TAB to switch between browser tabs. It’s also fired when I
click on the minimize button, but it’s not fired if the window is not
maximized and I click my editor window which is behing the browser
window. So the behaviour of this API and it’s different
implementations are still obscure.
A workaround for this, is to compensate taking advantage of the better
implemented focus and blur events, and making a custom approach to the
whole “Page Visibility” issue using an internal flag to prevent
multiple executions, this is what I’ve come up with:
var browserPrefixes = ['moz', 'ms', 'o', 'webkit'],
isVisible = true; // internal flag, defaults to true
// get the correct attribute name
function getHiddenPropertyName(prefix) {
return (prefix ? prefix + 'Hidden' : 'hidden');
}
// get the correct event name
function getVisibilityEvent(prefix) {
return (prefix ? prefix : '') + 'visibilitychange';
}
// get current browser vendor prefix
function getBrowserPrefix() {
for (var i = 0; i < browserPrefixes.length; i++) {
if(getHiddenPropertyName(browserPrefixes[i]) in document) {
// return vendor prefix
return browserPrefixes[i];
}
}
// no vendor prefix needed
return null;
}
// bind and handle events
var browserPrefix = getBrowserPrefix(),
hiddenPropertyName = getHiddenPropertyName(browserPrefix),
visibilityEventName = getVisibilityEvent(browserPrefix);
function onVisible() {
// prevent double execution
if(isVisible) {
return;
}
// change flag value
isVisible = true;
console.log('visible}
function onHidden() {
// prevent double execution
if(!isVisible) {
return;
}
// change flag value
isVisible = false;
console.log('hidden}
function handleVisibilityChange(forcedFlag) {
// forcedFlag is a boolean when this event handler is triggered by a
// focus or blur eventotherwise it's an Event object
if(typeof forcedFlag === "boolean") {
if(forcedFlag) {
return onVisible();
}
return onHidden();
}
if(document[hiddenPropertyName]) {
return onHidden();
}
return onVisible();
}
document.addEventListener(visibilityEventName, handleVisibilityChange, false);
// extra event listeners for better behaviour
document.addEventListener('focus', function() {
handleVisibilityChange(true);
}, false);
document.addEventListener('blur', function() {
handleVisibilityChange(false);
}, false);
window.addEventListener('focus', function() {
handleVisibilityChange(true);
}, false);
window.addEventListener('blur', function() {
handleVisibilityChange(false);
}, false);
I welcome any feedback on this workaround. Some other great sources
for ideas on this subject:
Using the Page Visibility API Using PC Hardware more efficiently in
HTML5: New Web Performance APIs, Part 2 Introduction to the Page
Visibility API Conclusion The technologies of the web are continuously
evolving, we’re still recovering from a dark past where tables where
the markup king, where semantics didn’t mattered, and they weren’t any
standards around how a browser should render a page.
It’s important we push these new standards forward, but sometimes our
development requirements make us still need to adapt to these kind of
transitions, by handling vendor prefixes, testing in different
browsers and differents OSs or depend on third-party tools to properly
identify this differences.
We can only hope for a future where the W3C specifications are
strictly revised, strictly implemented by the browser developer teams,
and maybe one day we will have a common standard for all of us to work
with.
As for the Page Visibility API let’s just kinda cite George Berkeley
and say that:
“being visible” is being perceived.
A working solution is proposed described here: https://stackoverflow.com/a/9502074/698168. It uses a combination of the W3C Page Visibility API, blur/focus and mouse movements. Hidden HTML pages related to Alt+Tab are identified in a probabilistic way (i.e. you cannot determine if your page is hidden with 100% accuracy).
we can do like below when switching between tabs and switching between applications
var pageVisible = true;
function handleVisibilityChange() {
if (document.hidden) {
pageVisible = false;
} else {
pageVisible = true;
}
console.log("handleVisibilityChange")
console.log("pageVisible", pageVisible)
// some function call
}
document.addEventListener("visibilitychange", handleVisibilityChange, false);
window.addEventListener('focus', function() {
pageVisible = true;
// some function call
}, false);
window.addEventListener('blur', function() {
pageVisible = false;
// some function call
}, false);
There's a very simple solution to this I have come across.
You just need to pass false to the useCapture while attaching an event listener to the document. Works like a charm!
document.addEventListener('visibilitychange', function () {
// code goes here
}, false)
I am writing some JS code to relink an image, then resize it to fit the containing object. Simplified version of code:
var image = (get image);
try {
image.itemLink.relink(File(new_filename));
}
catch(e) {
(log it);
}
var image = (find image again because after the relink it would otherwise cause error "Object no longer exists")
(work out new width, height, v offset, h offset);
try {
if(image.locked) {
lock_later = true;
image.locked = false;
}
}
catch(e) { }
// Resize and reposition image
image.geometricBounds = [(rectangle.geometricBounds[0] + h_offset) + "mm", (rectangle.geometricBounds[1] + w_offset) + "mm", (rectangle.geometricBounds[2] - h_offset) + "mm", (rectangle.geometricBounds[3] - w_offset) + "mm"];
// Lock the image again if it was locked before
if(lock_later) {
image.locked = true;
}
With the try/catch block around the if(image.locked) block, the resize line throws the error "Image is locked" (because it fails to unlock it). Without the try/catch but keeping the if(image.locked) block, it throws the error "The property is not applicable in the current state." when trying to access image.locked.
So what "state" is my image in, and why is it not "applicable" even though the app is clearly using it to prevent me resizing it? How do I resize my image, given that this is an automated process and in production I won't have access to InDesign to edit it manually beforehand?
As stated in Adobe's documentation, an image container -- the parent frame 'around' an image, which is a generic SplineItem -- can be locked and unlocked by changing the read/write boolean property locked.
In InDesign CS4 and earlier, the Graphic Class did not have this property, but since InDesign CS5 onwards, the property locked also appears in there and in all of its derived classes. According to Adobe's documentation it is a read/write property. However, this appears to be wrong. Experimenting with CS6, I found the locked property of a graphic inside its parent frame only reflects the parent's state, and is in fact read-only.
In the InDesign user interface in CS4 and earlier, the menu item "Lock" is disabled when a graphic inside a frame is selected. In the user interface from CS5 and later, a locked item cannot be selected, so the menu item cannot be invoked.
The easiest workaround, given a handle to a graphic image, is to check and/or change the state through its parent:
image = app.activeDocument.allGraphics[0]; // a handle to the first graphic
image.parent.locked = false; // unlock it