Greetings stackoverflow members,
i have 3 animated movieclips nested in a movieclip. What I'm trying to do is to get the name of the instance clicked and edit it befor applying gotoAndPlay. I can get the name but when ever I try to edit it I'm getting the Error:
Symbol 'Buttons MC', Layer 'Actions', Frame 1, Line 30 1061: Call to a possibly undefined method gotoAndPlay through a reference with static type String.
Here's my code so far:
[Bindable] var targetName:String;
var _userInput:String = new String();
_userInput = targetName;
//array for buttons
var btnArray:Array = [INS_Btn1, INS_Btn2, INS_Btn3];
//add eventlistiners
for(var i:uint=0; i<btnArray.length; i++) {
btnArray[i].addEventListener(MouseEvent.ROLL_OVER, bRollover);
btnArray[i].addEventListener(MouseEvent.ROLL_OUT, bOut);
btnArray[i].addEventListener(MouseEvent.CLICK, bClick);
btnArray[i].buttonMode=true;
}
//btn over state
function bRollover(event:MouseEvent):void{
event.target.gotoAndPlay("Over");
}
//btn out state
function bOut(event:MouseEvent):void{
event.target.gotoAndPlay("Out");
}
//btn click state
function bClick(event:MouseEvent):void{
targetName = event.target +("_ani")
targetName.gotoAndPlay("Active");
}
What I want is that the MC clicked should go and play the animation of an onther MC. Best I should mention that I'm a beginner in AS3.
targetName is a String and of course you can't gotoAndPlay on a string :) Besides of that, event.target will return the object that you've clicked and not its name. And the targetName does not need to be bindable if you don't do anything special with it besides of this code.
So I assume you want a movieclip with the instance name INS_Btn1_ani to be played when you click on the INS_Btn1 button? First, make sure your buttons have the name property set (to make it easier, set the name as "INS_Btn1", "INS_Btn2" etc as well.
INS_Btn1.name = "INS_Btn1";
Then you would do it like that:
function bClick(event:MouseEvent):void
{
targetName = event.target.name + "_ani"; // this will become INS_Btn1 + _ani = INS_Btn1_ani
// Now you need to let the movieclip with the name "INS_Btn1_ani" play
this[targetName].gotoAndPlay("Active");
}
So after understanding the answer from Philarmon I've solved the problem. In case someone has the same/similar problem here's what I've done to get it working:
var targetName:String;
var _userInput:String = new String();
_userInput = targetName;
//array for buttons MCs
var btnArray:Array = [INS_btn1, INS_btn2];
var aniArray:Array = [INS_btn1_ani, INS_btn2_ani];
//add eventlistiners
for(var i:uint=0; i<btnArray.length; i++) {
btnArray[i].addEventListener(MouseEvent.ROLL_OVER, bRollover);
btnArray[i].addEventListener(MouseEvent.ROLL_OUT, bOut);
btnArray[i].addEventListener(MouseEvent.CLICK, bClick);
btnArray[i].buttonMode=true;
}
//btn over state
function bRollover(event:MouseEvent):void{
targetName = event.currentTarget.name + "_ani";
this[targetName].gotoAndPlay("Over");
}
//btn out state
function bOut(event:MouseEvent):void{
targetName = event.currentTarget.name + "_ani";
this[targetName].gotoAndPlay("Out");
}
//on clicked
function bClick(event:MouseEvent):void{
//add listeners for unclicked
for (var i:uint=0;i<btnArray.length; i++){
btnArray[i].addEventListener(MouseEvent.ROLL_OUT, bOut);
btnArray[i].addEventListener(MouseEvent.ROLL_OVER, bRollover);
//stopping animation
aniArray[i].gotoAndStop("Out");
}
//remove Eventlistener when clicked
event.target.removeEventListener(MouseEvent.ROLL_OUT, bOut);
event.target.removeEventListener(MouseEvent.ROLL_OVER, bRollover);
targetName = event.currentTarget.name + "_ani";
this[targetName].gotoAndStop("Active");
}
As you can see I've added a "sticky" function to keep the mc on click state.
Related
How can click on any button to load the array into the concrete contents of the array Teddy I Grateful (Load Movieclips Array Click button Array)
var teddy:Array = [home,about,products,services,contact];
var l:int = teddy.length;
for (var j:int = 0; j < l; j++) {
var mc1=new teddy[j];
var mc2=new teddy[1];
teddy[j].buttonMode = true;
var Btn:Array = [Btnhome,Btnabout,Btnproducts,Btnservices,Btncontact];
var W:int = Btn.length;
for (var i:int = 0; i < W; i++) {
var mc:MovieClip = new Btn[i];
mc.buttonMode = true;
mc.x=400+i*100;
mc.y=600+i;
mc.addEventListener(MouseEvent.CLICK, clickHandler);
addChild(mc);
}
}
function clickHandler(event:MouseEvent):void {
switch (event.currentTarget) {
case mc :
addChild(mc1);
trace("home");
mc1.x=400;
mc1.y=200;
break;
case mc :
addChild(mc2);
trace("about");
mc2.x=400
mc2.y=300
break;
case products_mc :
trace("products");
break;
case services_mc :
trace("services");
break;
case contact_mc :
trace("contact");
break;
}}
if [home,about,products,services,contact],
and [Btnhome,Btnabout,Btnproducts,Btnservices,Btncontact] are object instance Name's, then your code is wrong.
But in that case, you can position them once, then each time set them visible/invisible with this;
// set as invisible
myArray[i].visible = false;
// set as visible
myArray[i].visible = true;
Else, if you have to re-create them each time, then you must specify an Object Class for your objects, and call them with their object classes
var mc = new myObjClass();
And to give object classes names that you can refer from your code, do the following;
In your Library panel,
Select the MovieClip you want to create instances of,
[Right-Click] > Properties...
Check Export for ActionScript
And give Class name below. Then use that class name in your code to create new MovieClip instances of it every time.
Depending on your Flash version that process can be slightly different. But you can google it anyway.
Hope that helps.
Okay I will try to help you one more time. But you must talk to the people trying to help you. If you dont understand just ask. Also at least up-vote useful answers to your questions or mark as correct if it works okay. Otherwise no-one wants to type tutorials (because there is Google and ActionScript manual for that).
The best way to test my shown code is... Make a new blank FLA file and save to some folder. Now go to Properties (ctrl+F3) and in the Class: box type in there Array_buttons_v1 (press enter and save FLA again). Now you can click the pencil icon next to Class: box to edit your Class document. You will replace that auto-code with mine shown below.. (in photo: MyClass becomes Array_buttons_v1)
image borrowed from: Adobe.com
You will also need 5 movieClips in your library (ctrl+L). That is one movieClip to use as button MC and then four other movieClips to be added on stage when you click. Each one in Library must be right-clicked and choose "properties" then in Linkage section tick Export for Actionscript and use the following name in Class box shown there..
one small MC as button use: btn_MC (later we make MC clickable just like a real button)
other four MCs to add when button clicked use: MC1, MC2, MC3, MC4
Now you can use the main Properties (crtl+F3) to click the pencil icon (see pencil in photo) and delete all that automatic code and paste this code there.. (try to understand what code is doing, not just copy+paste..). It makes four buttons from MC class name btn_MC into some array and then loads other four MCs to array then from Mc array can add to screen too. Hope it helps
package
{
//** You will need more IMPORTS as you use other Flash features (APIs)
//** But these two is enough here.. check AS3 manual or tutorials for what to add
import flash.display.MovieClip;
import flash.events.*;
public class Array_buttons_v1 extends MovieClip
{
public var MC_Array:Array = []; //new array is empty
public var Btn_Array:Array = [];
public var MC_0 : MC1 = new MC1();
public var MC_1 : MC2 = new MC2();
public var MC_2 : MC3 = new MC3();
public var MC_3 : MC4 = new MC4();
public var btn_0 : btn_MC = new btn_MC();
public var btn_1 : btn_MC = new btn_MC();
public var btn_2 : btn_MC = new btn_MC();
public var btn_3 : btn_MC = new btn_MC();
public var mClips_holder : MovieClip = new MovieClip;
public var buttons_holder : MovieClip = new MovieClip;
public function Array_buttons_v1()
{
//** Update MC array.. items are counted from 0,1,2,3 (NOT 1,2,3,4)
MC_Array = [ MC_0, MC_1, MC_2, MC_3 ]; //meaning array pos [ 0, 1, 2, 3 ]
stage.addChild( mClips_holder ); //will hold
mClips_holder.y = 70; //move down so its not blocking anything
//** Update Buttons array
Btn_Array = [ btn_0, btn_1, btn_2, btn_3 ];
stage.addChild( buttons_holder ); //put Button holder on stage
//buttons_holder.addChild( Btn_Array [0] ); //put Buttons inside holder
var insert_pos:int = 0; //will use as screen "adding position" for buttons
//** To add all in array.. we start from pos of 0 and count up to 3
//** For every count number we do instructions inside { } until count finished
for (var arr_pos:int = 0; arr_pos <= 3; arr_pos++) //create some counter
{
trace("position inside the array is now : " + arr_pos);
//** setup instance Names for movieClips inside the MC Array
//** later you can access each one by name using "getChildByName" as MC_1 or MC_2 etc..
MC_Array[arr_pos].name = "MC_" + ( String(arr_pos) );
//** setup Buttons (names, clicked functions etc )..
Btn_Array[arr_pos].name = "button_" + ( String(arr_pos) );
Btn_Array[arr_pos].buttonMode = true; //make clickable before adding to screen
Btn_Array[arr_pos].addEventListener(MouseEvent.CLICK, button_Clicked);
buttons_holder.addChildAt( Btn_Array [arr_pos], arr_pos ); //add to container
buttons_holder.getChildAt(arr_pos).x = insert_pos;
trace("pos of btn is now : " + buttons_holder.getChildAt(arr_pos).x);
//update the adding position amount
insert_pos += 50; //add +50 pixels distance for next item
} //end For loop
}
public function button_Clicked ( evt :MouseEvent ) : void
{
//** Use "evt" because it matches with above "evt:MouseEvent" for access
trace( "Button name: " + evt.currentTarget.name + " ..was clicked" );
//** Now you can use IF statement to run another function(s)
//if (evt.currentTarget.name == "button_0") { some_Test(); }
//** or Use SWITCH statement (better and easier)
switch (evt.currentTarget.name)
{
case "button_0" :
//mClips_holder.addChild(MC_0); //** can be done like this ..
mClips_holder.addChild( MC_Array[0] ); //but you wanted from array so do this way..
mClips_holder.getChildByName("MC_0").x = 0;
some_Test(); //to do some other function
//** to stop this button listening for mouse clicked
//Btn_Array[0].removeEventListener(MouseEvent.CLICK, button_Clicked);
break;
case "button_1" :
mClips_holder.addChild(MC_1);
mClips_holder.getChildByName("MC_1").x = 40;
//Btn_Array[1].removeEventListener(MouseEvent.CLICK, button_Clicked);
break;
case "button_2" :
mClips_holder.addChild(MC_2);
mClips_holder.getChildByName("MC_2").x = 80;
//Btn_Array[2].removeEventListener(MouseEvent.CLICK, button_Clicked);
break;
case "button_3" :
mClips_holder.addChild(MC_3);
mClips_holder.getChildByName("MC_3").x = 120;
break;
} //end Switch/Case
}
public function some_Test ( ) : void
{
trace(" ### This is some other function... do extra things in this section");
//your extra code here..
}
}
}
I would like to make my Flash AS3 based app more accessible with a keyboard navigation.
What's the best way to add to every MovieClip with a MouseEvent.CLICK the ability to get selected through the TAB and clicked/fired through ENTER?
Some basic example of my code:
nav.btna.addEventListener(MouseEvent.CLICK, openSection);
dialog.btnx.addEventListener(MouseEvent.CLICK, closeDialog);
function openSection(event:Event=null):void
{
trace("nav.btna")
}
function closeDialog(event:Event=null):void
{
trace("dialog.btnx")
}
I remember that there was a AS3 function that enabled that every MovieClip with a MouseEvent could be fire through ENTER if the MovieClip was selected with TAB. I can't remeber the function though.
I think the problem may be that you are attempting this with a MovieClip instead of a button (Button or SimpleButton).
I made a simple test by creating buttons instead of MovieClips in my library and this worked as expected:
// I have 4 buttons (button1, button2, etc) on the stage
for(var i:int = 1; i <= 4; i++)
{
var mc = getChildByName("button" + (i+1));
mc.tabIndex = i;
mc.addEventListener(MouseEvent.CLICK, onClicked);
}
function onClicked(e:MouseEvent):void
{
trace(e.currentTarget + " clicked");
}
stage.focus = stage;
I initially ran this test with MovieClip instances, and while they would show that the tab was working (a yellow border shows up), the MouseEvent.CLICK was never firing. Once I switched to actual buttons (SimpleButton in this case), it worked with both the Enter and Space keys.
EDIT:
To answer the question posed in the comments, this is a quick-and-dirty way to "convert" MovieClips to SimpleButtons at runtime:
// I have 4 MovieClips (button1, button2, etc) on the stage
for(var i:int = 1; i <= 4; i++)
{
var mc:MovieClip = getChildByName("button" + i) as MovieClip;
var button:SimpleButton = convertMovieClipToButton(mc);
button.tabIndex = i;
button.addEventListener(MouseEvent.CLICK, onClicked);
}
function convertMovieClipToButton(mc:MovieClip):SimpleButton
{
var className:Class = getDefinitionByName(getQualifiedClassName(mc)) as Class;
var button:SimpleButton = new SimpleButton(new className(), new className(), new className(), new className());
button.name = mc.name;
button.x = mc.x;
button.y = mc.y;
mc.parent.addChildAt(button, getChildIndex(mc));
mc.parent.removeChild(mc);
return button;
}
I have several movie clips on the stage of my main .fla named btn1-btn7 which will act as buttons. I have a class file named Functions.as where an event listener is created when a button is clicked. onButtonClicked is just going to a frame on the timeline.
obj.addEventListener(MouseEvent.CLICK, onButtonClicked);
I would like the ability to set the buttonMode, visibility, etc. of all of the buttons simultaneously. I have been looking into this for a few hours and am not able to find any solutions. I am now looking into adding them to a vector (which is a new concept for me), but I am not sure how to go about executing this properly. This is what I have so far.
public var buttons:Vector.<MovieClip > = new Vector.<MovieClip > ();
function addButtons()
{
buttons.push(btn1,btn2,btn3,btn4,btn5,btn6,btn7);
for (var i:int; i<buttons.length; i++)
{
trace(buttons[i].name);
}
}
How would I go about, for example, adding the event listener to all of the objects? I will also be setting the buttonMode to true, and making them all invisible simultaneously. I don't even know if it's possible to accomplish this. Thank you in advance for any suggestions.
I'm going to asume that you use timeline code, and have instances of the buttons already placed on the stage. So, first, create the vector:
var _btns:Vector.<MovieClip> = new Vector.<MovieClip>;
_btns.push(btn1,btn2,btn43....) //add all the buttons
Than, you can init the properties of all the buttons:
var _mc:MovieClip;//helper var
for(var i:int=0,i<_btns.length;i++)
{
_mc = _btns[i];
_mc.visible = false;
_mc.buttonMode = true;
_mc.addEventListener(MouseEvent.CLICK, onClick);
}
Then, the event handler:
function onClick(e:MouseEvent):void
{
for(var i:int=0,i<_btns.length;i++)//reset all the buttons
{
_btns[i].visible = false;
}
_mc = MovieClip(e.eventTarget);
_mc.visible = true; //make visible the clicked one
}
You just need to do what you are doing with the .name property in your example code. You need to loop thru every single button in your array (or vector, if you prefer). Here is an example how to set the property of buttonMode:
function setButtonMode(b:Boolean):void {
for(var i:int=0; i<buttons.length; i++) {
var btn:MovieClip = buttons[i]; //store the current reference in a var for faster access
btn.buttonMode = b;
btn.mouseChildren = !b;
}
}
I'm trying to make something like bookmarks, I have 1 note on the stage and when the user clicks it, it starts to drag and the users drops it where they want. the problem is I want these notes to be dragged multiple times.. here is my code:
import flash.events.MouseEvent;
//notess is the instance name of the movie clip on the stage
notess.inputText.visible = false;
//delet is a delete button inside the movie clip,
notess.delet.visible = false;
//the class of the object i want to drag
var note:notes = new notes ;
notess.addEventListener(MouseEvent.CLICK , newNote);
function newNote(e:MouseEvent):void
{
for (var i:Number = 1; i<10; i++)
{
addChild(note);
//inpuText is a text field in notess movie clip
note.inputText.visible = false;
note.x = mouseX;
note.y = mouseY;
note.addEventListener( MouseEvent.MOUSE_DOWN , drag);
note.addEventListener( MouseEvent.MOUSE_UP , drop);
note.delet.addEventListener( MouseEvent.CLICK , delet);
}
}
function drag(e:MouseEvent):void
{
note.startDrag();
}
function drop(e:MouseEvent):void
{
e.currentTarget.stopDrag();
note.inputText.visible = true;
note.delet.visible = true;
}
function delet(e:MouseEvent):void
{
removeChild(note);
}
any help will be appreciated.
You need to create a new instance of your note class when you drop, copy the location and other variables from the note you were dragging, add your new note to the stage, and return the dragging note to its original position.
Something like:
function drop($e:MouseEvent):void
{
$e.currentTarget.stopDrag();
dropNote($e.currentTarget as Note);
}
var newNote:Note;
function dropNote($note:Note):void
{
newNote = new Note();
// Copy vars:
newNote.x = $note.x;
newNote.y = $note.y;
// etc.
// restore original note.
// You will need to store its original position before you begin dragging:
$note.x = $note.originalX;
$note.y = $note.orgiinalY;
// etc.
// Finally, add your new note to the stage:
addChild(newNote);
}
... this is pseudo-code really, since I don't know if you need to add the new note to a list, or link it to its original note. If you Google ActionScript Drag Drop Duplicate, you will find quite a few more examples.
I think you are not target the drag object in drag function and problem in object instantiation
for (var i:Number = 1; i<numberOfNodes; i++) {
note = new note();
addChild(note);
...
....
}
function drag(e:MouseEvent):void{
(e.target).startDrag();
}
If you are dragging around multiple types of objects (eg. Notes and Images), you could do something like this, rather than hard coding the type of object to be instantiated.
function drop(e:MouseEvent):void{
// Get a reference to the class of the dragged object
var className:String = flash.utils.getQualifiedClassName(e.currentTarget);
var TheClass:Class = flash.utils.getDefinitionByName(className) as Class;
var scope:DisplayObjectContainer = this; // The Drop Target
// Convert the position of the dragged clip to local coordinates
var position:Point = scope.globalToLocal( DisplayObject(e.currentTarget).localToGlobal() );
// Create a new instance of the dragged object
var instance:DisplayObject = new TheClass();
instance.x = position.x;
instance.y = position.y;
scope.addChild(instance);
}
I'm trying to create an accordion menu off of an online tutorial. I followed every step (i think) on Original Tutorial but changed things according to my size, as well as make the instance names end with _mc or _txt accordingly. But for some reason it doesn't seem to be working.
I'm getting the #1010 error and it doesn't really clarify anything:
TypeError: Error #1010: A term is
undefined and has no properties.
at
tutorial_fla::MainTimeline/placeItemsOnStage()
at
tutorial_fla::MainTimeline/onComplete()
at
flash.events::EventDispatcher/dispatchEventFunction()
at
flash.events::EventDispatcher/dispatchEvent()
at flash.net::URLLoader/onComplete()
I have my first xml file that has all the images to insert and that one hasn't been changed at all should work fine.
I know this is long, but I'm hoping someone can check it out anyhow. I'm extremely new to this and would pretty much have to abandon the whole project. Thanks so much!
my code:
//import tweenlite classes
import gs.TweenLite;
import gs.easing.*;
var MENU_ARRAY:Array; //used to save the items data
var OPENED_MENU:int; //to inform the menu that should be open at startup
var MOVE_ON_MOUSE_OVER:Boolean=false; //tha name says everything
var xmlLoader:URLLoader; //the xml loader
loadXML("menu2.xml"); //load the xml
function loadXML(Uri:String):void {
xmlLoader = new URLLoader();
xmlLoader.addEventListener(Event.COMPLETE, onComplete);
xmlLoader.addEventListener(IOErrorEvent.IO_ERROR, onError);
xmlLoader.load(new URLRequest(Uri));
}
function onError(evt:ErrorEvent):void {
trace("cannot load xml file");
}
function onComplete(evt:Event):void {
//read and load xml into array, by parsing it using prepareMenu
MENU_ARRAY=prepareMenu(xmlLoader.data.toString());
placeItemsOnStage(); //place all required items on stage.
}
function placeItemsOnStage():void {
var pos:Number=0;
//define the container properties
menuContainer_mc.x=0;
menuContainer_mc.y=0;
for(var c:int=0; c<MENU_ARRAY.length; c++) {
var it:menuItem = new menuItem; //load out menuItem, because its exported to AS, we can use it here
it.x=c*51; //its the gray border width
it.y=0; //place on top
it.id="Item-"+c; //id the menuItem
it.name="Item-"+c; //name de menuItem
it.posX=pos; //actual pos, useful to open and know is position
it.itemLabel_txt.text=String(MENU_ARRAY[c].Ititle).toUpperCase(); //load the label in uppercase
it.addEventListener(MouseEvent.CLICK, onMouseClick); //add mouse click listener
if(MOVE_ON_MOUSE_OVER==true) it.addEventListener(MouseEvent.MOUSE_OVER, onMouseOver); //if configured, load the mouse over event
it.useHandCursor=true; //use hand cursor
it.buttonMode=true; //buttonMode
it.itemText_txt.visible=false; //hide the textField
menuContainer_mc.addChild(it); //add the menu item as child
if(String(MENU_ARRAY[c].IcontentType)=="image/swf") { //check the content and load things accordint to it
var ldr:Loader = new Loader();
ldr.x=51;
ldr.y=0;
it.addChild(ldr);
ldr.load(new URLRequest(MENU_ARRAY[c].IcontentData.toString()));
}
else if(String(MENU_ARRAY[c].IcontentType)=="text") {
it.itemText_txt.visible=true;
it.itemText_txt.text=MENU_ARRAY[c].IcontentData.toString();
}
pos+=51; //the next menuItem x position
}
//put mask in place
masker_mc.width=(MENU_ARRAY.length*51+700)
masker_mc.height=menuContainer_mc.height;
masker_mc.x=0;
masker_mc.y=0;
moveItem(OPENED_MENU-1); //open menu confirured in XML
}
function onMouseOver(evt:MouseEvent):void {
if(evt.target.name.toString()=="buttonBack") prepareMove(evt)
}
function prepareMove(evt:MouseEvent):void {
var targetName:String = evt.currentTarget.name.toString(); //get the menuItem
var temp:Array = targetName.split("-"); //split his name: Item-x
var itemNumber:int=(temp[1]); //got item number
moveItem(itemNumber); //move it
}
function onMouseClick(evt:MouseEvent):void {
if(evt.target.name.toString()=="buttonBack") prepareMove(evt); //mouse action was done in buttonBack
else trace("Item "+evt.currentTarget.name+" clicked!"); //mouse action was made on accordion area
}
function moveItem(num:int):void {
var itemToMove:menuItem=menuContainer_mc.getChildByName("Item-"+String(num)) as menuItem;
//get the menuItem child
for(var m=0;m<MENU_ARRAY.length;m++) //move one-by-one to the new position
{
var tempMc = menuContainer_mc.getChildByName("Item-"+m);
if(tempMc.x > itemToMove.x) TweenLite.to(tempMc, 1, {x:((tempMc.posX) + itemToMove.width-51), ease:Quart.easeOut}); //see tweenLite for info about this.
else if(tempMc.x <= itemToMove.x) TweenLite.to(tempMc, 1, {x:(tempMc.posX), ease:Quart.easeOut});
}
}
function prepareMenu (XMLData:String):Array
{
//make sure it cames in XML
var menuXML:XML = new XML(XMLData);
//just in case
menuXML.ignoreWhitespace = true;
//get XML item's entrys
var XMLItems = menuXML.descendants("item");
//load all items into an array
var itemsArray:Array = new Array();
var itemObj:Object;
for(var i in XMLItems)
{
itemObj=new Object();
itemObj.Ititle=XMLItems[i].#Ititle;
itemObj.IcontentType=XMLItems[i].#IcontentType;
itemObj.IcontentData=XMLItems[i].#IcontentData;
itemObj.itemID="menu"+i;
itemsArray.push(itemObj);
}
OPENED_MENU=menuXML.#menuOpen; //get menu for open.
MOVE_ON_MOUSE_OVER=(menuXML.#moveOnMouseOver.toString()=="true" ? true : false); //get the option for load or not mouseOver open
return itemsArray;
}
//finish.
stop();
"term" refers to an identifier, "Error #1010: A term is undefined and has no properties" means you are using an expression which cannot be evaluated. This usually happens when you try to access and use an undefined object property via its string name as in myobject["property"].method(). Can you provide the exact line on which the exception is raised?