2
\$\begingroup\$

This question is a follow-up question to this one.

I wrote a small JavaScript library for material design toasts (notifications). I'd like to know what are my mistakes and how can I correct them? Code works correctly and was linted with jshint but I'd like to get notes on readability and performance.

Here are the GitHub repo and demo.

;(function (namespace) {

var localToastConfig = {
    'duration': 5000,
    'style': {}
};
var previousToast;

function show(toastConfig) {

    // hide previousToast if it exists
    if (previousToast) hideToast(previousToast);

    // create config object for currentToast and delete toastConfig
    var currentToastConfig = cloneObject(localToastConfig);
    overrideObjectProperties(currentToastConfig, toastConfig);
    toastConfig = null;

    // create currentToast
    var currentToast = createToastAndInsertToastMessage(currentToastConfig);

    // insert action-btn if it exists
    if (currentToastConfig.actionInnerText && currentToastConfig.actionCallback) {
        insertToastButton(currentToastConfig, currentToast);
    }

    // override current toast style
    overrideObjectProperties(currentToast.style, currentToastConfig.style);

    // insert into body, choose height depending on line number, animate
    document.body.appendChild(currentToast);

    var toastComputedStyles = window.getComputedStyle(currentToast);
    if (toastComputedStyles.height === toastComputedStyles.lineHeight) {
        currentToast.classList.add('singleline');
    } else {
        currentToast.classList.add('multiline');
    }

    currentToast.classList.add('fade-in');

    // set timeout to hide toast
    setTimeout(function () {
        hideToast(currentToast);
    }, currentToastConfig.duration);

    // reference for hide toast when showing other one
    previousToast = currentToast;

}

// animate toast and then invoke deleteToast function
function hideToast(toast) {
    if ( !toast ) return;
    toast.addEventListener('webkitAnimationEnd', function () {
        deleteToast(toast);
    });
    toast.addEventListener('animationend', function () {
        deleteToast(toast);
    });
    toast.classList.add('fade-out');
}

// delete toast from dom
function deleteToast(toast) {
    if ( !toast ) return;
    toast.parentNode.removeChild(toast);
    toast = null;
}

// create new toast, insert message and return toast
function createToastAndInsertToastMessage(currentToastConfig) {
    var currentToast = document.createElement('div');
    currentToast.className = 'madtaras-toast';
    currentToast.insertAdjacentHTML('afterbegin',
      '<span class="madtaras-toast_text">' + currentToastConfig.innerText + '</span>');
    return currentToast;
}

// insert action button and add event listener to it
function insertToastButton(currentToastConfig, currentToast) {
    currentToast.insertAdjacentHTML('beforeend',
      '<span class="madtaras-toast_action-btn">' +
      currentToastConfig.actionInnerText + '</span>');
    currentToast.querySelector('.madtaras-toast_action-btn').
      addEventListener('click', function () {
          deleteToast(currentToast);
          currentToastConfig.actionCallback();
      });
}

// function for objects cloning
function cloneObject(objectToClone) {
    return JSON.parse(JSON.stringify(objectToClone));
}

// function to change localToastConfig
function changeConfig(toastConfig) {
    overrideObjectProperties(localToastConfig, toastConfig);
}

// function to merge toastConfig objects.
function overrideObjectProperties(theTarget, theSource) {

    // overriding toast's style properties
    if ( theSource.hasOwnProperty('style') ) {
        for (var styleProperty in theSource.style) {
            if ( theSource.style.hasOwnProperty(styleProperty) ) {
                theTarget.style[styleProperty] = theSource.style[styleProperty];
            }
        }
    }

    // overriding other toast's properties
    for (var property in theSource) {
        if ( theSource.hasOwnProperty(property) && property !== 'style' ) {
            theTarget[property] = theSource[property];
        }
    }
}

namespace.show = show;
namespace.changeConfig = changeConfig;

})(this.madtarasToast = this.madtarasToast || {});
\$\endgroup\$
  • 1
    \$\begingroup\$ Is this a follow-up question to this one? If so, please indicate it in the question so we know it! :) \$\endgroup\$ – IEatBagels Oct 16 '15 at 14:39
  • \$\begingroup\$ The only thing I would say, as a newer developer myself also, is that well commented code probably does require such long variable names. \$\endgroup\$ – Chris L Oct 19 '15 at 23:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.