UNPKG

infusion

Version:

Infusion is an application framework for developing flexible stuff with JavaScript

137 lines (120 loc) 5.34 kB
/* Copyright The Infusion copyright holders See the AUTHORS.md file at the top-level directory of this distribution and at https://github.com/fluid-project/infusion/raw/master/AUTHORS.md. Licensed under the Educational Community License (ECL), Version 2.0 or the New BSD license. You may not use this file except in compliance with one these Licenses. You may obtain a copy of the ECL 2.0 License and BSD License at https://github.com/fluid-project/infusion/raw/master/Infusion-LICENSE.txt */ var fluid_3_0_0 = fluid_3_0_0 || {}; (function ($, fluid) { "use strict"; /******************************************************************************* * fluid.textNodeParser * * Parses out the text nodes from a DOM element and its descendants *******************************************************************************/ fluid.defaults("fluid.textNodeParser", { gradeNames: ["fluid.component"], events: { onParsedTextNode: null, afterParse: null }, invokers: { parse: { funcName: "fluid.textNodeParser.parse", args: ["{that}", "{arguments}.0", "{arguments}.1", "{that}.events.afterParse.fire"] }, hasTextToRead: "fluid.textNodeParser.hasTextToRead", isWord: "fluid.textNodeParser.isWord", getLang: "fluid.textNodeParser.getLang" } }); /** * Tests if a string is a word; i.e. it has a value and is not only whitespace. * inspired by https://stackoverflow.com/a/2031143 * * @param {String} str - the String to test * * @return {Boolean} - `true` if a word, `false` otherwise. */ fluid.textNodeParser.isWord = function (str) { return fluid.isValue(str) && /\S/.test(str); }; /** * Determines if there is text in an element that should be read. * Will return false in the following conditions: * - elm is falsey (undefined, null, etc.) * - elm's offsetHeight is 0 (e.g. display none set on itself or its parent) * - elm has no text or only whitespace * * NOTE: Text added by pseudo elements (e.g. :before, :after) are not considered. * NOTE: This method is not supported in IE 11 because innerText returns the text for some hidden elements * that is inconsistent with modern browsers. * * @param {jQuery|DomElement} elm - either a DOM node or a jQuery element * * @return {Boolean} - returns true if there is rendered text within the element and false otherwise. * (See rules above) */ fluid.textNodeParser.hasTextToRead = function (elm) { elm = fluid.unwrap(elm); return elm && !!elm.offsetHeight && fluid.textNodeParser.isWord(elm.innerText); }; /** * Similar to `fluid.textNodeParser.hasTextToRead` except adds the following condition: * - elm or its parent has `aria-hidden="true"` set. * * @param {jQuery|DomElement} elm - either a DOM node or a jQuery element * * @return {Boolean} - returns true if there is rendered text within the element and false otherwise. * (See rules above) */ fluid.textNodeParser.hasVisibleText = function (elm) { return fluid.textNodeParser.hasTextToRead(elm) && !$(elm).closest("[aria-hidden=\"true\"]").length; }; /** * Uses jQuery's `closest` method to find the closest element with a lang attribute, and returns the value. * * @param {jQuery|DomElement} elm - either a DOM node or a jQuery element * * @return {String|Undefined} - a valid BCP 47 language code if found, otherwise undefined. */ fluid.textNodeParser.getLang = function (elm) { return $(elm).closest("[lang]").attr("lang"); }; /** * Recursively parses a DOM element and it's sub elements and fires the `onParsedTextNode` event for each text node * found. The event is fired with the text node, language and index of the text node in the list of its parent's * child nodes.. * * Note: elements that return `false` to `that.hasTextToRead` are ignored. * * @param {Component} that - an instance of `fluid.textNodeParser` * @param {jQuery|DomElement} elm - the DOM node to parse * @param {String} lang - a valid BCP 47 language code. * @param {Event} afterParseEvent - the event to fire after parsing has completed. */ fluid.textNodeParser.parse = function (that, elm, lang, afterParseEvent) { elm = fluid.unwrap(elm); lang = lang || that.getLang(elm); if (that.hasTextToRead(elm)) { var childNodes = elm.childNodes; var elementLang = elm.getAttribute("lang") || lang; $.each(childNodes, function (childIndex, childNode) { if (childNode.nodeType === Node.TEXT_NODE) { that.events.onParsedTextNode.fire(childNode, elementLang, childIndex); } else if (childNode.nodeType === Node.ELEMENT_NODE) { fluid.textNodeParser.parse(that, childNode, elementLang); } }); } if (afterParseEvent) { afterParseEvent(that); } }; })(jQuery, fluid_3_0_0);