I am trying to work out why my console.log command throws an event handler error when I put it into a click event.
My Javascript is not good enough to know if this is specific to Edge, or a more global JS thing.
Here is my code:
(function($, Edge, compId){
var Composition = Edge.Composition,
Symbol = Edge.Symbol; // aliases for commonly used Edge classes
//Edge symbol: 'stage'
(function(symbolName) {
Symbol.bindSymbolAction(compId, symbolName, "creationComplete", function(sym, e) {
// insert code to be run when the symbol is created here
var want = true;
console.log(want);
});
//Edge binding end
Symbol.bindElementAction(compId, symbolName, "${Rectangle}", "click", function(sym, e) {
// insert code for mouse click here
console.log(want);
});
//Edge binding end
})("stage");
//Edge symbol end:'stage'
})(window.jQuery || AdobeEdge.$, AdobeEdge, "EDGE-26284910");
The first console.log after creationComplete works fine, the next one in the click event does not work, and I have no idea why. Can anyone enlighten me?
Thanks
If you properly indent your code you'll notice that want was defined within inner function scope and was not accessible from within click handler.
(function($, Edge, compId){
var Composition = Edge.Composition,
Symbol = Edge.Symbol; // aliases for commonly used Edge classes
//Edge symbol: 'stage'
(function(symbolName) {
var want;
Symbol.bindSymbolAction(compId, symbolName, "creationComplete", function(sym, e) {
// insert code to be run when the symbol is created here
want = true; //you still can set its value
console.log(want);
});
//Edge binding end
Symbol.bindElementAction(compId, symbolName, "${Rectangle}", "click", function(sym, e) {
// insert code for mouse click here
console.log(want); // but now it is accessible from within this function
});
//Edge binding end
})("stage");
//Edge symbol end:'stage'
})(window.jQuery || AdobeEdge.$, AdobeEdge, "EDGE-26284910");
Related
I am trying to reduce the number of event listeners attached to my collaborative models. In order to do this, I have started listening to the ObjectChanged event instead of specific event types and delegating to other handlers. However it doesn't look like the ObjectChanged event is being bubbled properly for the ValuesAdded/ValuesRemoved changes on CollaborativeLists.
function onObjectChanged(e)
{
log('Changed: ', e);
}
// Placeholder, called when we load our doc through the realtime api.
function onDocLoaded(doc)
{
var docModel = doc.getModel();
var docRoot = docModel.getRoot();
console.log('Drive document loaded: ', window.performance.now());
if (docRoot.has('testMap'))
{
docRoot.delete('testMap');
}
docRoot.set('testMap', docModel.createMap());
var testMap = docRoot.get('testMap');
console.assert(testMap, 'Test map required');
docRoot.addEventListener(gapi.drive.realtime.EventType.OBJECT_CHANGED, onObjectChanged);
var testList = docModel.createList();
testMap.set('testList', testList);
console.assert(testList, 'Test list required');
setTimeout(function ()
{
console.log('Begin Push');
testList.push('This is a test string');
console.log('End Push');
}, 1000);
}
The code above is run on doc load and demonstrates the problem. In this case, I would expect two ObjectChanged events to be fired (first for the list being set on the map and second for the string push into the list). The first event fires correctly, however the list push does not trigger an ObjectChanged event on either the 'docRoot' or the 'testMap'. As both of these are ancestors of the testList an event should be bubbled to them (based on https://developers.google.com/drive/realtime/handle-events#event_bubbling).
The ObjectChanged event however IS fired on the testList, so it looks like there is an issue with only the bubbling portion.
Is there a way of ensuring that the event bubbling will occur? Additionally, for events that are bubbling up, is there a way to stop bubbling partway?
I want to add listeners to google map events, but not using anonymous functions but named, external functions as this happens inside a loop, I do not want to define an anonymous function right there, but instead use a named, external function:
Not:
for (...) {
googleMap.event.addListener(instance, eventName, function() {...});
}
But rather sth. like:
doSomething = function(parameter1, parameter2...) {
...
}
for (...) {
googleMap.event.addListener(instance, eventName, params, doSomething);
}
When "instance" is a google map marker, I can add the parameter(s) to the marker using marker.set(paramName, paramValue) and then access the parameters inside the event handler function via this.paramName, but is there any other way to pass values to the event handler function when I don't want to use an anonymous one?
Any advice welcome, Roman.
I had the same problem. Here is a solution. It genuinely avoids the create function in a loop problem, by using the pattern described here
In JavaScript, what are specific reasons why creating functions within a loop can be computationally wasteful?
Which I call the "function factory" pattern.
The other ingredients are that inside the function "this" refers to the object which raised the function (the thing on the map which was clicked, or whatever), and because JavaScript is completely dynamic, you can attach additional properties at will to the thing which was clicked, and query them by calling this.blah inside the function
function doSomethingHandlerFactory(){
var f = function(event){
//do something, for example call a method on a property we attached to the object which raised the event
this.blah.clicked(event);
};
return f;
}
//add a property to the google overlay object (for example a polyline which we've already set up)
thePolyline.blah = ...;
//get a handle for a function, attach the event (in this case to a polyline), and keep
//a reference to the event (in case we want to call removeListener later). The latter
//is optional.
var f = doSomethingHandlerFactory();
var ev = google.maps.event.addListener(thePolyline, 'click', f);
I hope this helps someone out.
How about wrapping your named function in an anonymous function:
google.maps.event.addListener(instance, eventName, function() { doSomething(parameter1, parameter2,...) });
I have a numeric stepper and I want to add an event listener to its text box:
use namespace mx_internal;
durationStepper.inputField.addEventListener(Event.CHANGE,durationStepperTextInputChanged);
private function durationStepperTextInputChanged(event:Event):void
{
use namespace mx_internal;
trace(durationStepper.inputField.text);
}
However, the event function does not execute! I put a break point there and it does not reach it! What am I missing here? Thanks.
The problem is that the developer has stopped Change event from bubbling up. You can find it if you go to the source file of the NumericStepper. Here are two functions, which prevent you from getting the event.
override protected function createChildren():void
{
super.createChildren();
if (!inputField)
{
inputField = new TextInput();
//some code
//some code
inputField.addEventListener(Event.CHANGE, inputField_changeHandler);
addChild(inputField);
}
}
private function inputField_changeHandler(event:Event):void
{
// Stop the event from bubbling up.
event.stopImmediatePropagation();
var inputValue:Number = Number(inputField.text);
if ((inputValue != value &&
(Math.abs(inputValue - value) >= 0.000001 || isNaN(inputValue))) ||
inputField.text == "")
{
_value = checkValidValue(inputValue);
}
}
As you can see the second function has
event.stopImmediatePropagation();
In this case you have two options: either you should find another way of implementing your logic, or you can copy the source code of the component and eliminate this code line.
It would be fine to override the function, but it is private.
You can read about this common problem here
I have tried to choose the second way. It works perfectly! It is not only the *.as file, but some others, which are used in it.
You can download the component here.
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 am working on an ASP.NET web application that is required to bring up a popup on a roolover. I am using the "OnMouseOver" event and it works as expected. The problem is that the event is on a "hair trigger"; even a casual passage of the mouse over the control brings up the popup (which then must be manually dismissed). I want to add a delay so that a rapid pass over the control in question does not trigger the event. Is there a way to set such a delay or is there a different event that I could use to get the same "trigger event on a slow rollover"?
One solution that comes to mind, there may be better ways though:
Make the onmouseover call the function via a setTimeout delay
Inside the function, check the mouse is actually over that element.
You could also use an onmouseout to clear the setTimeout, but then you'd have to store a reference to the timer in a global variable to get at it again.
What I ended up doing is as follows (oRow is a table row but it could be any control):
function ItemMouseOver(oRow, "parameters for the popup")
{
oRow.showTimer = window.setTimeout(function()
{
alert('popup');
}, 1000);
}
function ItemMouseOut(oRow)
{
if (oRow.showTimer)
window.clearTimeout(oRow.showTimer);
In the ASP.NET grid view RowDataBound event: I added the following code:
protected void ReportGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow && (
e.Row.RowState == DataControlRowState.Normal
|| e.Row.RowState == DataControlRowState.Alternate))
{
// get the input values for the popup for the row (stuff deleted)
e.Row.Attributes["onmouseover"] = "javascript:ItemMouseOver(this,
"parameters for the popup");";
e.Row.Attributes["onmouseout"] = "javascript:ItemMouseOut(this);";
}
}
It works just fine. Thanks.