I'm looking for some help on how I can optimize adding multiple data attribute tags to elements, and really, any feedback at all.
Background
Client uses a analytics tool through a tag management application (Ensighten) that picks-up data attributes when links are clicked. I'm adding attributes when the DOM is ready to provide them with more information about what people are clicking, where they are clicking, etc.
init.js
Here is an example of my init.js file (Ensighten wraps this in a IIFE):
// global namespace window.analytics = window.analytics || {}; window.analytics.heatmapping = window.analytics.heatmapping || {}; window.analytics.heatmapping.header = { logo: function () { var $this = jQuery(this), name = $this.closest('ul.navL2').prev().text(), type = $this.attr('alt'), title = $this.attr('title'); window.analytics.utilities.setDataAttributes($this, { 'region': 'header', 'name': name, 'type': type, 'title': title, 'index': '1' }); } // ... more below, }; // initializing jQuery('.top a').each(window.analytics.heatmapping.header.logo);
utilities.js
I have another custom javascript tag that houses all of the utility functions that we can reuse. This is where the setDataAttributes
function is kept. Here is the setDataAttributes
function with its supporting functions.
/** * Set data attributes on an element * @param {object} element A jQuery object, typically we'll pass jQuery(this). * @param {object} dataAttributes The data attributes we wish to set */ window.analytics.utilities.setDataAttributes = function (element, dataAttributes) { var util = window.analytics.utilities, dataAnalyticsTagAttributes, if (util.hasDataAnalyticsTag(element)) { dataAnalyticsTagAttributes = util.parseDataAnalyticsTag(element); // merge objects $.extend(dataAttributes, dataAnalyticsTagAttributes); } dataAttributes = util.prefixAndTrimProperties(dataAttributes); element.attr(dataAttributes); }; /** * Prefixes the incoming objects keys with 'data-' and trims objects values * @param {object} dataAttributes * @return {object} dataAttributeWithPrefix */ window.analytics.utilities.prefixAndTrimProperties = function (dataAttributes) { var util = window.analytics.utilities, dataAttributesWithPrefix = {}, dataKeyWithPrefix, dataKey, dataValue for (dataKey in dataAttributes) { if (dataAttributes.hasOwnProperty(dataKey)) { // prefix key with data- and trim value dataKeyWithPrefix = util.addPrefixToKey(dataKey) dataValue = jQuery.trim(dataAttributes[dataKey]); // returns new prefixed and clean property in dataAttributesWithPrefix object dataAttributesWithPrefix[wedcsKeyWithPrefix] = dataValue; } } return dataAttributesWithPrefix; }; /** * Determines if input element has the data-analytics tag attibute * @param {object} element jQuery(this) * @return {Boolean} */ window.analytics.utilities.hasDataAnalyticsTag = function(element) { return element.is('[data-analyticstag]'); }; /** * adds the 'data-' prefix to the input string * @param {string} key The objects key it currently iterating on. * @return {string} */ window.analytics.utilities.addPrefixToKey = function (key) { return 'data-' + key; } /** * Parses the data-analytics attribute on * @param {object} element A jQuery object, typically we'll pass jQuery(this). * @return {object} An object with the properties index, linktype and cmpgrp */ window.analytics.utilities.parseDataAnalyticsTag = function (element) { var dataAnalyticsAttributeArray = element.attr('data-analyticstag').split('_'); return { 'index': dataAnalyticsAttributeArray[4].match(/\d$/), 'type': dataAnalyticsAttributeArray.splice(0, 4).join(':'), 'region': dataAnalyticsAttributeArray[3] }; };
Let me explain what the setDataAttributes
function does:
- it takes two arguments: element and dataAttributes (an object)
- it checks to see if the element has a dataAnalytics tag (some links have a data-analytics tag that we can get some values from)
- if the element does have the data-analyticstag, then we parse it and return an object (see
parseDataAnalyticsTag
) and merge it with the original dataAttributes object. - Next, we take the dataAttributes object and pass it into another function
prefixAndTrimProperties
where we prefix each key with 'data-' and trim each value, this function returns an object. - we take the returned object and pass it into
element.attr(dataAttributes)
where it then sets the data attributes for that specific element.
Questions
I'm currently reading Clean Code by Robert C. Martin, and I'm attempting to apply some of his practices around naming and functions - haven't made it to the rest of the book yet.
- How does my naming look? I'm a little lost on the
prefixAndTrimProperties
function. In his book he states that you only want the function to do one thing, and my function is doing two - at least. - Am I splitting up my functions in a way that are more testable? For example, is it really necessary to just have a function like
hasDataAnalyticsTag
returntrue
orfalse
? How granular should I be getting? Is it overkill? - Any other advice?