Array

JavaScript's native array and collection features are limited and not very obvious, so Fit.UI tries to enhance and uniform this area.
Add, Insert, Remove, and Clear
var users = [];

var jimmy = { Name: "Jimmy", Email: "jimmy@server.com"};
var hans = { Name: "Hans", Email: "hans@server.com"};
var michael = { Name: "Michael", Email: "michael@server.com"};

// Add data
Fit.Array.Add(users, jimmy);
Fit.Array.Add(users, hans);
Fit.Array.Add(users, michael);

// Insert item on index 1
Fit.Array.Insert(users, 1, { Name: "Ole", "ole@server.com" });

// Array now contains: 0 = Jimmy, 1 = Ole, 2 = Hans, 3 = Michael

// Remove data
Fit.Array.RemoveAt(users, 2); // Remove by index (Hans)
Fit.Array.Remove(users, jimmy); // Remove by object reference (Jimmy)

// Get item (standard JavaScript)
var user = users[0];

// Remove all items in array
Fit.Array.Clear(users);


ForEach
Developers must be careful when using ordinary for and while loops in JavaScript to register events/callbacks and when postponing/scheduling code execution using setTimeout or setInterval due to the fact that callbacks used within these kinds of loops share the same execution context. Consider the example below which is not how it should be done.

Bad practice - do not use this approach
var users = [ "Hans", "Ole", "Jimmy", "Michael" ];

for (var i = 0 ; i < users.length ; i++)
{
    setTimeout(function()
    {
        console.log(users[i]);
    }, 500);
}


The code above does not output "Hans", "Ole", "Jimmy", and "Michael" to the browser console as one might expect. The i counter variable increments to 4 before the condition "i < users.length" is evaluated, and since all callbacks use the same i variable, the code being executed is actually "console.log(users[4])" which outputs undefined 4 times.
To use native for and while loops the developer must understand the concept of closures to avoid unexpected behaviour.
Most JavaScript based frameworks implement an iterator mechanism that takes care of the problem described above and so does Fit.UI. The example below will work exactly as expected.

Good practice
var users = [ "Hans", "Ole", "Jimmy", "Michael" ];

Fit.Array.ForEach(users, function(user)
{
    setTimeout(function()
    {
        console.log(user);
    }, 500);
});


The code above outputs each user to the console as expected.
The ForEach function can loop through any type of collection including instances of NodeList, HTMLCollection, and even object arrays (object properties) like shown below.

// Iterating NodeList

Fit.Array.ForEach(document.querySelector("div#PictureBox img"), function(image)
{
    image.style.border = "2px solid green";
});

// Iterating object array

var objArr = {};
objArr["jimmy"] = { Name: "James Thomson", Gender: "male", Age: 32 };
objArr["hans"] = { Name: "Hans Törp", Gender: "male", Age: 43 };
objArr["ilda"] = { Name: "Ilda Longstum", Gender: "female", Age: 38 };

Fit.Array.ForEach(objArr, function(key)
{
    var user = objArr[key];
    console.log(user.Name + " is a " + user.Age + " years old " + user.Gender);
});


With native loops we can skip items using continue and stop the loop using break. The same is possible with ForEach but the approach is a bit different as shown below.

var count = 0;

Fit.Array.ForEach(users, function(key)
{
    var user = users[key];

    if (user.Age < 20)
        return; // Skip users under the age of 20

    console.log(user.Name + " is a " + user.Age + " years old " + user.Gender);

    count++;

    if (count === 20)
        return false; // Break (stop) loop when 20 users have been processed
});


Simply use return within ForEach to skip an item, and return false to break the loop.

There is also a solution to looping through a hierarchical structure - we use the functions Recurse and CustomRecurse like shown below. The code below is based on this example data.

// Recursively iterate through array containing objects
// with a Title property and a Children property
// pointing to an array with nested children.

Fit.Array.Recurse(arr, "Children", function(item)
{
    console.log(item.Title);
});

// Children can also be retrieved from a function,
// in this case GetChildren().

Fit.Array.Recurse(arr, "GetChildren", function(item)
{
    console.log(item.Title);
});

// We can also use CustomRecurse which is useful when
// iterating through a hierarchy of different types of objects.

Fit.Array.CustomRecurse(arr, function(item)
{
    console.log(item.Title);

    if (item.Type === "Company")
        return item.Products;
    else if (item.Type === "Products")
        return item.Models;

    // Return Null when no more children are available
    return null;
});


Contains, GetIndex, and Count
To determine whether an array contains a given element, or the position within the element, simply use Contains and GetIndex. The Count function is useful to get the item count for object arrays which does not expose a length property like ordinary arrays.

// Using Contains and GetIndex

var arr = [ "jimmy@server.com", "hans.torp@server.com" ];

Fit.Array.Contains(arr, "test"); // Returns false
Fit.Array.Contains(arr, "hans.torp@server.com"); // Returns true

Fit.Array.GetIndex(arr, "test"); // Returns -1 (not found)
Fit.Array.GetIndex(arr, "hans.torp@server.com"); // Returns index 1

// Get item count from object array

var objArr = {};
objArr["jimmy"] = "jimmy@server.com";
objArr["hans"] = "hans.torp@server.com";
Fit.Array.Count(objArr); // Returns 2


Copy and Merge
Creating a shallow copy of an array, or merging two arrays, is equally simple.

var developers = [ "jimmy@server.com", "hans.torp@server.com" ];
var consultants = [ "martin@server.com", "anders@server.com" ];

// Create one array containing both developers and consultants
var allUsers = Fit.Array.Merge(developers, consultants);

// Create a copy of an array
var copy = Fit.Array.Copy(allUsers);


Notice that Copy only creates a shallow copy, and only supports ordinary arrays. To copy object arrays or to create deep copies, use Fit.Core.Clone instead.

ToArray
JavaScript has different collection types such as NodeList and HTMLCollection. Some functions in Fit.UI might only accept an instance of Array, in which case being able to turn other collection types into ordinary arrays come in handy.

var images = document.querySelectorAll("div.PictureBox img"); // Returns NodeList
var imagesArr = Fit.Array.ToArray(images);

// Because we were able to turn the NodeList into an ordinary array,
// we can now use all the array functions on the image collection:

Fit.Array.Add(imagesArr, document.querySelector("img#Uploaded"));
Fit.Array.Contains(imagesArr, document.querySelector("img#preview"));
Fit.Array.Count(imagesArr);
Fit.Array.RemoveAt(imagesArr, 0);
Fit.UI is open source (LGPL) - download or fork it on GitHub - website powered by Sitemagic CMS