I'm going crazy trying to get daydream controls to work in a my AFrame app. I'm not sure if it's my code, or my browser... Does anyone have an example that should work with the daydream controller?
This should be quite simple. Just use the official daydream component:
<a-entity daydream-controls="hand: left"></a-entity>
<a-entity daydream-controls="hand: right"></a-entity>
and utilize the emited events:
AFRAME.registerComponent("daydream-listener", {
init: function() {
this.el.addEventListener("trackpaddown", (e) => {
console.log("track down: ");
console.log(e);
})
}
})
<a-entity daydream-controls daydream-listener></a-entity>
live fiddle here.
Related
I've been trying to add a tooltip to a button that only shown when certain conditions are met. I'm using uikit#3.0.0-beta.35. According to the documentation, I should return false on beforeshow event.
UIkit.tooltip($element, { pos: 'top' });
$element.on('beforeshow', function(){
return false;
});
if(condition){
UIkit.tooltip($element).show();
}
The problem is that the beforeshow function never fires for some reason. I even tried this syntax mentioned in UIkit documentation:
UIkit.util.on($element, 'beforeshow', function () {
return false;
});
Unfortunately, none of these methods worked for me.
the docs has some mistake, switcher has the same problem. the event is triggered on document not the target. you can use this syntax like this:
UIkit.util.on(document, 'event', '#target-id', callback)
the docs confused me a long time :(
The problem with your code is, that you're trying to listen to an event directly on the element, while the event is triggered on the document - there is an error in the documentation, as they say it's triggered on the element, but it's not.
There is also a fresh false bug report regarding this
var $element = $('#hoverButton');
var $check = $('#tooltipToggle');
UIkit.tooltip($element);
$(document).on('beforeshow', $element, function() {
if (!$check.prop('checked')) return false;
});
<!-- UIkit CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.0-beta.35/css/uikit.min.css" />
<!-- UIkit JS & jQuery (not required by UIKit anymore) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.0-beta.35/js/uikit.min.js"></script>
<div class="uk-position-center">
<label>show tooltip <input id="tooltipToggle" class="uk-checkbox" type="checkbox"></label><br><br>
<button id="hoverButton" class="uk-button uk-button-default" title="Hello World">Hover</button>
</div>
For Switcher:
$(document).on('show', $('#switcherId'), function(){
console.log('fired');
});
I may need this answer in the future too...
I'm trying to find out if there is a way to determine which Vive controller is being used when there is only a single one. With OpenVR this information is available. I'm wondering if this is possible with A-Frame?
When you set the controllers, you set the handedness:
<a-entity id="leftHand" vive-controls="hand: left"></a-entity>
<a-entity id="rightHand" vive-controls="hand: right"></a-entity>
Just see which one of those hands becomes active. You could check its position/rotation are non-zero. Or in the upcoming release, you could do like:
AFRAME.registerComponent('controller-connected', {
init: function () {
var el = this.el;
el.addEventListener('controllerconnected', function (evt) {
console.log(evt.detail.component.data.hand);
// Or... console.log(el.getAttribute(evt.detail.name).hand)
});
}
});
<a-entity controller-connected id="leftHand" vive-controls="hand: left"></a-entity>
<a-entity controller-connected id="rightHand" vive-controls="hand: right"></a-entity>
A-Frame currently uses just the index of the Gamepad array to determine left/right. To manually check which controller is connected, you can call the Gamepad API:
navigator.getGamepads();
I've got a non-angular page made with fairly basic JS, and thought it'd be a splendid idea to try and add learn some Angular2 and use it for some new functionality.
My plan was that I'd bind an Angular2 component to an object that is being updated by the old code, and I'd use Angular2 magic to update a chunk of UI.
The problem is I cant convince Angular2 to react to any changes made in the outside JS. What the trick to doing that? Attempts at googling the problem lead to in depth explanations of Angular2's change detection process, which hasn't been helpful so far. Is this just an awful idea?
I found a random Angular2 jsfiddle and hacked it up to show the problem. Strings are added to 'window.names', but you dont see them until one is added from the angular side: https://jsfiddle.net/byfo3jg3/ . The code follows:
var names = ['Joe'];
setTimeout(function() {
names.push("Frank");
}, 1000);
setTimeout(function() {
names.push("Sterve");
}, 2000);
setTimeout(function() {
names.push("Garfield");
}, 3000);
(function() {
var HelloApp,
ListThing;
ListThing = ng
.Component({
selector: 'list-thing',
template: '<ul><li *ng-for="#name of names">{{name}}</li></ul>',
directives: [ng.NgFor]
})
.Class({
constructor: function() {
this.names = window.names;
setTimeout(function() {
this.names.push("Oh hai");
}.bind(this), 10000);
}
});
HelloApp = ng
.Component({
selector: 'hello-app',
template: '<list-thing></list-thing>',
directives: [ListThing]
})
.Class({
constructor: function() {}
});
document.addEventListener('DOMContentLoaded', function() {
ng.bootstrap(HelloApp);
});
}());
You will need to set the NgZone to window object and then call run function of the zone.
Please refer to Angular 2 How to get Angular to detect changes made outside Angular? SO Question
names should be component property to work inside of template:
constructor(){this.names = window.names}
Changes to window.names will not be detected by angular, so you have few options: poll names using setInterval(()=>{this.names = window.names}, 1000) or expose global callback:
constructor(zone:NgZone)
{
window.notify = ()=> {
zone.run(()=> {
this.names = window.names;
});
}
}
and call it from plain js window.notify() or use other methods to invoke change detection.
Is this just an awful idea?
Yes.
Angular's automatic change detection system assumes that changes to data (that you want your components to display) are happening inside an event handler that is monkey-patched by Zone.js. Because then Angular's change detection will execute when such an event handler fires (well, technically, it will execute after the event handler finishes).
If you want a component view to automatically update, you have to change the bound data inside Angular – inside the Angular zone. As #Jigar answered, you can modify your code to call angularZone.run(_ => // make changes here), but if you have to do that, you might as well move the code that manages and manipulates the data into a service (or a component, if the logic is minimal).
See also Günter's alternative approach: set up an event listener inside Angular (hence inside the Angular zone). Then fire that event whenever you make changes outside the Angular zone.
Meteor Router.go() doesn't work. It just flash a new url for few milliseconds in the browser, and the page didn't switch.
Sorry I can't find any clue how this wired thing happen..!
Template.Post.events({
'click a': function() {
Router.go('mainPage');
});
Router.route('/', {
name: 'mainPage',
template: 'mainPage'
});
Update: I input Router.go('mainPage'); in Chrome console. It works and return undefined.
To avoid this miserable, horrible experience for everyone, let me post my solution and answer myself:
When Router.go() redirects the URL, the URL also instantly redirects to href="#" or href="". Thus, it disables the redirection from Router.go().
The way to solve it is just to NOT put href="" in the <a> tag. Also, you can add this css:
a:hover {
cursor: pointer;
}
to show that the tag is actually clickable.
You can avoid having to remove the href by calling event.preventDefault() which stops the execution of any additional bubbled events like the href click:
"click #aLinkId": function(event, template) {
event.preventDefault();
Router.go('/newLocation');
}
I had this problem too, wrapping it in Meteor.setTimeout was the only way to make it work.
'click a': function() {
Meteor.setTimeout(function(){ Router.go('mainPage'); }, 10);
}
Can we see your Router definitions?
At least setup one route:
Router.route('/mainPage', {
template: 'mainPage'
});
Documentation can be found here: https://github.com/iron-meteor/iron-router/blob/devel/Guide.md
Following the example here I've tried doing the same but the query doesnt work for me.
http://jsfiddle.net/qDbd5/
require(["dojo/parser", "dijit/Toolbar", "dijit/form/ToggleButton", "dojo/query", "dojo/dom-class", "dojo/on", "dojo/domReady!"], function (parser, ToolBar, ToggleButton, query, domClass, on) {
on(query(".dijitToggleButton"), "click", function (e) {
query(".dijitToggleButton").forEach(function (node) {
console.log('Captured clicked event');
domClass.remove(node, "dijitToggleButtonChecked dijitToggleButtonRtlChecked dijitRtlChecked dijitChecked");
});
domClass.add(this, "dijitToggleButtonChecked dijitToggleButtonRtlChecked dijitRtlChecked dijitChecked");
});
});
I'm trying to make only 1 button toggle at a time.
Why the click event not triggered?
Wrapping everything in a ready() callback solves the problem.
See http://jsfiddle.net/cFQGq/
require(["dojo/ready", "dojo/parser", "dijit/Toolbar", "dijit/form/ToggleButton", "dojo/query", "dojo/dom-class", "dojo/on", "dojo/domReady!"], function (ready, parser, ToolBar, ToggleButton, query, domClass, on) {
ready(function() {
on(query(".dijitToggleButton"), "click", function (e) {
query(".dijitToggleButton").forEach(function (node) {
console.log('Captured clicked event');
domClass.remove(node, "dijitToggleButtonChecked dijitToggleButtonRtlChecked dijitRtlChecked dijitChecked");
});
domClass.add(this, "dijitToggleButtonChecked dijitToggleButtonRtlChecked dijitRtlChecked dijitChecked");
});
});
});
If you look at the explanation of domReady!, it mentions that it is insufficient for working with dojo widgets, because it executes after the DOM has loaded instead of after the widget has finished initializing. dojo/ready executes the callback after the widgets have finished loading.