Subsribe to InlineGraphicElement mouse click - actionscript-3

How can I implement this simple thing without getting list of all gaphic elements and adding listner to each? I can listen for mouse click event and get target as Loader which has parent.parent property as TextLine but I can't get InlineGraphicElement reference from it. Is there any functionality to determine which float element is under mouse pointer?
Here is my code:
findElement(textarea.textFlow);
private function findElement(group:FlowGroupElement):void{
for (var i:int = 0; i < group.numChildren; i++) {
var element:FlowElement = group.getChildAt(i);
if (element is InlineGraphicElement) {
var link1:InlineGraphicElement = element as InlineGraphicElement;
link1.graphic.addEventListener(MouseEvent.CLICK,someLinkClickHandler);
}
}
}
public function someLinkClickHandler(eve:Event):void
{
Alert.show((eve.target).parent.parent); //Here I need source of clicked InlineGraphicElement
}

You can use a library like HtmlAgilityPack or CsQuery to scrape HTML from a website. I'd recommend CsQuery as it has a familiar jQuery like syntax for scraping elements.
They also have NuGet packages to easily install them in a project.

Related

How to make a close button for a Flash banner ad with Actionscript 3

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);
}
}

ActionScript 3 - How to target textbox inside movieclip

I have a movie clip called radio and flashlight. Inside the movieclip, there is a text box with words inside. The instance name of the textbox inside radio is called 'radioText' and the instance name of the textbox inside flashlight is called 'flashlightText'. I want the color of the text to turn white when hovering over the movieclip.
The code below works for changing radioText but not flashlightText:
var containers = [radio, flashlight];
for (var i:int = 0; i<containers.length; i++) {
containers[i].addEventListener(MouseEvent.MOUSE_OVER, hOver);
}
var whiteFont:TextFormat = new TextFormat();
whiteFont.color = 0xFFFFFF;
function hOver(evt:Event):void {
evt.currentTarget.radioText.setTextFormat(whiteFont); //change radioText's color
}
what I want to do is instead of
evt.currentTarget.radioText.setTextFormat(whiteFont);
, I want to do somthing like
evt.currentTarget.(currentTarget.name + 'Text').setTextFormat(whiteFont);
but that doesn't work for obvious reasons. Is there a way to do what I want to do?
There are quite a few good ways to implement what you are asking, what you do really depends on how you are setting up your objects.
For example, your pseudo code:
evt.currentTarget.(currentTarget.name + 'Text').setTextFormat(whiteFont);
...could be implemented if you named all your child text fields identically OR if you named them accordingly to some convention (for this example I set a name for the parent and a similar name for the child). So let's assume your container has the name "container" and has a TextField child named "containerText". It would look something like this:
private function hOver(evt:MouseEvent):void {
var n:String = evt.currentTarget.name;
evt.currentTarget.getChildByName( n + "Text" ).setTextFormat( whiteFont );
}
This is now dependent on following a naming convention, which may or may not be ideal. So what might be an even better and more generic way to handle this? You can setup a class for your container object and have a TextField property there. For Example:
class myContainer extends Sprite {
public var textField:TextField;
public function myContainer():void {
textField = new TextField();
addChild(textField);
}
}
Pretty basic, but now if you added all the listeners to types of myContainer your event function could look like this:
private function hOver(evt:MouseEvent):void {
evt.currentTarget[ "textField" ].setTextFormat( whiteFont );
}
Which is probably more what you are looking for. This version allows you to grab the "textField" property of the object you applied the listener to, in this case that property would essentially be your radioText/flashlightText.
Ok so lastly, and the least favorable way to do this, assumes all you care about is that the object has a child of type TextField, it has no logical naming convention, and we are not sure what index it is at in the display list. You would have to do it something like this:
private function hOver(e:MouseEvent):void {
var i:int;
var displayObj:DisplayObjectContainer = e.currentTarget as DisplayObjectContainer;
for ( ; i < displayObj.numChildren; i++ ) {
var obj:* = displayObj.getChildAt( i );
if ( obj is TextField ) {
obj.setTextFormat( whiteFont );
}
}
}
That is also the slowest way of reaching your child object. This should cover all the bases, good luck!
What's wrong with?
DisplayObjectContainer(evt.currentTarget)[evt.currentTarget.name + 'Text'].setTextFormat(whiteFont);

AS3 buttons changing text when pressed

I need some help. In Flash, i have designed a sinmple button from the components panel. I have given it the instance name of btn_one. What i am attempting to do is everytime users click on the button i want the button to change text from send to next. But, how do you do this?
Unfortunately my knowledge of as3 is limited. They are many tutorials of as3 button but i have not found any in regards to this. I would really appreciate it if you guys could show me some examples of code or provide me some tutorials links.
Thanks
I've tried to do something about SimpleButtons' text fields, and came up with the following code. Hope it'll help.
public class GenericTextButton extends flash.display.SimpleButton {
public var buttonText:String;
private var tfs:Vector.<TextField>;
public function GenericTextButton():void
{
tfs=new Vector.<TextField>();
var tc:DisplayObjectContainer;
var i:int;
// now let's init embedded TFs
// trace((upState as DisplayObjectContainer).numChildren); // wow there's property available! YES
if (upState is DisplayObjectContainer) {
tc=(upState as DisplayObjectContainer);
for (i=0;i<tc.numChildren;i++)
if (tc.getChildAt(i) is TextField) tfs.push(tc.getChildAt(i) as TextField);
} // now same with overState and downState
if (overState is DisplayObjectContainer) {
tc=(overState as DisplayObjectContainer);
for (i=0;i<tc.numChildren;i++)
if (tc.getChildAt(i) is TextField) tfs.push(tc.getChildAt(i) as TextField);
}
if (downState is DisplayObjectContainer) {
tc=(downState as DisplayObjectContainer);
for (i=0;i<tc.numChildren;i++)
if (tc.getChildAt(i) is TextField) tfs.push(tc.getChildAt(i) as TextField);
}
// trace(name+' has '+tfs.length+' textfields'); // 3 !!!! Unbelieveable, but true
}
public function setText(the_text:String):void {
for (var i:int=0;i<tfs.length;i++) tfs[i].text=the_text; // and NOW we can do as simple as this
}
}
What does it do: You declare your button instance as GenericTextButton descendant, instead of SimpleButton, then you'll have setText() method available to instantly change all text in that button to whatever you supply. It enumerates internal structure of SimpleButton, grabs any TextFields there are, and stores it in a Vector for easy reference.

Flex 4 image object returning as MovieClip object

I am working on a custom context menu in Flex4. The context menu itself works fine but I am looking for a way to tell if the ContextMenuEvent mouseTarget is an image. As it stands, the mouseTarget shows that it is a "[object MovieClip]". Which is strange because I have no movie clips in my application, only image containers. Any idea what is going on?
private function openContextMenu(e:ContextMenuEvent):void {
Alert.show(e.mouseTarget.toString());// shows [object MovieClip] when it should show [Object Image]
}
Thanks
You need to set mouseChildren on the Image to false, then the MouseEvent will refer to the Image:
if (event.target is Image) {
//do stuff
}
So after a few more hours of research I came up with the below attached to the contextMenu's item select event listener. I am sure there has to be a better way to do this, but until then...
for(var i:int = 0; i < getObjectsUnderPoint(new Point(this.mouseX, this.mouseY)).length; i++)
{
if(getObjectsUnderPoint(new Point(this.mouseX, this.mouseY))[i].parent.parent is Image)
{
//do what I need to do
}
}
Thanks NHubben for your input. It got me going down the right path of looking at children.
The component name Image has no relevance concerning what makes it up. The flex inheritance is: Image -- SWFLoader -- UIComponent -- FlexSprite -- [...] (from mx.controls.Image docs).
So what you need to do is understand what you actually have when you bring it into a AS3 environment. It seems like it gets wrapped up in a MovieClip to allow it be in the Flash's display list. It also looks like you have to go through a loader, but I'm not sure of that.
Run a test or two to find out what the object is actually made up of:
// not foolproof, and will break on some stuff,
// so you will have to fix this as needed:
private function loopDisplay(obj:Sprite):void
{
trace(obj.name + ": " + obj);
if (obj.numChildren > 0)
{
for (var i:int = 0; i < this.numChildren; i++)
{
loopDisplay(obj.getChildAt(i));
}
}
}
If you put this in a mouse down handler, then you can see what is actually there.
However, the event.target or event.currentTarget should also hold the menu item object, so you can also just loop into those objects and see what is in them.

How to access MC inside movieclip added from library?

I have the following code and I followed the answer from this question, but it doesn't seem to be working for me. I'm not getting an error or getting a trace response.
Basically I need to access this test_mc inside the added child. Am I doing something wrong?
for (var i:int=0; i<30; i++) {
var mc:panelClass = new panelClass();
all_mc.addChild(mc);
mc.x = allWidth * i;
// Accessing the test mc
mc.test_mc.addEventListener(MouseEvent.CLICK, ctaOnClickHandler);
}
function ctaOnClickHandler(e:MouseEvent) {
trace("Clicked");
}
Kind of hard to answer this without know what panelClass is and how it is built. I'm assuming test_mc is a movieclip that's using all it's default properties and is on the display list of panelClass and since there are no errors it's been instantiated. The only think I can think of is there anything being displayed on top of test_mc inside panelClass?