simplifying variable.handler = function {} - function

I'm brushing up on my JS, and I don't know how to ask this, exactly.
I have this:
text_area.onkeyup = function() {
var text_length = this.value.length;
var text_remaining = text_max - text_length;
feed_back.innerHTML = "<strong>" + text_remaining + "</strong> charactres remaining";
}
It works. However, should I be able to take the function and pull it out to something like this?
function countDown() {
var text_length = this.value.length;
var text_remaining = text_max - text_length;
feed_back.innerHTML = "<strong>" + text_remaining + "</strong> charactres remaining";
}
and just call the function by its name?
text_area.onkeyup = countDown();
This has never worked for me, across multiple projects.
Should it? Why doesn't it?

You'll have to use:
text_area.onkeyup = countDown;
Without the parenthesis.
countDown is a reference to the actual function object countDown. It's simply a reference, and the function won't be called or executed.
countDown() actually calls the function, and evaluates to whatever it returns.

It doesn't work because () actually calls the function -- effectively setting text_area.onkeyup to the return value of countDown rather than the function itself.
Try this instead:
text_area.onkeyup = countDown;

The problem is that you're executing the function during the assignment, so the return value from the function becomes attached to the event. Instead you should attach a reference:
text_area.onkeyup = countDown
Or if countdown has parameters you want to pass with it then you can use a function to make sure they don't get lost. Something like this:
text_area.onkeyup = function(){ countDown(paremeter1, paremeter2); }

It shouldn't because you're assigning the result of a function call instead of a function reference. Should be:
text_area.onkeyup = countDown;

Related

Google Script call another function to return a value

I'm getting to grips with beginner methods of GScript now but so far have only used one function. Could someone show me how to 'call' another function to check for something and then return a TRUE or FALSE. Here is my attempt (it will eventually check a lot of things but I'm just checking one thing to start..)
Function callAnotherFunctionAndGetResult () {
MyResult = call(CheckTrueFalse)
if(MyResult = True then.. do something)
};
function CheckTrueFalse() {
if(3 > 2) {
CheckTrueFalse = TRUE
Else
CheckTrueFalse = FALSE
};
So basically I just want to get the other function to check something (in this case is 3 bigger than 2?) if it is then return TRUE. From this I should have the knowledge to modify for the real purpose. I'm used to Visual Basic so I've written it more how that would look - I know that won't work. Could someone help me convert so will work with Google Script please?
A function with a return statement is what you're looking for. Assuming you need the called function to take some input from the main function:
function mainFunction() {
//...
var that = "some variable found above";
//call other function with input and store result
var result = otherFunction(that);
if (result) {
//if result is true, do stuff
}
else {
//if result is false, do other stuff
}
}
function otherFunction(that) {
var this = "Something"; //check variable
return (this == that);
//(this == that) can be any conditional that evaluates to either true or false,
//The result then gets returned to the first function
}
You could also skip assigning the result variable and just check the returned condition directly, i.e.:
if (otherFunction(that)) {
//do stuff
}
else {do other stuff}
Let me know if you need me to clarify any of the syntax or if you have any more questions.
Here's a basic sample that might help you:
function petType(myPet){
return myPet;
}
function mainFunctoin(){
var newPet = petType("dog");
if(newPet === "dog"){
Logger.log("true");
}else{
Logger.log("false");
}
}
Execute mainFunction().
If you set petType to "cat", it will return false; but, if you set it to "dog", it will return true.
Let me know if it helped.

Call a random function from an array

I have three functions that I have listed in an array. Now I need a random function of the three to be called when pressing a button. However, when I press the button it calls all three functions and I'm not quite sure where I've gone wrong. It looks like this right now:
function Arm1function1(){
this.parent.parent.parent.Armfront1.visible = true;
this.parent.parent.parent.Armback1.visible = false;
}
function Arm1function2(){
this.parent.parent.parent.Armfront1.visible = false;
this.parent.parent.parent.Armback1.visible = true;
}
function Arm1function3(){
this.parent.parent.parent.Armfront1.visible = false;
this.parent.parent.parent.Armback1.visible = false;
}
function getRandomElementOf(Armbuttonarray1:Array):Object {
var Armbuttonarray1:Array = [Arm1function1(), Arm1function2(), Arm1function3()];
var idx:int=Math.floor(Math.random() * Armbuttonarray1.length);
return Armbuttonarray1[idx];
}
Randombutton1part1.addEventListener(MouseEvent.CLICK, Randombutton1part1Click);
function Randombutton1part1Click(e:MouseEvent):void
{
getRandomElementOf(null);
}
Any clue of where I've gone wrong?
Your issue is this line:
var Armbuttonarray1:Array = [Arm1function1(), Arm1function2(), Arm1function3()];
When populating that array, you are actually populating it with the results of the functions.
Should be:
var Armbuttonarray1:Array = [Arm1function1, Arm1function2, Arm1function3];
Notice the lack of parenthesis ().
You want to actually execute the function on the click handler, so you'll need to tweak that a bit too:
getRandomElementOf(null)();
or
getRandomElementOf(null).call();
As an aside, your getRandomElementOf function should probably look more like this:
function getRandomElementOf(array:Array):Object {
return array[Math.floor(Math.random() * array.length)];
}
Then do:
getRandomElementOf([Arm1function1, Arm1function2, Arm1function3])();

flash get function's argument name

I want to get all arguments names of a function inside the function
example:
function fct(var1:string,var2:string){
var names:Array=...
trace(names);
}
must trace : var1,var2
Thanks!
Simply put, this is not possible. The closest you can get is the argument number and value. See below:
function fct( ... args ):void {
for ( var v:Object in args ) {
trace( v + ": " + args[v] );
}
}
var str1:String = "this is a test";
var str2:String = "this is another test";
fct( str1, str2 );
//output
//0: this is a test
//1: this is another test
For future reference, you can use ... + a variable name to allow for as many arguments as you need. Regardless, you should just need to access args[ INDEX ] rather than the actual variable name, which you wouldn't be able to access anyway because there would be no way to apply scope (such as variableName[ "propertyName" ])
It is impossible like native method, but you can use metadata tag to set arguments names. I create simple example. But i don't understand how it can help you in real projects:
[Arguments(param1="arg1",param2="arg2")]
public function test(arg1:Number, arg2:Number):void {
var desc_xml:XML = describeType(Object(this).constructor);
var metas_xml:XMLList = desc_xml.factory.method.(#name == "test");
var args_xml:XMLList = metas_xml.metadata.(#name == "Arguments");
for each (var argx:XML in args_xml.arg)
{
trace(argx.#value.toXMLString());
}
};
I use flex 4.6. Don't forget add each existing Metadata tags to the compiler argument with “-keep-as3-metadata+=Arguments”. It need for compile release versions.

calling a function from inside another function

I need a little help. I'm trying to create a loop of three functions.
I created the first loop but I can not get to the first function after the
3rd one is done.
I think the best solution is to call the first one inside the third one,
but I'm not sure this is the best way.
Anyway this is my code:
function LOADALL(event:MouseEvent):void{
if (ConditionC == "NotPlaying"){
ConditionC = "Playing";
var urlRequest:URLRequest = new URLRequest(Sounds_Array[i]);
var wav:URLLoader = new URLLoader();
wav.dataFormat = 'binary';
wav.load(urlRequest);
wav.addEventListener(Event.COMPLETE, playWav);
}
}
function playWav(e:Event):void{
var tts:WavSound = new WavSound(e.target.data as ByteArray);
var channel:WavSoundChannel = tts.play();
channel.addEventListener(Event.SOUND_COMPLETE, completeHandler)
}
function completeHandler(e:Event):void{
ConditionC = "NotPlaying";
trace ("hello");
LOADALL();
}
The error is in the 2nd from the end line ( LOADALL(); )
Any help?
You are trying to call the LOADALL function without any arguments, when in fact it requires one argument: event - which is probably why you are getting an error. Since you are not using event in LOADALL, just pass null, ie:
LOADALL(null);

How to assign URLVariables result to a String Variable?

In the following example (yes, I am coding on my timeline while I try to work this out - I know, I know) I am loading an SWF in an HTML page and then directing the SWF to get the query parameters from the current URL. The query parameter will contain the source for the video to play.
This seems straight forward to me but I cannot get myURL = urlVars.videoloc; to work. More specifically, urlVars.videoloc seems to be undefined rather than holding the query parameter from the URL. All other variables are correct; both wholeURL and urlVars are defined.
//Initialize Global Event Listener
player.addEventListener(Event.ADDED_TO_STAGE, getPlay, false, 0, true);
//Function to play the video
function getPlay(e:Event):void {
var wholeURL:String = ExternalInterface.call("window.location.search.toString");
var urlVars:URLVariables = new URLVariables(wholeURL);
var myURL:String = urlVars.videoloc; //<--- Trouble, returning 'undefined'
errorBox.text = "videoloc="+urlVars.videoloc+"\nwholeURL="+wholeURL+"\nurlVars="+urlVars+"\nmyURL="+myURL; //<--- The reason I know it is returning 'undefined'
if (myURL) {
player.load(myURL);
player.play();
}
}
Ideally you should use a debugger to inspect the makeup of your URLVariables object.
If you're unable to do things the easy way, you could do this to trace its contents:
for (var parameter:String in urlVars) {
trace(parameter + "=" + urlVars[parameter]);
}
As you can see, you can step through every parameter inside urlVars using a for in loop.
I'm guessing videoLoc is your first parameter? Look at the results of this test of mine:
var address:String = "http://www.google.ca/search?q=test&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-GB:official&client=firefox-a";
var urlVars:URLVariables = new URLVariables(address);
for (var parameter:String in urlVars) {
trace(parameter + "=" + urlVars[parameter]);
}
The output of this is:
aq=t
rls=org.mozilla:en-GB:official
client=firefox-a
http://www.google.ca/search?q=test
ie=utf-8
oe=utf-8
See what happened to the q parameter? To fix this, use only the text past the ?
var address:String = "http://www.google.ca/search?q=test&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-GB:official&client=firefox-a";
var urlVars:URLVariables
= new URLVariables(address.substr(address.indexOf('?')+1));
for (var parameter:String in urlVars) {
trace(parameter + "=" + urlVars[parameter]);
}