A highly-configurable, highly-capable, superformant open source JavaScript library.

By Jacob Heater

Fork Watch Star Follow @jacobheater Code


Feature Highlights

pro.$class()

            
            /*Create a Person prototype. The $class() method decorates the prototype with some
            characteristics that make it easy to identify Pro.js classes*/
            var Person = pro.$class('Person', function(name, age, sex) {
                this.name = name || "";
                this.age = age || 0;
                this.sex = sex || "";
            });
            var p = new Person("John Doe", 100, "Male");
            
            
Result
            
            
            

Prototypal Inheritance  Got You Down?

Is inheritance a headache for you in JavaScript? Do you hate prototypal inheritance? Do you just find that you don't get prototypes? Don't worry about it! The Pro.js $class() decorator makes it super easy to achieve inheritance in your code, and you don't have to sweat the prototypes! Let Pro.js do that!

            
            /*Create a Person prototype. The $class() method decorates the prototype with some
            characteristics that make it easy to identify Pro.js classes*/
            var Person = pro.$class('Person', function(name, age, sex) {
                this.name = name || "";
                this.age = age || 0;
                this.sex = sex || "";
            });
            /*Now that we have our Person class defined, let's define a child class that inherits from the
            Person super class*/
            var Man = pro.$class('Man << Person', function(name, age) {
                //Call to the base constructor
                this.initializeBase(name, age, 'Male');
            }, Person);
            var m = new Man("John Doe", 100);
            /*Define a Woman class*/
            var Woman = pro.$class('Woman << Person', function(name, age) {
                //Call to the base constructor
                this.initializeBase(name, age, 'Female');
            }, Person);
            var w = new Woman("Jane Doe", 100);
            
            
Result
            
            
            

The .$class() decorator has been isolated from the core library as it's own module. This is useful in the event that you do not want to import the whole library, but you still desire the .$class() decorator for easy prototype creation.


Type Checking with Pro.js

Stop wasting precious time writing repetetive code! Let Pro.js handle type constraints, so you don't have to! Pro.js includes several type constraint methods to make your life easier to handle type checking with a proven result that is used in the Pro.js codebase.


            
            //Numbers
            var n = 100;
            if (pro.isNumber(n)) {
                console.log("It's a number!");
            } else {
                console.log("It's not a number!");
            }
            //Functions
            var action = () => console.log("Cool beans!");
            if (pro.isFunction(action)) {
                action();
            } else {
                console.log("No can do!");
            }
            //Arrays
            var arr = { length: 0 }; //Going to duck type this sucka!
            if (pro.isArray(arr)) {
                console.log(JSON.stringify(arr));
            } else {
                console.log("Not an array!");
            }
            //Too many more examples to count!
            
            
Result
            
            


The pro.collections Namespace
            
            //Declare an array.
            var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
            //Have the factory create an instance of the pro.collections.enumerable class.
            var enumerable = pro.collections.asEnumerable(array);
            //Now let's have some fun!
            var greaterThan5 = enumerable.where(n => n > 5).toArray(); //[6, 7, 8, 9, 10]
            var lessThan5 = enumerable.where(n => n < 5).toArray(); //[1, 2, 3, 4];
            var list = enumerable.toList(); //instance of pro.collections.list
            list.add(11);
            list.add(12);
            list.add(13);
            list.add(14);
            list.add(15);
            var greaterThan10 = list.where(n =>  n > 10).toArray(); //[11, 12, 13, 14, 15]
            //Examples without the .asEnumerable() factory
            var numbers = new pro.collections.list();
            //Add a range of numbers to the list
            numbers.addRange([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
            
            
Result

The collections namespace contains several wrapper classes that utilize native JavaScript array APIs, but expose methods that are uniform across the classes. This makes it easier to work with Pro.js stacks, queues, lists, dictionaries, and the enumerable class due the approachable and easy-to-understand API.

Because all of the wrapper classes in the collections namespace are prototypes, this makes it easy to extend them with child classes, or prototype extension methods. In the same way that the .$class() decorator above shows inheritance using the Pro.js API, the .$class() decorator was used to extend the pro.collections.enumerable super class with child classes like the pro.collections.list, or pro.collections.dictionary classes.



pro.observe()

The problem with the Object.observe() method is that it isn't implemented exactly the same way across browsers, nor is it standardized. This makes is hard to implement observers in JavaScript. Pro.js has an independent observer that was built without dependencies on any native APIs. This means that you can predict how the observer is going to behave across browsers. The functionality behaves very much in the same way as the native Object.observe API. For optimal performance, the pro.observe() method uses the native .requestAnimationFrame() method where available. When it's not available, it uses recursive .setTimeout() calls to achieve asynchronous observing of objects.

   
            
            //When DOM is ready for manipulation, handle...
            pro.document.ready(function() {
                //Find the target text box for observing.
                var target = pro.document.query('#observeTb').first();
                //The placeholder for the textbox text.
                var span = pro.document.query('#observeOutput');
                //Set up the observer event listener
                pro.observe(target, function (c) {
                    //This will get fired on target state change.
                    console.log(c); //c is Array of pro.Observer.ObjectChange
                    for (var i = 0; i < c.length; i++) {
                        var change = c[i];
                        //Look through changes of object for property value
                        if (change.propertyName === 'value') {
                            //Set the value to the currentValue
                            span.text(change.currentValue);
                        }
                    }
                });
            });