How to insert a g:text object inside another html element? - sidebar

I'm developing a Windows gadget. There is a function called addTextObject on the background object which creates the object I want which I can later add glowing and shadows to it. But the problem is that I am not able to control the objects location. For example, if I want to append it inside a div or span or td, the appendChild method is not working. How can I fix this?
var txtGlow = document.getElementById('imgBackground').addTextObject("test", "Verdana", 25, "Red", 50, 50);
txtGlow.opacity = 100;
txtGlow.addGlow("yellow", 50, 50);
var theDiv = document.getElementById('divx');
txtGlow.value = theDiv.innerText;
theDiv.appendChild(txtGlow);

Text and image objects added to the background aren't elements and as such can't be appended to just any element. You can create a <g:text> element in your HTML markup, but they don't behave in the same way:
Note This method does not expose the objects as g:image or g:text elements. You can locate and assign the objects using the document.getElementById("...") method, but the g:image or g:text methods and properties are not available.
You could create the element using document.createElement() or innerHTML.

Related

How to know google map controls creation is done?

I need to dynamically create a ui widget with a parent div.id='myDivId', which is a google map control.
var centerControlDiv = document.createElement('div');
var centerControl = new CenterControl(centerControlDiv, map);
centerControlDiv.index = 1;
centerControlDiv.id = 'myDivId';
map.controls[google.maps.ControlPosition.TOP_CENTER].push(centerControlDiv);
// $('#myDivId') causes exception as $('#myDivId') is not created on
// map as a DOM element yet.
var uiWidget = new uiWidget('myDivId');
// $(#myDivId) is used in class uiWidget().
class uiWidget {
constructor(divId) {
this.id = divId;
// It should fail here due to this.$div property, as
// div 'myDivId' is not a DOM element yet by google map
// controls API.
this.$div.click($.proxy(this.event_click, this));
}
get $div() {
return $(‘#’ + this.id);
}
event_click(eve) {
}
}
But, there is no event of when this parent div is created. Therefore, the child ui widget can't be created at correct time.
How to know parent div with id 'myDivId' is created?
You are trying to reference a DOM element by ID as a child of document when that element has only been created but not yet added to the document.
But you already have a reference to the #myDivId element in the centerControlDiv variable, so you don't need to use the ID to reference it. Just change this line:
$('#myDivId').append("<div>UI widget</div>");
to:
$(centerControlDiv).append("<div>UI widget</div>");
Put another way, to answer your question "How to know parent div with id 'myDivId' is created?", that div already is created - you created it in the document.createElement('div') call. It just isn't a child of document yet.
So when you use $('#myDivId'), or similar calls like document.getElementById('myDivId'), those calls can't see it. It's just a standalone element that you have a reference to, so you can access it through that element instead of looking it up in the document DOM.
Update based on your latest code:
To apply this principle to your uiWidget class, you can have the class work with the actual div element you created instead of accessing it by ID. Even better, since you're using jQuery, pass it a jQuery object from the beginning, like this:
var uiWidget = new UiWidget( $(centerControlDiv) );
class UiWidget {
constructor($div) {
this.$div = $div;
this.$div.click($.proxy(this.event_click, this));
}
// ...
}
As you can see, the code no longer requires the div ID at all, and it doesn't need the get $div() either. $div and this.$div are already a jQuery object wrapping your centerControlDiv.
I also changed the name of the class to UiWidget to follow recommended JavaScript style and avoid conflict with the uiWidget variable that holds an instance of the class.

AS3: A term is undefined when adding a shape inside a movieclip

I have what seems to be a very simple issue. I need to create a shape and add it inside a movie clip that is inside of another movie clip.
The code I am currently using is as follows:
var enemy_beacon:Shape = new Shape();
fullmenu_mc.menu_map_mc.addChild(enemy_beacon);
fullmenu_mc.menu_map_mc.enemy_beacon.graphics.lineStyle(1, 0xFF0000, 1);
fullmenu_mc.menu_map_mc.enemy_beacon.graphics.beginFill(0xFFBB00,1);
fullmenu_mc.menu_map_mc.enemy_beacon.graphics.drawCircle(50, 50, 25);
fullmenu_mc.menu_map_mc.enemy_beacon.graphics.endFill();
However, this code throws an Error #1010: A term is undefined and has no properties.
It seems to create the shape fine, but adding the shape (via addChild) or accessing any of its properties makes everything go haywire.
I already checked the instance names of the movie clips, everything is spelled correctly and nested correctly.
Any thoughts?
Since you have enemy_bacon instance, you can access it directly:
var enemy_beacon:Shape = new Shape();
fullmenu_mc.menu_map_mc.addChild(enemy_beacon);
enemy_beacon.graphics.lineStyle(1, 0xFF0000, 1);
enemy_beacon.graphics.beginFill(0xFFBB00,1);
enemy_beacon.graphics.drawCircle(50, 50, 25);
enemy_beacon.graphics.endFill();
The problem is that you don't give a name to your Shape.
fullmenu_mc.menu_map_mc doesn't know that your variable named enemy_beacon is the same that you've added to it's children.
Targeting children like that means that you are using their instance names. So fullmenu_mc.menu_map_mc.enemy_beacon means that you are searching a child called enemy_beacon inside menu_map_mc. And with the first two lines, you've just added some child to that menu item, but haven't specified name.
Instance names are not the same as your variables. Check this out:
var myShape:Shape = new Shape();
myShape.name = 'otherShape';
this.addChild(myShape); // you add specific item, name doesn't matter
trace (this.getChildByName('otherShape') == myShape); // you get child by NAME
// and because the child is the same as you've added, this will output: TRUE

How to detect if a specific button has been clicked?

I have various colour buttons that change the colour of a movieclip on click but I want to write code that says like if btnRed has been clicked, apply red ColorTransform. This is because I have multiple buttons and I don't want to have to write methods that are almost identical just with different RGB multiplier values. Is there a way of doing it so that the event listener for each button calls the same method but then within that method it basically says if redBtn is clicked, change color to red, if blueBtn is clicked, change color to blue etc.
As M4tchB0X3r indicated, use a Dictionary to store a lookup of button object to color transform. Here is working code, assuming your button names are btnRed, btnGreen, and btnBlue, and that you have some kind of named object on the stage called box1.
They key points here are that the Dictionary can use object references as keys (not just integers and strings as with the simple Object type), and that the target property of an Event object holds a reference to the thing that raised the event--in this case a button. In fact it's probably safer to use currentTarget, because sometimes target is a parent or child display object, due to the way events can bubble up and down the tree.
import flash.utils.Dictionary;
import flash.geom.ColorTransform;
var buttonToTransform:Dictionary = new Dictionary();
buttonToTransform[btnRed] = new ColorTransform(1.0, 0.2, 0.2);
buttonToTransform[btnGreen] = new ColorTransform(0.2, 1.0, 0.2);
buttonToTransform[btnBlue] = new ColorTransform(0.2, 0.2, 1.0);
// Note: for..in iterates over the keys of an object
// (vs. for each, which iterates over the values)
for(var btn:* in buttonToTransform) {
btn.addEventListener(MouseEvent.CLICK, onTransform);
}
function onTransform(e:MouseEvent):void {
this.box1.transform.colorTransform = buttonToTransform[e.currentTarget];
}
Hold all your Buttons in an Array, in the CLICK Event determin which one was pressed with buttonArray.indexOf(event.target);
then get the according color value from a map like a Dictionary or an Object.
You could also keep your Buttons in the Dictionary itself and loop through it to find your color.

How to change borderColor in Spark Button in runtime?

I need to set up some parameters in spark Buttons. I tried setStyle, but it doesn't work with borderColor.
My code is something like this:
for each (var prop:XML in option.elements()){
var but:spark.components.Button = new spark.components.Button();
but.label=prop
but.width=button_width
but.setStyle("verticalAlign",'middle')
but.setStyle('chromeColor', '#'+arrayRGB[j]) // arrayRGB have the colors i need
but.setStyle('borderColor','#'+arrayRGB[i]) //<-- Don't work
container.addElement(but)
}
Honestly, if you can create a new SkinClass for the button, set the Rect property in there, and give it a border, that's your best option. Then you can just to but.setSkinClass and control it from there.
Think of the button's "skin" has a child object to the button object and not just a property.

Is there a way to keep an object always at the top of the display list?

Is there a way to make a display object always be at the top of the display list?
For example, I know you can set the childIndex, i.e:
setChildIndex(myDisplayObject, numChildren-1);
But is there a way that an object has sensed that something else has been added to the display list and restack themselves accordingly?
You can listen to the Event.ADDED event on the container. This event will bubble up, so you'll get called whenever a display object is added to the container or any of its children.
Here's an example of how you could do this. You'll see the black box always stays on top.
var container:DisplayObjectContainer = this; // this is a frame script but just change this line as necessary
container.addEventListener(Event.ADDED,handleAdded,true);
function handleAdded(e:Event):void {
// this if tries to cover some edge cases, unlikely to happen in your code, from your description
if(container == topElement.parent && container.numChildren > 0 && container.getChildIndex(topElement) != container.numChildren - 1) {
container.setChildIndex(topElement,numChildren - 1);
}
}
function getSprite(c:uint):Sprite {
var sp:Sprite = new Sprite();
sp.graphics.beginFill(c);
sp.graphics.drawRect(0,0,100,100);
sp.graphics.endFill();
return sp;
}
var topElement:Sprite = getSprite(0);
container.addChild(topElement);
var sp:Sprite = getSprite(0xff0000);
container.addChild(sp);
sp.addChild(getSprite(0xff00));
var sp2:Sprite = getSprite(0xff);
container.addChild(sp2);
However, I think it's much simpler and cleaner just to have 2 containers, say, top and bottom, kind of like layers. In top you'd add the element that always must be on top (or this could be your element as you probably don't need to have this extra container). In bottom you'd add and remove whatever you want. Then you can forget about manually restacking stuff (at least to keep the top element atop).
You can override the addChild() method in the parent object. In that method you can move your child to the top using
setChildIndex(myDisplayObject, numChildren-1);
In this way everytime an object is added to the parent, the parent moves your object to the top.