Feathersui AS3 unshift new items if they don't exist in_arry - actionscript-3

I have a feathersui list component and I was wondering if there is a way to unshift a new item to the beginning of the list IF it doesn't current exist in the list. What I would like to do is something like the below (most is already done except the 'if it doesn't exist part):
for(var i:int = 0; i < resultsArray.length; i++)
{
if(resultsArray[i].notification_id DOES NOT EXIST IN itemListArray)
{
this.itemListArray.unshift({notificationID: resultsArray[i].notification_id,
notificationText: resultsArray[i].message,
notificationType: resultsArray[i].notification_type,
notificationDest: resultsArray[i].destination,
notificationDestID: resultsArray[i].destination_id,
dateAdded: resultsArray[i].date_added});
}
}
I know PHP has in_array so hoping someone knows an AS3 equivalent.
Thanks

Define a dictionary before the loop to get all the notificationID which itemListArray contains.
Array has a indexOf function, you can search item by that function. http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Array.html#indexOf()
In your case, the array isn't directly contains the notification_id, so it won't work
var dict:Dictionary = new Dictionary();
for each (var obj:Object in itemListArray) {
dict[obj.notification_id] = true;
}
for(var i:int = 0; i < resultsArray.length; i++)
{
if(!dict[resultsArray[i].notification_id])
{
dict[resultsArray[i].notification_id] = true;
this.itemListArray.unshift({notificationID: resultsArray[i].notification_id}, notificationText: resultsArray[i].message,
notificationType: resultsArray[i].notification_type,
notificationDest: resultsArray[i].destination,
notificationDestID: resultsArray[i].destination_id,
dateAdded: resultsArray[i].date_added}););
}
}

Look at indexOf -> docs
it will return the position of the item, if it doesnt exist it will return -1
if(itemListArray.indexOf(resultsArray[i].notification_id) == -1){
// item i doesnt exist
}

Related

How to compare properties of objects inside a vector?

I have a couple of display objects moving around the screen, the all belong to the same Vector.
I would like to create a function that lets me pick an object with the lowest x value at the moment the function is called.
This is quite easy and if you're into programming, you should be able to do it yourself, but if you're a beginner, I'll give you some code:
var vec:Vector.<DisplayObject> = new Vector.<DisplayObject>();
function getLowestXObject():DisplayObject
{
var minX:DisplayObject = vec[0];
for(var i:int = 1; i < vec.length; i++)
{
if(minX.x > vec[i].x)
{
minX = vec[i];
}
}
return minX;
}

How i set index of an item in combo box in flex?

I want to set the items order that are in an array Collection and bind with a combo-box.
here is my code
[Bindable]private var langList:ArrayCollection = new ArrayCollection([{label:"Englis"},{label:"Urdu"},{label:"Arabic"},{label:"Spanish"}]);
protected function cbm_creationCompleteHandler(event:FlexEvent):void
{
for(var i:int =0; i< langList.length; i++)
{
if(langList[i].label == 'Urdu')
{
cbm.setChildIndex(cbm.getChildAt(i), 0);
break;
}
}
}
<s:ComboBox id="cbm" x="258" y="113" dataProvider="{langList}" creationComplete="cbm_creationCompleteHandler(event)"/>
when i try to run it the following exception throw by the compiler
RangeError: Error #2006: The supplied index is out of bounds.
Be careful, ComboBox::getChildAt won't return the list item, you shouldn't access the children of a Flex a component, this is a skin matter.
If you want to change the elements' order you must do it in the dataProvider, this is a data matter.
for(var i:int =0; i< langList.length; i++)
{
var item:Object = langList[i];
if(item.label == 'Urdu')
{
langList.removeItemAt(i);
langList.addItemAt(item, 0);
break;
}
}
Since your langList is Bindable, the combobox will be automatically updated.

AS3 Remove element from array (of objects) generically

Is there a way to generically remove an object from an array?
(maybe not using array.filter or creating a new array)
Example:
var arr:Array= new Array();
//create dummy objs
for (var i:uint=0; i < 10; i++){
var someObject:SomeClassObject = new SomeClassObject();
someObject.Name ="Amit"+ i;
someObject.Site="http://www.mysite.com/"+i;
//...many more props
arr.push(someObject);
}
//
removeElement("Amit4",arr);
removeElement("Amit8",arr);
//...so on so forth
Currently im using array.splice() to remove object
for (var i:Number=0; i < arr.length; i++)
{
if (arr[i].Name == element)
{
arr.splice(i, 1);
}
}
I want to write removeElement in such a way that i can use it for different
types of objects.
currently removeElement becomes dependant on implmentation..
Suppose if i want to remove a file from array of files given file name..i wud have to
again write "removeElement" by changing criteria.
Also may be i can vary the criteria varing criteria?
example :
arr= removeElement("Site","http://www.mysite.com/6",arr)
will remove object from arr whose "Site" property is equal to "http://www.mysite.com/6"
(using above example)
ie. removeElement(criteria:object,criteria_value(s):object,arr)
Thanks All.
Use
if(array.indexOf(obj) != -1)
array.splice(array.indexOf(obj),1);
I think the most flexible approach is the one followed by Array::filter. It's up to the caller to determine whether an item should be filtered out of the list or not, through a function callback.
Now, if you want to do it in place, you could write a simple function like this:
function remove(list:Array,callback:Function):Array {
for(var i:int = list.length - 1; i >= 0; i--) {
if(!callback(list[i])) {
list.splice(i,1);
}
}
return list;
}
This returns the list, as it could be convenient if you wanted to chain calls, but it acts on the array you passed instead of creating a new one.
Also note that it loops backwards. Otherwise, splice will get you bogus results.
You could use it like this:
var arr:Array = [1,2,9,10,455];
trace(arr);
function removeCallback(item:Number):Boolean {
return item < 10;
}
remove(arr,removeCallback);
trace(arr);
This way you are not restricted to equality (or inequality). The caller determines if the item should be kept or removed, by returning true or false respectively (to match filter). So, it's pretty much like filter, except it works in-place. If you want, you could also keep the same interface for the callback (passing the index of the item and a reference to the original array) to make it more coherent.
By the way, you can use strings as indices for an array, and then you can safely use the 'delete' keyword to delete an object from inside the "middle" (there's actually no "middle" in this situation :) of the array.
e.g.:
var arr:Array = new Array();
arr['o1'] = new Object();
arr['o1'].someproperty = true;
arr['o2'] = new Object();
arr['o2'].someproperty = true;
arr['o3'] = new Object();
arr['o3'].someproperty = true;
trace (arr['o2'].someproperty);
//Returns 'true'
trace (arr['o2']);
//Returns '[object Object]'
delete arr['o2'];
trace (arr['o2']);
//Returns 'undefined'
trace (arr['o2'].someproperty);
//Returns 'TypeError: Error #1010: A term is undefined and has no properties.'
The disadvantage is you won't be able to know the length of the array (arr.length will return 0), but you can of-course track it yourself...
Here is a generic function which will do what you want:
public static function removeItem(array: Array, propertyName: String, value: String): Array
{
var newArray: Array = [];
for (var index: int = 0; index < array.length; index++) {
var item: Object = array[index];
if (item && item.hasOwnProperty(propertyName)) {
if (item[propertyName] != value)
newArray.push(item);
}
}
return newArray;
}

ActionScript - Retrieving Index Of Specific Filter

i have a few filters on a sprite. on mouse over i would like to access one of the filters in the filters array, but i'm having a bit of trouble trying to accomplish this.
mySprite.filters = [new DropShadowFilter(), new GlowFilter(), new BlurFilter()];
mySprite.addEventListener(MouseEvent.MOUSE_OVER, mouseOverEventHandler);
function mouseOverEventHandler(evt:MouseEvent)
{
//obtain indexOf the GlowFilter
trace(evt.currentTarget.filters[evt.currentTarget.filters.indexOf([Object GlowFilter])]));
}
the above code doesn't work. what's the proper way to get the index of a specific filter in a filters array?
If I understand correctly, you're essentially trying to do this:
var index:int = evt.currentTarget.filters.indexOf([Object GlowFilter]);
The bracketed part is not valid Actionscript it shouldn't even compile. What you need to do is to iterate over the filters and test them yourself since there's no way to search for a specific class with indexOf.
Try this instead:
function mouseOverEventHandler(evt:MouseEvent) {
var glowFilter:GlowFilter;
for (var i:int = 0; i < evt.target.filters.length; i++) {
if (evt.target.filters[i] is GlowFilter) {
glowFilter = evt.target.filters[i];
break;
}
}
}
Also, if you're going to fiddle with the filters in the array Flash won't accept in-place modifications, so you need to re-set the array once you've changed it:
function mouseOverEventHandler(evt:MouseEvent) {
var glowFilter:GlowFilter;
for (var i:int = 0; i < evt.target.filters.length; i++) {
if (evt.target.filters[i] is GlowFilter) {
glowFilter = evt.target.filters[i];
break;
}
}
if (!glowFilter) return;
glowFilter.blurX = 10;
var filters:Array = evt.target.filters;
filters[i] = glowFilter;
evt.target.filters = filters;
}

AS3 - Is it possible to search an Array by Object properties?

Would it be possible to use Array.indexOf() to search through an Array by the properties of the Objects within the array:
var myArray:Array = new Array();
var myMovieClip = new MovieClip();
myMovieClip.name = "foo";
myArray.push(myMovieClip);
myArray.indexOf(MovieClip.name == "foo"); //0
OR
myArray.indexOf(myMovieClip.name == "foo"); //0
Both indexOf() above do not work, is there away to achieve this with the correct syntax?
Look into Array's filter method (newly available for AS3). You can write a filter method that returns all objects that will meet your criteria (in your case, a movieclip with a certain name)
index of will search for an entry ... MovieClip.name == "foo" should throw a compiler error, since MovieClip does not have a property "name" ... myMovieClip.name == "foo" will be true, and then you will get the index of true, if it is in the array at all ...
if you really need the index, you will need to iterate over the array ... by key ... or in an incremental loop, if the array is numeric and dense ...
if the array is associative (string keys used) you imperatively need to use for-in loops, since filter and related functions will only cover numeric indices ...
in a numeric array, i'd suggest one of the following two approaches:
//this will return an array of all indices
myArray.map(function (val:*,index:int,...rest):int { return (val.name == "foo") ? index : -1 }).filter(function (val:int,...rest):Boolean { return val != -1 });
//here a more reusable utility function ... you may want to put it to some better place ... just as an example ...
package {
public class ArrayUtils {
public static function indexOf(source:Array, filter:Function, startPos:int = 0):int {
var len:int = source.length;
for (var i:int = startPos; i < len; i++)
if (filter(source[i],i,source)) return i;
return -1;
}
}
}
//and now in your code:
var i:int = ArrayUtils.indexOf(myArray, function (val:*,...rest):Boolean { return val.name == "foo" });
hope that helped ... ;)
greetz
back2dos
Though back2dos' method is cool, I think beginners might find it overly-complicated, so for the sake of them here is a simpler method, that may be easier to use, though won't be as versatile for any situation as back2dos' method.
var myArray:Array = new Array();
var myMovieClip1 = new MovieClip();
var myMovieClip2 = new MovieClip();
myMovieClip1.name = "foo";
myMovieClip2.name = "bar";
myArray.push(myMovieClip1);
myArray.push(myMovieClip2);
function getIndexByName(array:Array, search:String):int {
// returns the index of an array where it finds an object with the given search value for it's name property (movieclips, sprites, or custom objects)
for (var i:int = 0; i < array.length; i++) {
if (array[i].name == search) {
return i;
}
}
return -1;
}
trace("bar index = "+getIndexByName(myArray, "bar"));
trace("foo index = "+getIndexByName(myArray, "foo"));
myMovieClip.name == "foo";
^== if you want to assign a variable, use
myMovieClip.name = "foo";
Here is what I did. Change the function name if you want... this is all just for the sake of explanation.
getObjectFromArrayByProperty(arrayToSearch, 'oBjectProperty', 'value');
function getObjectFromArrayByPoperty(array:Array, _property, search:String):Object{
for (var i:int = 0; i < array.length; i++) {
if (array[i][_property] == search) {
return array[i];
}
}
return null;
}
This returns the object instead of just an index. If a match is not found, the function returns null.