'use strict'; (function(window, document, undefined) { var defaultOptions; defaultOptions = { className: 'revealing', /** * Tokenizer method * * @param DOM Node element * @return Array of wrapped nodes */ tokenizer: function(node) { if (node.nodeType === 3) { return node.nodeValue.split('').map(function(s) { return ''+s+''; }); // return node.nodeValue.replace(/\w/g, '$&'); } return null; } }; // check for collision if (window.Revealing !== undefined) { throw new Error("The global name Revealing is already assigned, it's a collision !"); } /** * Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1 * @param obj1 * @param obj2 * @returns obj3 a new object based on obj1 and obj2 */ function mergeOptions(obj1, obj2) { var obj3 = {}, attrname; for (attrname in obj1) { obj3[attrname] = obj1[attrname]; } for (attrname in obj2) { obj3[attrname] = obj2[attrname]; } return obj3; } function addClassName(el, className) { if (el.classList) { el.classList.add(className); } else { el.className += ' ' + className; } } function removeClassName(el, className) { if (el.classList) { el.classList.remove(className); } else { el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); } } /** * Recursively inject IN PLACE elements to wrap each letters */ function injector(root, tokenizer) { if (tokenizer === undefined) { throw new Error("You need to specify a tokenizer method"); } // split elements var tokens = tokenizer(root); if (tokens !== null) { return tokens; } var els = [], nodes = []; // node element if (root.nodeType === 1) { els = root.childNodes; } // recursively wrap text nodes Array.prototype.forEach.call(els, function(el) { nodes = nodes.concat(injector(el, tokenizer)); }); // replace html content with new nodes root.innerHTML = ''; nodes.forEach(function(el) { if (el.nodeType === 1) { root.innerHTML += el.outerHTML; } else if (el.nodeType === 3) { root.innerHTML += el.nodeValue; } else { root.innerHTML += el; } }); return root; } var Revealing = function(element, options) { this.element = element; this.settings = mergeOptions(defaultOptions, options); this.init(); }; Revealing.prototype.init = function() { // add the base animation class if not already present addClassName(this.element, this.settings.className); // split the elements this.tokenize(); }; Revealing.prototype.tokenize = function() { injector(this.element, this.settings.tokenizer); }; // public methods Revealing.prototype.show = function() { removeClassName(this.element, 'reset'); addClassName(this.element, 'reveal'); }; Revealing.prototype.reset = function() { removeClassName(this.element, 'reveal') addClassName(this.element, 'reset'); }; // expose the class window.Revealing = Revealing; })(window, document);