A-Frame not removing attribute after function being initialized in a component. - event-handling

I am trying to add a on click handler that will toggle the light attribute on an entity when a separate entity is clicked. However nothing is happening when I click the separate entity, and I have no errors in my console.
Here is my component:
AFRAME.registerComponent("lightsOut", {
schema: {
target : { type : "selector"}
},
init: function(){
this.el.addEventListener("click",function(){
this.data.target.removeAttribute("light");
}.bind(this));
}
})
And here are the two entities:
<a-entity id="streetLamp"
obj-model="obj:./models/streetlamp/StreetLamp.obj;mtl:./models/streetlamp/StreetLamp.mtl"
material="color:black"
scale="0.3 0.6 0.5"
position="-7.138 -1.499 -11.711"
lightsOut="target:#streetLight">
</a-entity>
<a-entity id="streetLight"
position="-4.961 6.205 -11.962"
rotation="-67.208 -112.987 87.548"
scale="0.657 0.612 0.718"
light="distance:15;decay:2;intensity:5a;angle:90;color:#ff8000;groundColor:#ffffff;penumbra:0.5;castShadow:true;type:point"
></a-entity>
When I click streetLamp, I would like to remove or hide streetLight. I am using cursor controls.

You can't have a uppercase letter in the component name, a-frame will try to make it lowercase, (...) in the end it won't work.
Try naming it lightsout or lights_out. Throw in a console.log() when clicked, to be sure it's properly working.
Also You need to refresh the raycaster manually, using raycaster.refreshObjects(), it's a bug, which is fixed by december 2017 in the master build.

Related

How to access control from the popup fragment by ID

I want my text area to be empty after I press OK button.
I have try this line this.byId("id").setValue("")
onWorkInProgress: function (oEvent) {
if (!this._oOnWorkInProgressDialog) {
this._oOnWorkInProgressDialog = sap.ui.xmlfragment("WIPworklist", "com.sap.FinalAssestments.view.WorkInProgress", this);
//this.byId("WIP").value = "";
//this.byId("WIP").setValue();
this.getView().addDependent(this._oOnWorkInProgressDialog);
}
var bindingPath = oEvent.getSource().getBindingContext().getPath();
this._oOnWorkInProgressDialog.bindElement(bindingPath);
this._oOnWorkInProgressDialog.open();
},
//function when cancel button inside the fragments is triggered
onCancelApproval: function() {
this._oOnWorkInProgressDialog.close();
},
//function when approval button inside the fragments is triggered
onWIPApproval: function() {
this._oOnWorkInProgressDialog.close();
var message = this.getView().getModel("i18n").getResourceBundle().getText("wipSuccess");
MessageToast.show(message);
},
The text area will be in popup in the fragment. I am expecting the text area to be empty.
If you instantiate your fragment like this:
sap.ui.xmlfragment("WIPworklist", "com.sap.FinalAssestments.view.WorkInProgress", this);
You can access its controls like this:
Fragment.byId("WIPworklist", "WIP").setValue(""); // Fragment required from "sap/ui/core/Fragment"
Source: How to Access Elements from XML Fragment by ID
The better approach would be to use a view model. The model should have a property textAreaValue or something like that.
Then bind that property to your TextArea (<TextArea value="{view>/textAreaValue}" />). If you change the value using code (e.g. this.getView().getModel("view").setProperty("/textAreaValue", "")), it will automatically show the new value in your popup.
And it works both ways: if a user changes the text, it will be automatically updated in the view model, so you can access the new value using this.getView().getModel("view").getProperty("/textAreaValue");.
You almost have it, I think. Just put the
this.byId("WIP").setValue("") line after the if() block. Since you are adding the fragment as a dependent of your view, this.byId("WIP") will find the control with id "WIP" every time you open the WIP fragment and set its value to blank.
You are likely not achieving it now because A. it is not yet a dependent of your view and B. it is only getting fired on the first go-around.

TooltipBaseRenderer.js: 404 - NOT FOUND

I extended sap.ui.core.TooltipBase with mouseover event handling which is attached to some sap.ui.core.Icon in the ChartContainer:
sap.ui.define(function () {
"use strict";
return sap.ui.core.TooltipBase.extend("dvd.rl.component.ChartContainer.parts.TooltipBase.TooltipBase", {
metadata: {
events: {
"onmouseover" : {}
}
},
oView: null,
setView : function(view){
this.oView = view;
},
// the hover event handler, it is called when the Button is hovered - no event registration required
onmouseover : function() {},
});
Everythink works well, but when I click on the Icon in the ChartContainer I got this error from the TooltipBaseRenderer.js (This happens before handling of press event.):
In the TooltipBaseRenderer.js it is this line:
I have no idea what is going on there. If you will have I will be happy to hear it.
This is how I added TooltipBase to sap.ui.core.Icon:
// Add custom Icon for filter
var oFilterIcon = new sap.ui.core.Icon("filterButton", {
tooltip : "{i18n>filter}",
src : "sap-icon://filter",
press : [this.onHandleLocalFilterOpen,this]
});
// Add Icon to chart component
oChartContainer.addCustomIcon(oFilterIcon);
var oTooltipBase = new TooltipBase();
// set new TooltipBase to Icon
oFilterIcon.setTooltip(oTooltipBase);
EDITED 12:15 100117:
When I use renderer in the TooltipBase.extend:
//just inherit the renderer as it is
renderer: {},
I got this error:
So I removed renderer, and TooltipBase works when I hover over Icon. The problem is when I click on the Icon as I described higher.
Here is a working sample custom tooltip extended from sap/ui/core/TooltipBase.
Make sure that your renderer has the render method. Otherwise UI5 will look for it at the parent. Also TooltipBase already handles the mouse events. No need to handle them in your extension.
This is what happened:
Your renderer had no render function (renderer: { }).
UI5 looks for the render in the parent renderer (sap/ui/core/TooltipBaseRenderer).
There is no TooltipBaseRenderer.js since TooltipBase is an abstract control. Abstract controls have no renderer (renderer: null // not undefined in their definition).
Usually, UI5 bypasses fetching the renderer for abstract controls but the TooltipBase was unfortunately missing the renderer: null. So UI5 assumed that there must be a file named TooltipBaseRenderer.js which resulted in the 404 error. As of UI5 1.82, the TooltipBase has renderer: null, so the issue is no longer reproducible.

Algolia autocomplete js with select2

I am using aloglia autocomplete.js and followed the tutorial.
I want to use autocomplete text box with others select2 selectbox.
var client = algoliasearch('YourApplicationID','YourSearchOnlyAPIKey')
var index = client.initIndex('YourIndex');
autocomplete('#search-input', { hint: false }, [
{
source: autocomplete.sources.hits(index, { hitsPerPage: 5 }),
displayKey: 'my_attribute',
templates: {
suggestion: function(suggestion) {
return suggestion._highlightResult.my_attribute.value;
}
}
}
]).on('autocomplete:selected', function(event, suggestion, dataset) {
console.log(suggestion, dataset);
$("#search-input").val(suggestion.full_name.name)
});
Problem is when I clicked anywhere beside that autocomplete box autocomplete disappear and it showed only what I typed before.
I don't want it to disappear. How can I implement it? Thanks for helping.
Please see the example below for detail problem.
Assume you have a simple form with one auto complete input field,two select2 boxes and one submit button. After you choose auto complete filed, when you click anywhere, it changed to default text. I mean, you put "piz" and it shows "pizza". Therefore you select pizza and it display "pizza".Then, you try to choose one select2 box or click anywhere. The autocomplete input field changed back to "piz".
I tried autocomplete:closed , $("#search-input").focusout to set the input field but it just changed back to my query.
To prevent it from disappearing, you can use autocomplete.js's debug option:
autocomplete('#search-input', { hint: false, debug: true }, [ /* ... */ ]);
The complete options list is available on GitHub.
Now I have it. When you need to only select and not to do any action, you can safety remove autocomplete:selected. And make sure your display key is value not object.
It saves me for trouble.

Switch class on tabs with React.js

So I have a tab-component that has 3 items:
React.DOM.ul( className: 'nav navbar-nav',
MenuItem( uid: 'home')
MenuItem( uid: 'about')
MenuItem( uid: 'contact)
)
And in the .render of MenuItem:
React.DOM.li( id : #props.uid, className: #activeClass, onClick: #handleClick,
React.DOM.a( href: "#"+#props.uid, #props.uid)
)
Every time I click an item, a backbone router gets called, which will then call the tab-component, which in turn will call a page-component.
I'm still trying to wrap my head around the fact there's basically a one-way data-flow. And I'm so used to manipulating the DOM directly.
What I want to do, is add the .active class to the tab clicked, and make sure it gets removed from the inactive ones.
I know the CSS trick where you can use a data- attribute and apply different styling to the attribute that is true or false.
The backbone router already has already gotten the variable uid and calls the right page. I'm just not sure how to best toggle the classes between tabs, because only one can be active at the same time.
Now I could keep some record of which tab is and was selected, and toggle them etc. But React.js already has this record-keeping functionality.
The #handleClick you see, I don't even want to use, because the router should tell the tab-component which one to give the className: '.active' And I want to avoid jQuery, because React.js doesn't need direct DOM manipulation.
I've tried some things with #state but I know for sure there is a really elegant way to achieve this fairly simple, I think I watched some presentation or video of someone doing it.
I'm really have to get used to and change my mindset towards thinking React-ively.
Just looking for a best practice way, I could solve it in a really ugly and bulky way, but I like React.js because it's so simple.
Push the state as high up the component hierarchy as possible and work on the immutable props at all levels below. It seems to make sense to store the active tab in your tab-component and to generate the menu items off data (this.props in this case) to reduce code duplication:
Working JSFiddle of the below example + a Backbone Router: http://jsfiddle.net/ssorallen/4G46g/
var TabComponent = React.createClass({
getDefaultProps: function() {
return {
menuItems: [
{uid: 'home'},
{uid: 'about'},
{uid: 'contact'}
]
};
},
getInitialState: function() {
return {
activeMenuItemUid: 'home'
};
},
setActiveMenuItem: function(uid) {
this.setState({activeMenuItemUid: uid});
},
render: function() {
var menuItems = this.props.menuItems.map(function(menuItem) {
return (
MenuItem({
active: (this.state.activeMenuItemUid === menuItem.uid),
key: menuItem.uid,
onSelect: this.setActiveMenuItem,
uid: menuItem.uid
})
);
}.bind(this));
return (
React.DOM.ul({className: 'nav navbar-nav'}, menuItems)
);
}
});
The MenuItem could do very little aside from append a class name and expose a click event:
var MenuItem = React.createClass({
handleClick: function(event) {
event.preventDefault();
this.props.onSelect(this.props.uid);
},
render: function() {
var className = this.props.active ? 'active' : null;
return (
React.DOM.li({className: className},
React.DOM.a({href: "#" + this.props.uid, onClick: this.handleClick})
)
);
}
});
You can try react-router-active-componet - if you working with boostrap navbars.
You could try to push the menu item click handler up to it's parent component. In fact I am trying to do something similar to what you are doing.. I have a top level menubar component that I want to use a menubar model to render the menu bar and items. Other components can contribute to the top level menubar by adding to the menubar model... simply adding the top level menu, the submenuitem, and click handler (which is in the component adding the menu). The top level component would then render the menubar UI and when anything is clicked, it would use the "callback" component click handler to call to. By using a menu model, I can add things like css styles for actice/mouseover/inactive, etc, as well as icons and such. The top level menubar component can then decide how to render the items, including mouse overs, clicks, etc. At least I think it can.. still working on it as I am new to ReactJS myself.

How to programmatically fire keydown event in ExtJS 4

In ExtJs 4 how can I programmatically fire 'keydown' (or 'keypress') event (on TAB key) ?
I should want to simulate a TAB key pression in response to another event.
I have tried with code (in this event handler) :
field.fireEvent('keydown', {keyCode: 9})
but it's not working...
You may have to spy your DOM a bit (to see what elements are there, like fileInputEl in the example below), but this works for me:
var uploadField = Ext.getCmp( 'uploadField' );
uploadField.fileInputEl.dom.click();
I am also looking for a solution .... I have a numberfield component and a pop-up keyboard... when I try to click on key ('.') on the keyboard-pop-up... I want to attach to numberfield (like when you press '.')... but nothing happens. I try this:
// Ext version 5.1
var field = Ext.getCmp('numberfield-test');
var event = Ext.create('Ext.event.Event', {
key: 110 // Want to emulate '.' key
});
// none of the following works
field.fireEvent('keydown', [ field, event ]);
field.fireEvent('keypress', [ field, event ]);
field.fireEvent('keyup', [ field, event ]);
// neither this ones
field.fireEvent('keydown', field, event);
field.fireEvent('keypress', field, event);
field.fireEvent('keyup', field, event);