diff --git a/.gitignore b/.gitignore index 29c0029..6e067fb 100644 --- a/.gitignore +++ b/.gitignore @@ -14,5 +14,6 @@ Thumbs.db # NPM /node_modules yarn-error.log +yarn.lock !**/.gitkeep diff --git a/CHANGELOG.md b/CHANGELOG.md index 20b0403..f6a03e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changes +## unreleased + + - FEATURE: Added truncate component. #32 + ## 1.4.1 - FEATURE: Added return of instance in startComponent. #30 diff --git a/scss/tools/_media.scss b/scss/tools/_media.scss index 43d7d44..77c6c03 100644 --- a/scss/tools/_media.scss +++ b/scss/tools/_media.scss @@ -187,4 +187,3 @@ $media-breakpoints: $breakpoints !default; } } } - diff --git a/src/components/truncate.js b/src/components/truncate.js new file mode 100644 index 0000000..0106ff8 --- /dev/null +++ b/src/components/truncate.js @@ -0,0 +1,71 @@ +// Truncate text component module + +'use strict'; + +var $ = require('jquery'); +var debounce = require('../services/debounce'); + +module.exports = function Truncate() { + var truncate = {}; + + /** + * @example + *
+ * Lorem ipsum ... + *
+ * + * import truncate from 'massive-web/src/components/truncate'; + * truncate.initialize($('#truncate'), {}); + * + * @param {jQuery} $el + * @param {object} options + */ + truncate.initialize = function initialize($el, options) { + truncate.$el = $el; + + // Set default options if no custom options are defined + truncate.separator = options.separator || ' ...'; + truncate.debounceDelay = options.debounceDelay || 250; + + truncate.text = truncate.$el.text().trim(); + truncate.$inner = $('').text(truncate.text).css('display', 'block'); + truncate.$el.html(truncate.$inner).css('display', 'block'); + + truncate.calculateRegex(); + truncate.calculateText(); + + $(window).on('resize', debounce(truncate.calculateText, truncate.debounceDelay)); + }; + + /** + * Calculate regex based on the separator. + */ + truncate.calculateRegex = function calculateRegex() { + var separatorRegex = truncate.separator.split('').map(c => '\\' + c).join(''); + truncate.regex = new RegExp('\\W*\\s?(?:\\S*|\\S*' + separatorRegex + ')$'); + }; + + /** + * Calculate output text based on the element's height. + */ + truncate.calculateText = function calculateText() { + var height; + + truncate.$inner.text(truncate.text); + height = truncate.$el.height(); + + while (truncate.$inner.outerHeight() > height) { + truncate.$inner.text(function(index, text) { + if (text === truncate.separator) { + return ''; + } + + return text.replace(truncate.regex, truncate.separator); + }); + } + }; + + return { + initialize: truncate.initialize + }; +}; diff --git a/src/services/debounce.js b/src/services/debounce.js new file mode 100644 index 0000000..9f7cb96 --- /dev/null +++ b/src/services/debounce.js @@ -0,0 +1,30 @@ +// Debounce function + +'use strict'; + +/** + * Extracted from UnderscoreJS + * + * @ignore + */ +module.exports = function debounce(func, wait, immediate) { + var timeout; + + return function() { + var context = this; + var args = arguments; + + clearTimeout(timeout); + timeout = setTimeout(function() { + timeout = null; + + if (!immediate) { + func.apply(context, args); + } + }, wait); + + if (immediate && !timeout) { + func.apply(context, args); + } + }; +};