Repository | Demo

Want to have some fun with Objects?

Let's use compose library to build a mini incremental game.

model

Install and include the library.

<!-- include the library -->
<script src="https://cdn.jsdelivr.net/npm/@bblocks/compose@0.1.2/compose.umd.js"></script>
// Optionally create shortcuts in lodash style 
var _ = Object.assign(_ || {}, compose); // Now you can use it like _.mix(...)  _.clone(...)  new _.Block(...) _.block

Create a big number feature

We can improve our original example to make it more efficient.


// Display big numbers with suffixes
var bigNumber = new _.Block({
    suffixes: ["", "k", "m", "b","t"],
    toString: function (value) {
        var newValue = value;
        if (value >= 1000) {
            var suffixes = this.suffixes;
            var suffixNum = Math.floor( (""+value).length/3 );
            var shortValue = '';
            for (var precision = 2; precision >= 1; precision--) {
                shortValue = parseFloat( (suffixNum != 0 ? (value / Math.pow(1000,suffixNum) ) : value).toPrecision(precision));
                var dotLessShortValue = (shortValue + '').replace(/[^a-zA-Z 0-9]+/g,'');
                if (dotLessShortValue.length <= 2) { break; }
            }
            if (shortValue % 1 != 0)  shortNum = shortValue.toFixed(1);
            newValue = shortValue+suffixes[suffixNum];
        }
        return newValue;
    }
}).define({ // Note how it is easier to define property descriptors
    'value': {
        get: function() {
            return this._value || 0;
        },
        set: function(newValue) {
            if (newValue != this._value) {
                this.stringValue = this.toString(newValue);

                // Display if we can 
                if (this.innerHTML !== undefined) {
                    this.innerHTML = this.stringValue;
                } 
            }
            this._value = newValue;
        }
    }
});

// Check bigNumber
console.log('100000 = ' + bigNumber.toString(100000)); // 1000000 = 1m 

Define incremental features.

// Define a new feature to increment a number
var increment = new _.Block({
    amount: 1, // Incremental step
    increment: function(amount) {
        this.value = (this.value || 0) + (amount || this.amount || 1);
    }
});

// Check increment
{
    let obj = increment.clone(); // Create a new instance 
    obj.increment(2);
    console.log('Increment 0 + 2 = ', obj.value); // Increment 0 + 2 = 2
}

Create a powerful button that can display bigNumber and increment

// Create a dom element and add more features to it
function createComponent(name, feature1, feature2, feature3) {
    var el = document.createElement(name);

    // Add our "Block" features but override clone method since we can't inherit directly from DOM elements
    arguments[0] = _.mix(el, _.block, {
        clone: function() {
            Array.prototype.unshift.call(arguments, createComponent(this.tagName, this));
            return _.mix.apply(null, arguments);
        }
    });
    var featuredElement = _.mix.apply(null, arguments); // Using composition to add features to the DOM element
    return featuredElement;
}

// Increment on click
let btn = createComponent('button', bigNumber, increment); // Note how easy we can create more powerful DOM elements
btn.addEventListener('click', function () {
    this.increment();
});
btn.increment(); // initial value

// Add to the DOM
var container = document.querySelector('#example-1-') || document.body;
container.appendChild(btn);

Example 1:

Now we can clone our button to create more powerful buttons :)

var biggerBtn = btn.clone({amount: 1000}); 
biggerBtn.addEventListener('click', function () {
    this.increment();
});
biggerBtn.increment();
var container = document.querySelector('#example-2-') || document.body;
container.appendChild(biggerBtn);

Example 2:

Hope you enjoyed it!