so I am trying to drag around some images in a canvas.
I am adding eventlisteners to the components and calling startDrag() and stopDrag() to pick them up and stuff:
component.addEventListener(MouseEvent.MOUSE_DOWN, component.startDrag)
The problem is that it is selecting the image at its (0,0) location and not where I initially click on it. So there's a sudden "jump" when I click on the image. It is not smooth.
I noticed that startDrag() has two default parameters, one of them is lockCenter and it is default to false. Maybe do I set it equal to true somehow? (I don't know how to pass arguments to my second parameter in addeventlistener)
Another question: if I want to add more conditions to it, like make a new function that uses component.startDrag(), how do I pass the component to this function while adding event listener to it at the same time?
for example: I want to do:
component.addEventListener(MouseEvent.MOUSE_DOWN, some_other_function);
where some_other_function uses component.startDrag();
Thanks!
You should have your event listener call an event handler instead of start drag directly - that way you can pass arguments:
ie:
component.addEventListener(MouseEvent.MOUSE_DOWN, dragStartHandler);
public function dragStartHandler(event:MouseEvent):void{
component.startDrag(true);
}
You don't have to do all that. Use the DragManager. Here's a page to show you how:
http://www.switchonthecode.com/tutorials/simple-flex-drag-and-drop
Related
Question
I'm working with Adobe Scene7 BasicZoomViewer and I'm looking for a way to tell the ZoomViewer to reset the zoom so that the user is no longer zoomed in on an image but instead will show the default "zoom" level.
What I've found
The closest thing I found to what I need is this reset property ZoomView.reset which "Resets the viewport when the frame (image) changes. If set to 0 it preserves the current viewport with the best possible fit while preserving the aspect ratio of the newly set image".
This looks close to something I need but it states that it will reset or preserve the aspect ratio when a new image has been inserted but I am not inserting new images.
Demo from Adobe
There is a button on the image that the API inserts into the page that resets the zoom level. Adobe provides a demo page that shows what I'm working with. If you look at the bottom left, the right-most button is the reset button. When clicked, it has to make some kind of API call and I need to figure out which one it is.
Edit
I've been able to find a minified version of the BasicZoomViewer and I am currently attempting to make sense of the code.
There is an event listener placed on the "Zoom Reset Button" that just simply calls a reset() method on line 274 in the uglified version of the file. Currently, I am trying to make sense of the file and figure out how to access this method.
c.zoomResetButton.addEventListener("click", function () {
c.zoomView.zoomReset()
});
I will be answering my own question. If someone finds a better way please feel free to answer as well.
tldr;
Create a variable to hold the instance of your s7viewers.BasicZoomViewer() and inside of that you can access the event handlers and much more.
Example of calling the reset zoom handler
// instantiate the s7viewers class and save it in a variable
var s7BasicZoomViewer = new s7viewers.BasicZoomViewer({
containerId: 's7viewer',
params: {
asset: assetUrl,
serverurl: serverUrl
})
// example of how to call the "zoomReset()" method
s7BasicZoomViewer.zoomResetButton.component.events.click[0].handler()
Explanation
After digging through the minified code that was uglified I found an event listener on the s7zoomresetbutton DOM class name, or perhaps it's watching for the ID of that DOM element which is the same ID as the container div for your S7 BasicZoom Viewer plus some added text to make this ID unique. For example, if the container div is s7viewer then the reset zoom button will have an ID of s7viewer_zoomresetbutton.
Now, going through the code I found this event listener which let me know there must be some way to call the zoomReset() method.
c.zoomResetButton.addEventListener("click", function () {
c.zoomView.zoomReset()
});
In the code above, the value of c is this or in other words it's the instance of your S7 BasicViewerZoom and in my case I have multiple depending on how many images I need to zoom on.
When instantiating the s7viewers class you can then reference that instance later and access the event handlers on each button and other properties and methods.
From there it was just looking through the object returned from the instance and calling the handler for the reset button.
I am currently trying to create a custom UINavigationBar Subclass.
What i want to achieve is that all custom navigationbars inside my app should have a couple of barbuttonitems in common. But it should still be possible to define left or .rightbarItems on the navigationItem in code.
What i tried so far is that subclassed the UINavigationBar and played around with all methods and delegate callbacks i could potentially use to change the navigationItem. There are methods like
setItems:animated:
setItems:
navigationBar:didPushitem etc.
.. which could be used to modify the navigationItem somehow.
But there is no callback which can be used to change the item initially.
What i basically want to know is how it is possible to change navigationItem initially before it is being pushed ?
Solved it by myself using
willShowViewController of the UINavigationControllerDelegateProtocol
to modify the navigationItem
Can I listen to Alert button click between components using AsyncToken?
Basically, I want to have a method that opens an Alert with buttons and have it return an AsyncToken so that other components calling that method can listen for button click.
Example:
var token:AsyncToken=methodThatOpensAlert();
token.addResponder(new mx.rpc.Responder(buttonClick));
What's the way to do that?
Thank you.
You might be able to use an AsyncToken to achieve this but you could also just register for custom events that you dispatch from the pop up, this is a much cleaner method IMO. Really you've got two relatively clean options I can think of. 1 you make your pop-up dispatch events like "okClicked" "cancelClicked" for different button clicks within the pop-up, you create an instance of the pop up and add listeners then call PopUpManager.addPopUp, or else you do PopUpManager.createPopUp and keep a reference to the returned display object (the instance of the pop-up it created) and add your listeners then. 2 you make two properties in the pop up typed as function, you use them as call backs, so when you create the pop-up you set the okClickedFunction and cancelClickedFunction (or whatever your buttons may be) then in the pop-up you put cilck handlers on the buttons, check to see if the appropriate call-back function is set and call it if so, like
if(okClickedFunction)
okClickedFunction();
Let me know if you have a specific need that makes you think you must use the AsyncToken, but from checking out the docs it looks as though it's strictly meant to work with the other RPC methods and lots of properties are read-only.
EDIT:
[SomeUtilClass.as]
private static function methodThatOpensAlert():CustomAlert
{
return PopUpManager.createPopUp(Application.application, CustomAlert) as CustomAlert;
}
[CustomAlert.as]
[Event(type="flash.events.Event", name="button1Clicked")]
[Event(type="flash.events.Event", name="button2Clicked")]
private function button1Clicked_handler(event:MouseEvent):void
{
dispatchEvent(new Event("button1Clicked", true));
}
private function button2Clicked_handler(event:MouseEvent):void
{
dispatchEvent(new Event("button2Clicked", true));
}
[ThingThatUsesAlert]
var ca:CustomAlert = SomeUtilClass.methodThatOpensAlert();
ca.addEventListener("button1Clicked", button1ClickHandler);
ca.addEventListener("button2Clicked", button2ClickHandler);
And I believe mouse events bubble by default anyhow still so you could really just listen for a click event on the pop up then use the event.target to determine if it was one of the buttons your interested in.
Let me know if you can make sense of this or need more info.
Flex 3 question:
I trying here to avoid having to bind resources to all my components labels ( ie a button) and find a way to have this automated.
Problem:
It corrupts the layout in design mode to bind directly in the mxml label="{resourceManager.getString('myResources', 'submit')}" and makes the design view useless. but when declaring bindings elsewhere, in actionScript or via a bind tag, it is counter productive and prone to many errors and miss.
Proposition:
I would like to create my own button that automatically invoke resources to localize a button label. So the author puts "Submit" in the mxml description of my button, and when running it would take the value of the label ie "submit" and use resourceManager.getString('myResources', 'submit').
but I can't find the way to override the set label function, Is it possible if yes how? else how can I go about it?
Maybe I am missing an essential process here that would make the use of resources more elegant, as well as how to override such thing as a button's label.
Thanks for your advices.
Create a component called MyButton, extending Button. Then use this:
override public function set label(value:String):void {
super.label = resourceManager.getString('myResources', value) || value;
}
Assuming the resource manager returns "null" or "undefined" this will work, and will only replace the value if it exists in "myResources".
If you don't want to override every component you need to do this with, then you can add a FlexEvent.CREATION_COMPLETE event on every component. Then use a single generic function to do your label localization.
I have 2 components for example (editor.mxml using mx:windows), when I click an edit button, I want to get the current value from the other component's datafield? (datagrid.mxml using mx:window)
I do know how to access the main MXML's datagrid by parentDocument or Application.application method, but stumped block if I want to access other way as mentioned above. Keep the code as simple as possible.
You could either do dependency injection, that is, give component A a reference to component B so that they can communicate directly (example of tighter coupling,) or have both components communicate through a common mediator using events (example of more loose coupling.)
Both of those options would be implemented wherever it is that you're creating those components (A and B in this example) and adding them to the display list.
This might be more complicated than it deserves, and it smacks of Pattern-Fever, but you could use a mediator class that listens for the CLICK event from the button and knows enough about the other component to query its property. It could even transmit that data using a custom event, which the button listens for.
While this involves three classes instead of two, it often turns out to be easier to have two components that focus on looking good and one that worries about coordination.
Cheers
Try this:
FlexGlobals.topLevelApplication
This points Your root. From the root You can grab every element You want.
You can also add an id to the custom component like this,
<custom:Editor id="myCustomComponent">
</Editor:AddressForm>
and
access your datagrid's value like this,
var data:ArrayCollection = myCustomComponent.DatagridID.dataProvider;