How can I detect when Mapbox or Leaflet enters or exits fullscreen mode?
I found this answer where someone said this:
Documentation says:
map.on('fullscreenchange', function () {
if (map.isFullscreen()) {
console.log('entered fullscreen');
} else {
console.log('exited fullscreen');
}
});
If doesnt work, use this instead:
map.on('enterFullscreen', function(){
});
map.on('exitFullscreen', function(){
});
I tried that, as well as a few variations of the event type parameter. No dice.
Also, the documentation doesn't mention an event for this.
Note that I am using Mapbox GL JS.
I know this is a late response but to anyone in the future this is how I approached it (for mapbox GL JS (without leaflet).
map.on("resize", () => {
if (document.fullscreenElement) // do something
});
You can give the map wrapper div a name and exclusively also check if the map is what triggered the fullscreen event
map.on("resize", () => {
if (document.fullscreenElement?.attributes.name.value === "mapWrapper") // do something
});
And if you are using React you can use a state to hold this information.
const [isFullScreen, setIsFullScreen] = useState();
...
map.on("resize", () => {
setIsFullScreen(
document.fullscreenElement?.attributes.name.value === "mapWrapper"
);
});
...
if (isFullScreen) //do something
This is actually really simple. You don't need anything from Leaflet or Mapbox. Just use an event listener on the document object.
let fullScreenChange;
if ('onfullscreenchange' in window.document) {
fullScreenChange = 'fullscreenchange';
} else if ('onmozfullscreenchange' in window.document) {
fullScreenChange = 'mozfullscreenchange';
} else if ('onwebkitfullscreenchange' in window.document) {
fullScreenChange = 'webkitfullscreenchange';
} else if ('onmsfullscreenchange' in window.document) {
fullScreenChange = 'MSFullscreenChange';
}
function onFullscreenChange() {
// Your stuff.
}
window.document.addEventListener(fullScreenChange, onFullscreenChange);
Related
I've followed this tutorial which outlines adding monitoring beacons in an Ionic 2 application. I have it working great: when the view loads, it initializes and begins listening for beacons:
home.ts
ionViewDidLoad() {
this.platform.ready().then(() => {
this.beaconProvider.initialise().then((isInitialised) => {
if (isInitialised) {
this.listenToBeaconEvents();
}
});
});
}
This calls the listenToBeaconEvents function which populates a list in the view with all of the beacons:
home.ts
listenToBeaconEvents() {
this.events.subscribe(‘didRangeBeaconsInRegion’, (data) => {
// update the UI with the beacon list
this.zone.run(() => {
this.beacons = [];
let beaconList = data.beacons;
beaconList.forEach((beacon) => {
let beaconObject = new BeaconModel(beacon);
this.beacons.push(beaconObject);
});
});
});
}
I'm able to stop ranging using this.beaconProvider.stopRanging() that calls a function from the below function:
beacon-provider.ts
stopRanging() {
if (this.platform.is('cordova')) {
// stop ranging
this.ibeacon.stopRangingBeaconsInRegion(this.region)
.then(
() => {
console.log('Stopped Ranging');
},
error => {
console.error('Failed to stop monitoring: ', error);
}
);
}
}
The problem I'm having is this - in the original tutorial the beacon list is shown at the root, there's no other navigation. I've moved it to a different view, and if the user exits and re-enters the view, it re-initializes and loads everything, resulting in duplicate list entries.
I've tried creating a function within beacon-provider.ts to call before the view exits, but I can't figure out how to keep the subscriptions/events from duplicating.
I've tried this.delegate.didRangeBeaconsInRegion().unsubscribe(), and some other variations but they all result in runtime errors.
In your case you are using Ionic's Events API which has its own unsubscribe(topic, handler) function.
In your component, whenever you need to unsubscribe, you should call this with the same topic:
this.events.unsubscribe(‘didRangeBeaconsInRegion’);
This will remove all handlers you may have registered for the didRangeBeaconsInRegion.
If you want to unsubscribe one specific function, you will have to have registered a named handler which you can send with unsubscribe.
this.events.unsubscribe(‘didRangeBeaconsInRegion’,this.mySubscribedHandler);
And your home.ts would look like:
mySubscribedHandler:any = (data) => {
// update the UI with the beacon list
this.zone.run(() => {
this.beacons = [];
let beaconList = data.beacons;
beaconList.forEach((beacon) => {
let beaconObject = new BeaconModel(beacon);
this.beacons.push(beaconObject);
});
});
}
listenToBeaconEvents() {
this.events.subscribe(‘didRangeBeaconsInRegion’,this.mySubscribedHandler);
}
I looked everywhere on the internet but I couldn't find any clear documentation or some examples to create my verySimplePlugin for videoJS 5 (Since it uses ES6).
I just want to add a button next to the big play button... Can someone help me?
Thanks...
PS: I'm using it in angularJS but I guess this can not a problem
This is how you can add download button to the end of control bar without any plugins or other complicated code:
var vjsButtonComponent = videojs.getComponent('Button');
videojs.registerComponent('DownloadButton', videojs.extend(vjsButtonComponent, {
constructor: function () {
vjsButtonComponent.apply(this, arguments);
},
handleClick: function () {
document.location = '/path/to/your/video.mp4'; //< there are many variants here so it is up to you how to get video url
},
buildCSSClass: function () {
return 'vjs-control vjs-download-button';
},
createControlTextEl: function (button) {
return $(button).html($('<span class="glyphicon glyphicon-download-alt"></span>').attr('title', 'Download'));
}
}));
videojs(
'player-id',
{fluid: true},
function () {
this.getChild('controlBar').addChild('DownloadButton', {});
}
);
I used 'glyphicon glyphicon-download-alt' icon and a title for it so it fits to the player control bar styling.
How it works:
We registering a new component called 'DownloadButton' that extends built-in 'Button' component of video.js lib
In constructor we're calling constructor of the 'Button' component (it is quite complicated for me to understand it 100% but it is similar as calling parent::__construct() in php)
buildCSSClass - set button classes ('vjs-control' is must have!)
createControlTextEl - adds content to the button (in this case - an icon and title for it)
handleClick - does something when user presses this button
After player was initialized we're adding 'DownloadButton' to 'controlBar'
Note: there also should be a way to place your button anywhere within 'controlBar' but I haven't figured out how because download button is ok in the end of the control bar
This is how I created a simple button plugin for videojs 5:
(function() {
var vsComponent = videojs.getComponent('Button');
// Create the button
videojs.SampleButton = videojs.extend(vsComponent, {
constructor: function() {
vsComponent.call(this, videojs, null);
}
});
// Set the text for the button
videojs.SampleButton.prototype.buttonText = 'Mute Icon';
// These are the defaults for this class.
videojs.SampleButton.prototype.options_ = {};
// videojs.Button uses this function to build the class name.
videojs.SampleButton.prototype.buildCSSClass = function() {
// Add our className to the returned className
return 'vjs-mute-button ' + vsComponent.prototype.buildCSSClass.call(this);
};
// videojs.Button already sets up the onclick event handler, we just need to overwrite the function
videojs.SampleButton.prototype.handleClick = function( e ) {
// Add specific click actions here.
console.log('clicked');
};
videojs.SampleButton.prototype.createEl = function(type, properties, attributes) {
return videojs.createEl('button', {}, {class: 'vjs-mute-btn'});
};
var pluginFn = function(options) {
var SampleButton = new videojs.SampleButton(this, options);
this.addChild(SampleButton);
return SampleButton;
};
videojs.plugin('sampleButton', pluginFn);
})();
You can use it this way:
var properties = { "plugins": { "muteBtn": {} } }
var player = videojs('really-cool-video', properties , function() { //do something cool here });
Or this way:
player.sampleButton()
I have code like this:
element(by.model("roleSelection.role")).element(by.cssContainingText('option', newRole)).click();//.then(function() {console.log('role click')})//;
where the options is loaded via a call to the server.
I can wait for the first element by doing this
browser.wait(function() {
return browser.isElementPresent(by.model("roleSelection.role")).then(function(present){
return present;
});}, 8000);
and it seems to work. But how can I wait until the "sub-element" is clickable.
I have tried this
browser.wait(function() {
return browser.isElementPresent(by.model("roleSelection.role")).then(function(present){
if (present) {
var elm = element(by.model("roleSelection.role"));
return elm.isElementPresent(by.cssContainingText('option', newRole)).then(function(subpresent) {
return subpresent;
});
}
}); }, 8000);
Have you tried clickable? Something along these lines
var EC = protractor.ExpectedConditions;
var select = element(by.model("roleSelection.role"))
var isClickable = EC.elementToBeClickable(select);
browser.wait(isClickable,5000); //now options should have been loaded by now
Well, try to this: https://angular.github.io/protractor/#/api?view=ExpectedConditions.prototype.elementToBeClickable
But, Please keep in mind, Protractor is suitable for angular webpages and interactions, and animations. For example ng-animate. So, it is not sure to working for example jquery, or other animates.
In this way:
onPrepare: function () {
// disable animations when testing to speed things up
var disableNgAnimate = function () {
angular.module('disableNgAnimate', []).run(function ($animate) {
$animate.enabled(false);
});
};
browser.addMockModule('disableNgAnimate', disableNgAnimate);
}
Or you can switch in script way in browser.executeScript().
Please see this link. It works only jquery animations.
If you not have animate problems. Use setTimeout() JS function.
We are currently using the soundcloud API SDK for streaming and it does work on desktop but not 100% on mobile. (using responsive html. same api of course)
Sometime track is not lauch ? sometime it is.
I do not have specific error but on chrome network this line is show in red ??
http://api.soundcloud.com/tracks/146926142/stream?client_id=XXXXX
Redirect
We use a function to stream the track.
function streamTrack(id) {
var defer = $q.defer();
// Stream the track
SC.stream('/tracks/' + id, {
useHTML5Audio: false,
waitForWindowLoad: true,
onfinish: _scope.next,
whileplaying: function () {
var _this = this;
// Since we are in a callback, we need to tell angularJS to apply the change
if (timeout1) $timeout.cancel(timeout1);
timeout1 = $timeout(function () {
// Update the progress bar
_scope.progress = (_this.position / currentTrackDuration * 100) + '%';
_scope.timer = moment(_this.position).format('mm:ss');
$rootScope.$broadcast('trackRunning', { timerunning: _scope.timer });
});
}
}, function (sound) {
if (sound) {
defer.resolve(sound);
} else {
defer.reject();
}
});
return defer.promise;
}
If somebody has an idea pls.
Best Regards
Xavier
Know if it's possible to access the iPhone compass in Safari using JavaScript? I see how the GPS can be accessed, but I can't figure out the compass.
On iOS, you can retrieve the compass value like this.
window.addEventListener('deviceorientation', function(e) {
console.log( e.webkitCompassHeading );
}, false);
For more informations, read the Apple DeviceOrientationEvent documentation.
Hope this helps.
You cannot access that information via javascript, unless you're using something like iPhoneGap
At the time this was true, in iOS 5 you can use the compass heading in JS. https://developer.apple.com/documentation/webkitjs/deviceorientationevent/1804777-webkitcompassheading
For Android it works auto, for iOS it needs to be clicked to start it.
Here's a part of code you can use for that
startBtn.addEventListener("click", startCompass);
function startCompass() {
if (isIOS) {
DeviceOrientationEvent.requestPermission()
.then((response) => {
if (response === "granted") {
window.addEventListener("deviceorientation", handler, true);
} else {
alert("has to be allowed!");
}
})
.catch(() => alert("not supported"));
} else {
window.addEventListener("deviceorientationabsolute", handler, true);
}
}
function handler(e) {
const degree = e.webkitCompassHeading || Math.abs(e.alpha - 360);
}
Full tutorial is here, try demo also
https://dev.to/orkhanjafarovr/real-compass-on-mobile-browsers-with-javascript-3emi
I advise you to use LeafletJS with this plugin
https://github.com/stefanocudini/leaflet-compass
very simple to use with events and methods.
You can try a demo here:
https://opengeo.tech/maps/leaflet-compass/