I want add eventListener highlight buttonLockup with stackTemplate.
Can you guide to use this?
Thanks,
The event system in TVJS is extremely similar to that in a web browser. After all, it's just JS and a DOM. MDN's documentation on Event Handlers should be mostly relevant
To add an event listener to a specific button, just find that button (using ID or name or whatever), and use addEventListener.
var myButton = doc.getElementByName('buttonLockup')
var onSelect = function(ev) {
console.log('Button selected!')
}
myButton.addEventListener('select', onSelect)
However, depending on your use case, I've found Apple's approach in their sample apps to be quite useful. They rely on the fact that events bubble up to the root of the template, and just listen to them there. So for example:
// Given a TVML document has been presented with this somewhere in it
<buttonLockup action="doSomething">Do something</buttonLockup>
// When it's selected, doSomething
var globalOnSelect = function(ev) {
var target = ev.target;
var action = target.getAttribute('action')
if (action === 'doSomething') {
console.log('Do Something button selected');
doSomething();
}
}
doc.addEventListener('select', globalOnSelect);
Related
I searched quite a bit to find out the correct way to remove event listeners in Cesium. I believe the confusion I have is around whether to treat Cesium events as regular dom events (due to a lack of knowledge about events in general in javascript). I am creating a screen space event like below:
var handler = new Cesium.ScreenSpaceEventHandler(canvas);
handler.setInputAction(function (movement) {
var picked = scene.pick(movement.endPosition);
if (Cesium.defined(picked) && picked.id === someEntity) {
labelEntity.position = someEntity.position;
labelEntity.label.show = true;
} else {
labelEntity.label.show = false;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
My question is, how can I remove this event? Is handler.destroy() removes all the event listeners associated with handler, or do I specifically have to remove event listeners by pointing to the cesium map dom element and calling removeEventListener on it? If that's the case, what parameters should be passed to removeEventListener?
The parameters for removeInputAction are just the type and optionally the modifer, and it looks like you're not using the modifier (SHIFT key, ALT key etc.)
So for the code you posted above, the removal would be:
handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
I am following this tutorial to build a store locator page with a Mapbox map.
I don't want to add custom markers because I already have custom map labels (symbols?), which means I don't need the optional last section of the tutorial and stop right after Add Event Listeners.
Once this is completed, the page should react to clicks in the side panel list, as well as on the map (2 event listeners). However, in the demo provided in the tutorial for that particular step, you can tell the code for the second event listener, the one making the map clickable, is not functioning, which makes me believe there is a mistake in the provided code:
// Add an event listener for when a user clicks on the map
map.on('click', function(e) {
// Query all the rendered points in the view
var features = map.queryRenderedFeatures(e.point, { layers: ['locations'] });
if (features.length) {
var clickedPoint = features[0];
// 1. Fly to the point
flyToStore(clickedPoint);
// 2. Close all other popups and display popup for clicked store
createPopUp(clickedPoint);
// 3. Highlight listing in sidebar (and remove highlight for all other listings)
var activeItem = document.getElementsByClassName('active');
if (activeItem[0]) {
activeItem[0].classList.remove('active');
}
// Find the index of the store.features that corresponds to the clickedPoint that fired the event listener
var selectedFeature = clickedPoint.properties.address;
for (var i = 0; i < stores.features.length; i++) {
if (stores.features[i].properties.address === selectedFeature) {
selectedFeatureIndex = i;
}
}
// Select the correct list item using the found index and add the active class
var listing = document.getElementById('listing-' + selectedFeatureIndex);
listing.classList.add('active');
}
});
Would anyone be able to tell what is wrong with this code?
Turns out the code is incomplete in that the cursor doesn't change to a pointer as you hover over a map label/marker so it doesn't clue you into realising you can click on it, hence my assumption it wasn't working at all. I assume the general users who would then face the map would be equally deceived unless the pointer shows up. So in the tutorial, if you do go ahead and click the marker, it will have the expected behaviour and display the popup, although no pointer is shown.
Here is how to create the pointer, based on this fiddle: https://jsfiddle.net/Twalsh88/5j70wm8n/25/
map.on('mouseenter', 'locations', function(e) {
// Change the cursor style as a UI indicator.
map.getCanvas().style.cursor = 'pointer';
});
map.on('mouseleave', 'locations', function() {
map.getCanvas().style.cursor = '';
});
I am working on a Flash banner ad built with Actionscript 3. It will be embedded into web pages.
The ad needs to have a close button. When the user clicks the button the ad should disappear.
This needs to be done entirely in the banner, as we have no control over the webpages where it will be embedded.
In Actionscript 2 I used to do this by running this code when the user clicked the button:
unloadMovie(this);
This seems to no longer work in Actionscript 3. What can I do to achieve this functionality in AS3?
Thanks for your help.
For documentation purposes, here are the conclusions Andreyu and I reached regarding the issue: unloading/removing a swf file from within the swf to allow users access to the elements under the swf.
One option is to use ExternalInterface to inject js code to:
get the id/name of the swf as registered with the DOM
remove the swf element from the DOM using the found id/name
In terms of code, this is using a technique described on Zeh Fernando's blog
as modified by Andreyu to include the DOM element removal:
// Based on work by Zeh Fernando: http://zehfernando.com/2011/getting-the-swfs-html-objectembed-id-from-within-the-flash-movie-itself/
function getSWFObjectName(): String {
// Returns the SWF's object name for getElementById
// Based on https://github.com/millermedeiros/Hasher_AS3_helper/blob/master/dev/src/org/osflash/hasher/Hasher.as
var js:XML;
js = <script><![CDATA[
function(__randomFunction) {
var check = function(objects){
for (var i = 0; i < objects.length; i++){
if (typeof(eval("objects["+i+"]." + __randomFunction)) != undefined) {
return objects[i].id;
}
}
return undefined;
};
return check(document.getElementsByTagName("object")) || check(document.getElementsByTagName("embed"));
}
]]></script>;
var __randomFunction:String = "checkFunction_" + Math.floor(Math.random() * 99999); // Something random just so it's safer
ExternalInterface.addCallback(__randomFunction, getSWFObjectName); // The second parameter can be anything, just passing a function that exists
return ExternalInterface.call(js, __randomFunction);
}
// Function to remove the SWF from the webpage
function destroyEverything(event:MouseEvent): void {
var js:XML;
js = <script><![CDATA[
function(__SWFContext) {
var element = document.getElementById(__SWFContext);
element.parentNode.removeChild(element);
}
]]></script>;
ExternalInterface.call(js, getSWFObjectName());
}
// Add function to click event of button
close_button.addEventListener(MouseEvent.CLICK, destroyEverything);
If unloadMovie was enough for you, you could simply remove everything from the stage:
//In button click handler, call "removeEverything" function
//function onClickClose(e:MouseEvent):void{
// removeEverything()
//}
//As a result you will get empty stage
function removeEverything():void {
while (stage.numChildren) {
stage.removeChildAt(0);
}
}
How can I access to an object who fires an eventListener event?
Let's say I have a mc:
var element = new MovieClip();
which has an eventlistener:
element.addEventListener(MouseEvent.CLICK, elementEventHandler);
And then, in the event handler, I want to add something to my mc:
function elementEventHandler(event:MouseEvent):void
{
var b1:balloon = new balloon("ballon1"); //this is another class.
event.target.addChild(b1);//this doesn't work.
}
So that is what I want to achieve... Recover the object who fired the event and then do crazy things with it (in this example, add another object in it).
If anybody has any idea, thanks in advance!
pd: yes, I know I can directly use the var element in this snippet, but in the real code I'm generating the mcs in a loop, according to a xml file.
function elementEventHandler(event:MouseEvent):void
{
// use the as-operator to cast the target into the class you need
var element:DisplayObjectContainer = e.target as DisplayObjectContainer;
// if the cast fails, element will be null, then we bail
if(!element) return;
// then, create your child and add it
var b1:balloon = new balloon("ballon1");
element.addChild(b1);
}
The reason you're getting an error is probably that the event is not coming directly from element but instead from one of its descendant objects.
"click" is a bubbling event.
Check out event flow in the DOM Level 3 Events spec to understand how the capture, target, and bubbling phases work:
http://www.w3.org/TR/DOM-Level-3-Events/#dom-event-architecture
So here's what I would do:
function elementEventHandler(event:MouseEvent):void
{
if (event.target != event.currentTarget)
// If event is not from "element", ignore it.
return;
...
}
I've been reading the Google Maps API docs to see if it's possible to tell the difference between a system event vs. a user one?
For example, the zoom_changed event gets triggered when you use methods like setZoom, fitBounds, etc, which in my implementation is unsavoury, as I just want to know when the user actually changes the zoom level.
Unfortunately, the click event is only fired on the map itself, not the controls, so you can't rely on that method to help detect the users input.
Ideas?
Although I haven't been able to solve this using the Google Maps API, I have created a workaround which involves me calling this method before I change the map zoom or positioning without user interaction:
MapGraph.prototype.systemMove = function() {
var _this = this;
this.isMoving = true;
return setTimeout(function() {
return _this.isMoving = false;
}, 500);
};
And my event bindings look like this:
google.maps.event.addListener(this.map, 'dragend', function(event) {
if (!_this.isMoving) return _this.mapChanged();
});
Not perfect, but it does work.
Would love to see any other implementations though.
You may also consider an alternate solution I proposed in this Stack Overflow answer, which does not rely on mouse events to recognize user-initiated changes.
Instead of trying to recognize user events, add a flag to the map whenever a programmatic change is initiated with setZoom or fitBounds.
map.systemChange = true
map.setZoom()
Then check for (and reset) the flag in the event listener.
map.addListener('zoom_changed', function () {
if (map.systemChange) {
map.systemChange = false // Reset the flag for a system-initiated event
} else {
// Handle the user-initiated event
}
});