Parameter passing for multiple text fields that are gathered in an array? - actionscript-3

So, I have a question. I'm currently working an an education program that teaches basics on cell organelles. I have lines pointing to each organelle, in which I want to have the user be able to input what each organelle name is (like a diagram). When the user has completed the work properly, I will display the next button.
However, in order to give the user the ability to proceed, I need a way of tracking whether or not a student's answers are correct. I am using parameter passing for this.
I would like to be able to return either true/false. If all answers are returned true, the user may advance. If even one answer is wrong, a message displays.
How do I use parameter passing to determine if a users answers are right/wrong? The textfields are in an array as well...
Here is the code.
Thanks!
-Zero;
import flash.events.MouseEvent;
var organelleInput:Array=[F18nucleolusInput_txt, F18nucleusInput_txt, F18erInput_txt, F18golgiInput_txt, F18vacuoleInput_txt, F18chloroplastInput_txt, F18lysosomeInput_txt, F18mitochondriaInput_txt];
F18next_btn.visible=false;
F18next_btn.addEventListener(MouseEvent.CLICK, F18goToFrameNineteen);
F18back_btn.addEventListener(MouseEvent.CLICK, F18goToFrameSix);
checkMyWork_btn.addEventListener(MouseEvent.CLICK, checkAnswers);
function checkAnswers(event:MouseEvent):void
{
var answer:String;
var correctAnswers:Boolean;
var incorrectAnswers:Boolean;
answer = organelleInput[i];
correctAnswers=checkCorrectAnswers(answer);
for(var j:int=0; j<organelleInput.length; j++)
{
organelleInput[j].restrict="a-z";
if(correctAnswers==true)
{
F18output_txt.text="Well done!";
F18next_btn.visible=true;
checkMyWork_btn.visible==false;
}
if(correctAnswers==false)
{
F18output_txt.text="One of them seems to be wrong. Try again.";
}
}
}
function F18goToFrameNineteen(event:MouseEvent):void{
gotoAndStop(19);
}
function F18goToFrameSix(event:MouseEvent):void{
gotoAndStop(6);
}
function checkCorrectAnswers(s:String):Boolean
{
if(F18nucleolusInput_txt.text=="nucleolus"){
return true;
}
return false;
if(F18nucleusInput_txt.text=="nucleus"){
return true;
}
return false;
if((F18erInput_txt.text=="endoplasmic reticulum")||(F18erInput_txt.text=="er")){
return true;
}
return false;
if((F18golgiInput_txt.text=="golgi body")||(F18golgiInput_txt.text=="golgi apparatus")){
return true;
}
return false;
if((F18mitochondriaInput_txt.text=="mitochondria")||(F18mitochondriaInput_txt.text=="mitochondrion")){
return true;
}
return false;
if((F18lysosomeInput_txt.text=="lysosome")||(F18lysosomeInput_txt.text=="lysosomes")){
return true;
}
return false;
if(F18vacuoleInput_txt.text=="vacuole"){
return true;
}
return false;
if((F18chloroplastInput_txt.text=="chloroplast")||(F18chloroplastInput_txt.text=="chloroplasts")){
return true;
}
return false;
}

You can check Array of TextFields vs Array of Arrays:
var Correct:Array = [
["nucleolus"],
["nucleus"],
["golgi body", "golgi apparatus"],
["mitochondria", "mitochondrion"]
];
var Answers:Array = [T1, T2, T3, T4];
// Returns true if all answers are correct.
function allCorrect():Boolean
{
for (var i:int = 0; i < Answers.length; i++)
if (!oneCorrect(Answers[i], Correct[i]))
return false;
return true;
}
// Returns true if answer is on the Array of correct answers.
function oneCorrect(source:TextField, target:Array):Boolean
{
return target.indexOf(source.text.toLowerCase()) > -1;
}

Related

An empty array shows up non-empty when returned from function [duplicate]

This question already has answers here:
How do I test for an empty JavaScript object?
(48 answers)
Closed 5 years ago.
What is the fastest way to check if an object is empty or not?
Is there a faster and better way than this:
function count_obj(obj){
var i = 0;
for(var key in obj){
++i;
}
return i;
}
For ECMAScript5 (not supported in all browsers yet though), you can use:
Object.keys(obj).length === 0
I'm assuming that by empty you mean "has no properties of its own".
// Speed up calls to hasOwnProperty
var hasOwnProperty = Object.prototype.hasOwnProperty;
function isEmpty(obj) {
// null and undefined are "empty"
if (obj == null) return true;
// Assume if it has a length property with a non-zero value
// that that property is correct.
if (obj.length > 0) return false;
if (obj.length === 0) return true;
// If it isn't an object at this point
// it is empty, but it can't be anything *but* empty
// Is it empty? Depends on your application.
if (typeof obj !== "object") return true;
// Otherwise, does it have any properties of its own?
// Note that this doesn't handle
// toString and valueOf enumeration bugs in IE < 9
for (var key in obj) {
if (hasOwnProperty.call(obj, key)) return false;
}
return true;
}
Examples:
isEmpty(""), // true
isEmpty(33), // true (arguably could be a TypeError)
isEmpty([]), // true
isEmpty({}), // true
isEmpty({length: 0, custom_property: []}), // true
isEmpty("Hello"), // false
isEmpty([1,2,3]), // false
isEmpty({test: 1}), // false
isEmpty({length: 3, custom_property: [1,2,3]}) // false
If you only need to handle ECMAScript5 browsers, you can use Object.getOwnPropertyNames instead of the hasOwnProperty loop:
if (Object.getOwnPropertyNames(obj).length > 0) return false;
This will ensure that even if the object only has non-enumerable properties isEmpty will still give you the correct results.
EDIT: Note that you should probably use ES5 solution instead of this since ES5 support is widespread these days. It still works for jQuery though.
Easy and cross-browser way is by using jQuery.isEmptyObject:
if ($.isEmptyObject(obj))
{
// do something
}
More: http://api.jquery.com/jQuery.isEmptyObject/
You need jquery though.
Underscore and lodash each have a convenient isEmpty() function, if you don't mind adding an extra library.
_.isEmpty({});
Lets put this baby to bed; tested under Node, Chrome, Firefox and IE 9, it becomes evident that for most use cases:
(for...in...) is the fastest option to use!
Object.keys(obj).length is 10 times slower for empty objects
JSON.stringify(obj).length is always the slowest (not surprising)
Object.getOwnPropertyNames(obj).length takes longer than Object.keys(obj).length can be much longer on some systems.
Bottom line performance wise, use:
function isEmpty(obj) {
for (var x in obj) { return false; }
return true;
}
or
function isEmpty(obj) {
for (var x in obj) { if (obj.hasOwnProperty(x)) return false; }
return true;
}
Results under Node:
first result: return (Object.keys(obj).length === 0)
second result: for (var x in obj) { return false; }...
third result: for (var x in obj) { if (obj.hasOwnProperty(x)) return false; }...
forth result: return ('{}' === JSON.stringify(obj))
Testing for Object with 0 keys
0.00018
0.000015
0.000015
0.000324
Testing for Object with 1 keys
0.000346
0.000458
0.000577
0.000657
Testing for Object with 2 keys
0.000375
0.00046
0.000565
0.000773
Testing for Object with 3 keys
0.000406
0.000476
0.000577
0.000904
Testing for Object with 4 keys
0.000435
0.000487
0.000589
0.001031
Testing for Object with 5 keys
0.000465
0.000501
0.000604
0.001148
Testing for Object with 6 keys
0.000492
0.000511
0.000618
0.001269
Testing for Object with 7 keys
0.000528
0.000527
0.000637
0.00138
Testing for Object with 8 keys
0.000565
0.000538
0.000647
0.00159
Testing for Object with 100 keys
0.003718
0.00243
0.002535
0.01381
Testing for Object with 1000 keys
0.0337
0.0193
0.0194
0.1337
Note that if your typical use case tests a non empty object with few keys, and rarely do you get to test empty objects or objects with 10 or more keys, consider the Object.keys(obj).length option. - otherwise go with the more generic (for... in...) implementation.
Note that Firefox seem to have a faster support for Object.keys(obj).length and Object.getOwnPropertyNames(obj).length, making it a better choice for any non empty Object, but still when it comes to empty objects, the (for...in...) is simply 10 times faster.
My 2 cents is that Object.keys(obj).length is a poor idea since it creates an object of keys just to count how many keys are inside, than destroys it! In order to create that object he needs to loop overt the keys... so why use it and not the (for... in...) option :)
var a = {};
function timeit(func,count) {
if (!count) count = 100000;
var start = Date.now();
for (i=0;i<count;i++) func();
var end = Date.now();
var duration = end - start;
console.log(duration/count)
}
function isEmpty1() {
return (Object.keys(a).length === 0)
}
function isEmpty2() {
for (x in a) { return false; }
return true;
}
function isEmpty3() {
for (x in a) { if (a.hasOwnProperty(x)) return false; }
return true;
}
function isEmpty4() {
return ('{}' === JSON.stringify(a))
}
for (var j=0;j<10;j++) {
a = {}
for (var i=0;i<j;i++) a[i] = i;
console.log('Testing for Object with '+Object.keys(a).length+' keys')
timeit(isEmpty1);
timeit(isEmpty2);
timeit(isEmpty3);
timeit(isEmpty4);
}
a = {}
for (var i=0;i<100;i++) a[i] = i;
console.log('Testing for Object with '+Object.keys(a).length+' keys')
timeit(isEmpty1);
timeit(isEmpty2);
timeit(isEmpty3);
timeit(isEmpty4, 10000);
a = {}
for (var i=0;i<1000;i++) a[i] = i;
console.log('Testing for Object with '+Object.keys(a).length+' keys')
timeit(isEmpty1,10000);
timeit(isEmpty2,10000);
timeit(isEmpty3,10000);
timeit(isEmpty4,10000);
Elegant way - use keys
var myEmptyObj = {};
var myFullObj = {"key":"value"};
console.log(Object.keys(myEmptyObj).length); //0
console.log(Object.keys(myFullObj).length); //1
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
function isEmpty( o ) {
for ( var p in o ) {
if ( o.hasOwnProperty( p ) ) { return false; }
}
return true;
}
var x= {}
var y= {x:'hi'}
console.log(Object.keys(x).length===0)
console.log(Object.keys(y).length===0)
true
false
http://jsfiddle.net/j7ona6hz/1/
Surprised to see so many weak answers on such a basic JS question... The top answer is no good too for these reasons:
it generates a global variable
returns true on undefined
uses for...in which is extremely slow by itself
function inside for...in is useless - return false without hasOwnProperty magic will work fine
In fact there's a simpler solution:
function isEmpty(value) {
return Boolean(value && typeof value === 'object') && !Object.keys(value).length;
}
https://lodash.com/docs#isEmpty comes in pretty handy:
_.isEmpty({}) // true
_.isEmpty() // true
_.isEmpty(null) // true
_.isEmpty("") // true
How bad is this?
function(obj){
for(var key in obj){
return false; // not empty
}
return true; // empty
}
No need for a library.
function(){ //must be within a function
var obj = {}; //the object to test
for(var isNotEmpty in obj) //will loop through once if there is a property of some sort, then
return alert('not empty')//what ever you are trying to do once
return alert('empty'); //nope obj was empty do this instead;
}
It might be a bit hacky. You can try this.
if (JSON.stringify(data).length === 2) {
// Do something
}
Not sure if there is any disadvantage of this method.
fast onliner for 'dictionary'-objects:
function isEmptyDict(d){for (var k in d) return false; return true}
You can write a fallback if Array.isArray and Object.getOwnPropertyNames is not available
XX.isEmpty = function(a){
if(Array.isArray(a)){
return (a.length==0);
}
if(!a){
return true;
}
if(a instanceof Object){
if(a instanceof Date){
return false;
}
if(Object.getOwnPropertyNames(a).length == 0){
return true;
}
}
return false;
}
Imagine you have the objects below:
var obj1= {};
var obj2= {test: "test"};
Don't forget we can NOT use === sign for testing an object equality as they get inheritance, so If you using ECMA 5 and upper version of javascript, the answer is easy, you can use the function below:
function isEmpty(obj) {
//check if it's an Obj first
var isObj = obj !== null
&& typeof obj === 'object'
&& Object.prototype.toString.call(obj) === '[object Object]';
if (isObj) {
for (var o in obj) {
if (obj.hasOwnProperty(o)) {
return false;
break;
}
}
return true;
} else {
console.error("isEmpty function only accept an Object");
}
}
so the result as below:
isEmpty(obj1); //this returns true
isEmpty(obj2); //this returns false
isEmpty([]); // log in console: isEmpty function only accept an Object
funtion isEmpty(o,i)
{
for(i in o)
{
return!1
}
return!0
}
here's a good way to do it
function isEmpty(obj) {
if (Array.isArray(obj)) {
return obj.length === 0;
} else if (typeof obj === 'object') {
for (var i in obj) {
return false;
}
return true;
} else {
return !obj;
}
}
var hasOwnProperty = Object.prototype.hasOwnProperty;
function isArray(a) {
return Object.prototype.toString.call(a) === '[object Array]'
}
function isObject(a) {
return Object.prototype.toString.call(a) === '[object Object]'
}
function isEmpty(a) {
if (null == a || "" == a)return!0;
if ("number" == typeof a || "string" == typeof a)return!1;
var b = !0;
if (isArray(a)) {
if (!a.length)return!0;
for (var c = 0; c < a.length; c++)isEmpty(a[c]) || (b = !1);
return b
}
if (isObject(a)) {
for (var d in a)hasOwnProperty.call(a, d) && (isEmpty(a[d]) || (b = !1));
return b
}
return!0
}
May be you can use this decision:
var isEmpty = function(obj) {
for (var key in obj)
if(obj.hasOwnProperty(key))
return false;
return true;
}
I modified Sean Vieira's code to suit my needs. null and undefined don't count as object at all, and numbers, boolean values and empty strings return false.
'use strict';
// Speed up calls to hasOwnProperty
var hasOwnProperty = Object.prototype.hasOwnProperty;
var isObjectEmpty = function(obj) {
// null and undefined are not empty
if (obj == null) return false;
if(obj === false) return false;
if(obj === true) return false;
if(obj === "") return false;
if(typeof obj === "number") {
return false;
}
// Assume if it has a length property with a non-zero value
// that that property is correct.
if (obj.length > 0) return false;
if (obj.length === 0) return true;
// Otherwise, does it have any properties of its own?
// Note that this doesn't handle
// toString and valueOf enumeration bugs in IE < 9
for (var key in obj) {
if (hasOwnProperty.call(obj, key)) return false;
}
return true;
};
exports.isObjectEmpty = isObjectEmpty;
here my solution
function isEmpty(value) {
if(Object.prototype.toString.call(value) === '[object Array]') {
return value.length == 0;
} else if(value != null && typeof value === 'object') {
return Object.getOwnPropertyNames(value).length == 0;
} else {
return !(value || (value === 0));
}
}
Chears
if (Object.getOwnPropertyNames(obj1).length > 0)
{
alert('obj1 is empty!');
}

Actions Script 3.0 if else statements

need to do several things by it's click event. I'm a beginner to this, so is there any other way to write this code? by clicking this button, it goes to next frame and according to statement several buttons will be visible or not. I wrote the code this way and it says there are syntax error, but I couldn't find any. Hope you guys understand this and will help me. :) Thank you!
review_btn.addEventListener(MouseEvent.CLICK, review1)
function review1(event:MouseEvent):void{
if(rvw1 == "Correct"){
gotoAndStop(3627);
help1.visible = false
}
else{
gotoAndStop(3627);
help1.visible = true
}
}
review_btn.addEventListener(MouseEvent.CLICK, review2)
function review2(event:MouseEvent):void{
if(rvw2 == "Correct"){
gotoAndStop(3627);
help2.visible = false
}
else{
gotoAndStop(3627);
help2.visible = true
}
}
review_btn.addEventListener(MouseEvent.CLICK, review3)
function review3(event:MouseEvent):void{
if(rvw3 == "Correct"){
gotoAndStop(3627);
help3.visible = false
}
else{
gotoAndStop(3627);
help3.visible = true
}
}
review_btn.addEventListener(MouseEvent.CLICK, review4)
function review4(event:MouseEvent):void{
if(rvw4 == "Correct"){
gotoAndStop(3627);
help4.visible = false
}
else{
gotoAndStop(3627);
help4.visible = true
}
}
review_btn.addEventListener(MouseEvent.CLICK, review5)
function review5(event:MouseEvent):void{
if(rvw5 == "Correct"){
gotoAndStop(3627);
help5.visible = false
}
else{
gotoAndStop(3627);
help5.visible = true
}
}
I'll take an attempt at it. It looks like the only difference is that in each method you need to match up "helpX".visible with "rvwX" equals the string "Correct", where X is a number from 1-5. The gotoAndStop() frame is the same regardless. Also, that all five are meant to be off the same button. I'm going to take an assumption that the clips 'help' are movieclips defined on the stage else if they are from something else I would store them in an array for looping through instead of 'building' the name and finding the reference that way just for clarity.
function review(event:MouseEvent):void {
for(var counter:int = 1; counter < 6; counter++){
this["help" + counter].visible = (this["rvw" + counter] != "Correct");
}
this.gotoAndStop(3627);
}
review_btn.addEventListener(MouseEvent.CLICK, review);
I think you have to do a class with 2 fields: "help" and "rvw" (let me call it "Switcher"). Also it may contain a function of setting visibility (may, not must, this function can also be in your main class):
Switcher.as:
import flash.display.MovieClip;
public class Switcher {
private var help:MovieClip;
private var rvw:String;
public function setVisibility() {
help.visible = !(rvw == "Correct");
}
}
Then you have to make an array of Switcher's objects in your main class and to use only one "review" handler:
function review(event:MouseEvent):void {
for each(var sw:Switcher in switchersArray) {
sw.setVisibility();
}
this.gotoAndStop(3627);
}
The code from previous answer will work correctly, but IMHO, creating an Array (or Vector) of similar objects is better than doing lots of help1, help2, help3 etc variables.

Find existing bookmark folder by title?

I am trying to bring back the folder id of any bookmark folder which has a title matching a given string.
Problem is it doesn't return back folder ids when the text is the same :C
This is my code:
chrome.bookmarks.getTree(function(bookmarks)
{
search_for_url(bookmarks, "herpaderp");
});
function search_for_title(bookmarks, title)
{
for(i=0; i < bookmarks.length; i++)
{
if(bookmarks[i].url != null && bookmarks[i].title == title)
{
// Totally found a folder that matches!
return bookmarks[i].id;
}
else
{
if(bookmarks[i].children)
{
// inception recursive stuff to get into the next layer of children
return search_for_title(bookmarks[i].children, title);
}
}
}
// No results :C
return false;
}
There are two problems with your search_for_title function.
The variable i must be local. To make it a local variable, you have to use var i = 0 instead of i = 0 in the for statement.
search_for_title returns false when it can't find a bookmark that has the specified title, but you still need to look into the next item, so after recursively calling search_for_title, you return the return value only if the bookmark has been found. Otherwise, search should be continued instead of returning false.
Here's the code I tested to run correctly:
function search_for_title(bookmarks, title)
{
for(var i=0; i < bookmarks.length; i++)
{
if(bookmarks[i].url != null && bookmarks[i].title == title)
{
// Totally found a folder that matches!
return bookmarks[i].id;
}
else
{
if(bookmarks[i].children)
{
// inception recursive stuff to get into the next layer of children
var id = search_for_title(bookmarks[i].children, title);
if(id)
return id;
}
}
}
// No results :C
return false;
}

How to merge two arraycollection and without duplicates?

I want merge 2 array collection, where no duplicates are allowed,
var ac1:ArrayCollection = new ArrayCollection([ {s:"4",e:"8"}, {s:"9",e:"10"}, ]);
var ac2:ArrayCollection = new ArrayCollection([ {s:"2",e:"3"}, {s:"4",e:"8"}, {s:"9",e:"10"}, {s:"11",e:"12"}, ]);
how can I do it in efficient way
Thanks,
Errr, I'm not an actionscript guy but it's a classic problem - sort the two arrays in ascending order, then feed them into your third array, always selecting the lowest value from the two source arrays and escaping the write to the destination if what you would write is already at the end of the list - you'll end up with a sorted list of the unique values in the n input arrays
For more properties, use something like:
function equals(o1:Object, o2:Object):Boolean
{
if (o1 == o2) return true;
if (!o1 || !o2) return false;
for (var key:String in o1)
{
if (!(key in o2)) return false;
if (o1[key] != o2[key]) return false;
}
return true;
}
Perhaps this is a good starter.
function equals(o1:Object, o2:Object)
{
return (o1 && o2) && (o1 != o2) && (o1.s != o2.s) && (o1.e != o2.e);
}
function merge(a:Array, b:Array):Array
{
const source = [];
var isContained:Boolean = false;
for (var i:int; i< a.length;i++) {
isContained = false
for (var j:int; j< b.length;j++) {
if (equals(a[i], b[j])) {
isContained = true;
break;
}
}
if (!isContained) {
source.push(a[1]);
}
}
return source.concat(b);
}

Trying to create a function which extracts a URL from an array. JavaScript

So basically I would like to create a function that when alerted, returns the URL from an array (in this case the array is declared as 'websites'). The function has two parameters 'websites' and 'searchTerm'.
I'm struggling to make the function behave, so that when i type yahoo or google or bing in the searchTerm parameter for the function; I want it to return the corresponding URL.
Any help or support would be greatly appreciated.
Sorry if I have not made myself clear in my explanation, if this is the case, let me know and I will try and be clearer in my explanation.
Thanks in advance!
Try something more like:
var websites = {google: 'www.google.com', yahoo: 'www.yahoo.com'};
function filterURL(websites,searchTerm)
{
return websites[searchTerm] || 'www.defaultsearchwebstirehere.com';
}
** Update following comment **
Build up your websites object like so (where input is your array of key values seperated by pipe characters):
var websites = {};
for (var i = 0; i < input.length; i++) {
var siteToSearchTerm = input[i].split('|');
websites[siteToSearchTerm[1]] = siteToSearchTerm[0];
}
Here is how:
var websites = ["www.google.com|Google" , "www.yahoo.com|Yahoo" , "www.bing.com|Bing"];
function filterURL(websites,searchTerm)
{
for (var i = 0; i < websites.length; i++) {
if (websites[i].split('|')[1] === searchTerm) {
return websites[i].split('|')[0];
}
}
}
Working Example
You can also validate and improve function:
function filterURL(websites,searchTerm)
{
if (typeof websites != 'Array' || ! searchTerm) return false;
for (var i = 0; i < websites.length; i++) {
if (websites[i].split('|')[1] === searchTerm) {
return websites[i].split('|')[0];
}
}
return false;
}
Why not just use an object?
var websites = {
Google: 'www.google.com',
Yahoo: 'www.yahoo.com'
};
function filterURL(sites, searchTerm) {
if (sites[searchTerm]) {
return sites[searchTerm];
} else {
// What do you want to do when it can't be found?
}
}
alert(filterURL(websites, 'Google')); // alerts 'www.google.com'
You should really be using a hash-table like structure so that you don't have to search through the whole array every time. Something like this:
var websites = {
"Google": "www.google.com",
"Yahoo": "www.yahoo.com",
"Bing": "www.bing.com"
};
function filterURL(websites, searchTerm) {
if (websites[searchTerm] !== undefined)
return websites[searchTerm];
else
return null;
}
I'm not sure why you want to use an array for this, as what you're really doing fits a key-value pair better; however, here's how I'd do it:
function filterURL(websites, searchTerm) {
var i = 0,
parts;
for (i = 0; i < websites.length; i++) {
parts = websites[i].split("|");
if (parts[1].toLowerCase() === searchTerm) {
return parts[0];
}
}
}
But consider if you used a proper JavaScript Object instead:
var websites = {
Google: "www.google.com",
Yahoo: "www.yahoo.com",
Bing: "www.bing.com"
}
// Now it's much simpler:
function filterURL(websites, searchTerm) {
// key has first letter capitalized…
return websites[searchTerm.charAt(0).toUpperCase() + searchTerm.slice(1).toLowerCase()];
}