Is there any workaround to create submenu in a flex context menu other than stopping right click from javascript.
Regards,
Hi Frank,
Yes, I want to create submenus in a context menu. Can you help me here.
Regards,
Hi Frank,
I need the context menu for the application not for datagrid.
In my initial question the phrase "other than stopping right click from javascript" means
"catch the right click in html, call a javascript function and over js call a as function."
The project that you have specified does the above procedure. I don't want to use this
procedure. Is there any other way for achieving submenus in a flex context menu. Could you
please tell me if so..
Regards,
Arvind
Yes, there is.
I don't know, what you exactly mean with this:
other than stopping right click from
javascript.
But, if you want to create a entry in submenu, do this:
//Instance of my own class
private var myContext:myContextMenu = new myContextMenu();
application.contextMenu = myContext.myContextMenu;
//Here is the Class:
package com.my.components
{
/* ////////////////////////////////////////////
///// My Context MenĂ¼ /////////////////////
///////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
//to use: //
// private var myContext:MyContextMenu = new MyContextMenu(); //
// init() in creationComplete //
// application.contextMenu = myContext.myContextMenu; //
////////////////////////////////////////////////////////////////////////////// */
import flash.display.Sprite;
import flash.events.ContextMenuEvent;
import flash.net.URLRequest;
import flash.net.navigateToURL;
import flash.text.TextField;
import flash.ui.ContextMenu;
import flash.ui.ContextMenuBuiltInItems;
import flash.ui.ContextMenuItem;
public class MyContextMenu extends Sprite
{
public var myContextMenu:ContextMenu;
private var menuLabel:String = String.fromCharCode(169)+" My Company GmbH";
public function MyContextMenu()
{
myContextMenu = new ContextMenu;
removeDefaultItems();
addCustomItems();
myContextMenu.addEventListener(ContextMenuEvent.MENU_SELECT, menuSelectHandler);
super();
}
private function removeDefaultItems():void
{
myContextMenu.hideBuiltInItems();
var defaultItems:ContextMenuBuiltInItems = myContextMenu.builtInItems;
defaultItems.print = true;
}
private function addCustomItems():void
{
var item:ContextMenuItem = new ContextMenuItem(menuLabel);
myContextMenu.customItems.push(item);
item.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,menuItemSelectHandler);
}
private function menuSelectHandler(event:ContextMenuEvent):void
{
}
private function menuItemSelectHandler(event:ContextMenuEvent):void
{
navigateToURL(new URLRequest('http://www.my-company.de'));
}
private function createLabel():TextField
{
var txtField:TextField = new TextField();
//txtField.text = textLabel;
txtField.text = "RightClickHere";
return txtField;
}
}
}
Have fun
EDIT:
There is an interesting project here. They catch the right click in html, call a javascript function and over js call a as function.
Unfortunately, the limitation of FP or NativeMenu APi allowed just on level contextmenu. Read here
Frank
Related
I was wondering if anyone had any luck with the following senario in flex.
I'd like to be able to have a custom item renderer which delegates to another renderer inside.
The reason for this would be in a datagrid for instance displaying a checkbox if the dataprovider for the row had a boolean value. Using the default item renderer when the value was a non boolean.
Basically I was hoping to use a proxy object (though not necessarily the proxy class) so that I could a renderer which delegated all of its responsibilties to a sub renderer.
Hard to explain.
Edit 1
I think the following gives a clearer idea of what I had in mind. This is only knocked up quickly for the purpose of showing the idea.
SwitchingRenderer.as
package com.example
{
import mx.controls.CheckBox;
import mx.controls.dataGridClasses.DataGridItemRenderer;
import mx.controls.listClasses.BaseListData;
import mx.controls.listClasses.IDropInListItemRenderer;
import mx.core.IDataRenderer;
import mx.core.UIComponent;
public class SwitchingRenderer extends UIComponent implements IDataRenderer, IDropInListItemRenderer
{
private var checkboxRenderer:CheckBox;
private var defaultRenderer:DataGridItemRenderer;
private var currentRenderer:IDataRenderer;
public function SwitchingRenderer()
{
this.checkboxRenderer = new CheckBox();
this.defaultRenderer = new DataGridItemRenderer();
this.currentRenderer = defaultRenderer();
super();
}
public function get data():Object
{
//If the data for this cell is a boolean
// currentRender = checkBoxRenderer
// otherwise
// currentRenderer = defaultRenderer
}
public function set data(value:Object):void
{
currentRenderer.data = value;
}
public function get listData():BaseListData
{
return currentRenderer.listData;
}
public function set listData(value:BaseListData):void
{
currentRenderer.listData = value;
}
}
}
If you're using Flex 4 spark components look into the itemRendererFunction,
Here is a good sample from the interwebs.
Unfortunately, Flex 3 components, such as the DataGrid do not support that.
You're a bit vague on what you'd be displaying if the data sent into the itemRenderer was not a Boolean value. But, you can easily modify the visual appearance of a component based on the data change event, including swapping visible properties of a component's children, changing states or change the selectedIndex of a ViewStack. All these things can be done within an itemRenderer w/o issues.
Edit:
Based on the user's additional posting, I'd add that what he is after can be done like this:
public function get data():Object
{
if(this.data is Boolean){
checkBoxRenderer.visible = true;
defaultRenderer.visible = false;
} else {
checkBoxRenderer.visible = false;
defaultRenderer.visible = true;
}
}
I've got a Flash UI that does a periodic server call to get some updated information. The call uses the flex sdk's rpc.soap.Operation class. It looks something like this:
var wsOperation:Operation = Operation(webService.getOperation(SomeOperation));
wsOperation.addEventListener("fault", wsError);
wsOperation.addEventListener("result", wsResult);
wsOperation.send(...some params);
This call gets some data from a SQL database. I have timed the call from right before the send to the start of the wsResult function at ~4 seconds. During this time, my UI is not updated. It is frozen/unresponsive.
Now, I know Flash is single-threaded/asynchronous, so I'm not sure why this is happening. I see that the send(..) function returns an AsyncToken which I am not using. Could this have something to do with it?
Any other ideas as to why this is happening are appreciated. Thanks.
I still haven't found an acceptable solution to this. It seems ridiculous that I would have to Pseudo thread to get flash to update the UI during a 4 second call. I'm wondering if maybe the parsing of the soap response could be taking up a lot of time. If there is a lot of processing to do, will Flash delay updating the UI indefinitely?
You will get a UI freeze in Flash because it is single threaded. However, you can do pseudo threading with something like this:
package
{
import flash.display.DisplayObjectContainer;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.utils.getTimer;
import mx.core.UIComponent;
import mx.managers.ISystemManager;
public class PseudoThread extends EventDispatcher
{
public function PseudoThread(sm:ISystemManager, threadFunction:Function, threadObject:Object)
{
fn = threadFunction;
obj = threadObject;
// add high priority listener for ENTER_FRAME
sm.stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler, false, 100);
sm.stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
sm.stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
thread = new UIComponent();
sm.addChild(thread);
thread.addEventListener(Event.RENDER, renderHandler);
}
// number of milliseconds we think it takes to render the screen
public var RENDER_DEDUCTION:int = 10;
private var fn:Function;
private var obj:Object;
private var thread:UIComponent;
private var start:Number;
private var due:Number;
private var mouseEvent:Boolean;
private var keyEvent:Boolean;
private function enterFrameHandler(event:Event):void
{
start = getTimer();
var fr:Number = Math.floor(1000 / thread.systemManager.stage.frameRate);
due = start + fr;
thread.systemManager.stage.invalidate();
thread.graphics.clear();
thread.graphics.moveTo(0, 0);
thread.graphics.lineTo(0, 0);
}
private function renderHandler(event:Event):void
{
if (mouseEvent || keyEvent)
due -= RENDER_DEDUCTION;
while (getTimer() < due)
{
if (!fn(obj))
{
if (!thread.parent)
return;
var sm:ISystemManager = thread.systemManager;
sm.stage.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
sm.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
sm.stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
sm.removeChild(thread);
thread.removeEventListener(Event.RENDER, renderHandler);
dispatchEvent(new Event("threadComplete"));
}
}
mouseEvent = false;
keyEvent = false;
}
private function mouseMoveHandler(event:Event):void
{
mouseEvent = true;
}
private function keyDownHandler(event:Event):void
{
keyEvent = true;
}
}
}
This will enable you to do a process without the UI Freeze. It basically uses the stage's RENDER event to defer processing. This code performs as much Actionscript computation as possible limited by the time needed to maintain the frame rate. For more information see: http://blogs.adobe.com/aharui/2008/01/threads_in_actionscript_3.html
I want to add a simple piece of text to the stage and add a listener to do something when the user clicks it.
Here's my TextLink class:
package some.package
{
import flash.display.Sprite;
import flash.external.ExternalInterface;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
public class TextLink extends Sprite
{
public var tf:TextField = new TextField();
public var bspr:Sprite = new Sprite();
public function TextLink(tx:int, ty:int, tft:String):void
{
tf.text = tft;
tf.x = tx;
tf.y = ty;
tf.autoSize = TextFieldAutoSize.LEFT;
bspr.addChild(tf);
this.addChild(tf);
}
}
}
And here is the way I am calling it, along with the listener:
public function test_array_of_objects():void
{
var tmp:TextLink = new TextLink(30, 30, "some text");
tmp.addEventListener(MouseEvent.CLICK, roverNotify);
addChild(tmp);
}
protected function roverNotify(e:Event):void
{
ExternalInterface.call("console.log", "got a click");
}
...But I don't get a message for some reason.
I've imported everything successfully. Any thoughts on what else I can try?
Is your TextLink class an event dispatcher? You're trying to add a listener to the TextLink object, but the click listener needs to be attached to the text field that you're using inside TextLink. TextLink needs to be a DisplayObject of some kind to inherit the dispatching capabilities.
Also, constructors should not specify a return type (since they're just returning themselves) -- the :void should not be there where your TextLink constructor is.
Does function TextLink require something like this at the beginning:
var tf:Text = new Text();
Is the problem with clicking the Sprite or getting the event to fire? If it's the former you could try adding the code below.
tmp.mouseChildren = false;
tmp.buttonMode = true;
ExternalInterface.call("console.log", "got a click");
You have a JavaScript function defined like this??:
function console.log(inputString) {
//do something
}
Edit: Nevermind the above, forgot about Firebug.
Also, TextLink doesn't need to be an event dispatcher, though you may want to have TextLink set its mouseChildren property to false (unless you need to be able to select that text), so that you don't inadvertently trigger events on the TextField, and buttonMode to true.
Edit: Also, what's the point of?:
var bspr:Sprite = new Sprite();
bspr.addChild(tf);
Final edit
How about this? http://code.google.com/p/fbug/issues/detail?id=1494
Yes, you are correct, in FF3 the console is injected only when the page has
javascript and uses window.console.
If you put any js that accesses the console before the Flash loads it should work, eg
<script>
var triggerFirebugConsole = window.console;
</script>
Let us know if this works. It's unlikely that we can fix this soon.
When I debug my code nothing appears on screen. I've rechecked the code and consulted with others yet nothing appears. My html template is fine.
package {
import flash.display.Sprite;
import flash.events.*;
public class asgnv2 extends Sprite
{
var lineY = 0;
public function asgnv2()
{
stage.addEventListener(Event.ENTER_FRAME, update);
graphics.lineStyle(1);
}
function update(e){
graphics.clear();
graphics.moveTo(0 ,lineY);
graphics.lineTo(100, lineY);
lineY+=0.5;
}
}
}
unless asgnv2 is Document class, it is not going to work, as you are registering ENTER_FRAME event on the stage inside the constructor of asgnv2. A DisplayObject can not access stage property until it is added to Stage Display List. So try the following. public function asgnv2(){
this.addEventListener(Event.ADDED_TO_STAGE, onAdded);
graphics.lineStyle(1);
}
private function onAdded(e:Event):void {
stage.addEventListener(Event.ENTER_FRAME, update);
this.removeEventListener(Event.ADDED_TO_STAGE, onAdded);
}
private function update(e:Event):void{
//do the stuff
}
how do you tell a single mouse click from a double click? my single
click listener seems to be trapping all the double clicks as well:
tz locator
it's a known issue for the flash/flex API but the js workaround doesn't seem to handle both either: code.google.com
Might need a bit of clarification, but make sure you are using the Google Map's MapMouseEvent, not the Flash API's click events (please assume this code in inside a Map subclass):
public class GoogleMap extends Map
{
import com.google.maps.LatLng;
import com.google.maps.Map;
import com.google.maps.MapEvent;
import com.google.maps.MapMouseEvent;
public function GoogleMap():void
{
super();
this.key = "YOUR_API_KEY";
addEventListener(MapEvent.MAP_READY, _onMapReady);
addEventListener(MapMouseEvent.CLICK, _onMapClick);
addEventListener(MapMouseEvent.DOUBLE_CLICK, _onMapDoubleClick);
}
protected function _onMapClick(event:MapMouseEvent):void
{
trace("single!");
var mousePoint:Point = new Point(mouseX, mouseY);
var mousePointLocal:Point = globalToLocal(mousePoint);
var mouseLatLng:LatLng = this.fromViewportToLatLng(mousePointLocal);
}
protected function _onMapDoubleClick(event:MapMouseEvent):void
{
trace("double!");
}
protected function _onMapReady(event:MapEvent):void
{
trace("ready!")
}
}