app/scripts/ui-lib/ellipsis.coffee

Ellipsis

The Ellipsis class provides a plugin that truncates text/HTML.

author: Julien Ramboz
version: 1.0
usage: Ellipsis examples

AMD loader

Try loading as AMD module or fall back to default loading

((plugin) -> if typeof define is "function" and define.amd define ["jslib", "core", "plugin"], plugin else plugin @$, _, AbstractPlugin ) ellipsis = ($, _, AbstractPlugin) -> "use strict"

The actual plugin class

class Ellipsis extends AbstractPlugin

Default options for the plugin

@defaultOptions: format: "html" parent: "" append: "…" resize: true keep: "" allowDescenders: true

Initializer function.

initialize: (options) -> super(options)

Clean up content

if @options.format is "html" @element.html( @element.html() .replace(/\n/g, "") # Remove newlines .replace(/\ +/g," ") # Remove multiple spaces .replace(/> </g, "><") # Remove empty elements .replace(/^\s\s*/g, '') # Remove leading spaces .replace(/\s\s*$/g, '')) # Remove trailing spaces @originalText = @element.html() else @element.text( @element.text() .replace(/^\s\s*/, '') # Remove leading spaces .replace(/\s\s*$/, '')) # Remove trailing spaces @originalText = @element.text()

Find the parent to use as reference

@parent = @element.parents(@options.parent or undefined).first() return if not @parent.length @truncate()

Event handling

Attach evenets to the widget

bindEvents: () ->

Do the actual truncation

truncate: () -> if @options.format is "html" @element.html(@originalText) else @element.text(@originalText)

Truncate until the element fits into the reference parent height NOTE: "|| 0" with parseInt is for compatibility with IE8-

height = @parent.height() + @parent.offset().top - @element.offset().top + (parseInt(@parent.css('padding-bottom'), 10) || 0)

Let descenders overflow

if @options.descenders height += (parseInt(@element.css('font-size'), 10) || 0) / 2

Abort truncation if height <= 0 or we won't have any text displayed

return if height <= 0 text = @originalText

Prepare the string append

append = @options.append if @options.keep regexp = new RegExp("<(\\w+)[^>]*?class=\"([^\"]+ )?" + @options.keep + "( [^\"]+)?\\2[^>]*>.*<\\/\\1>") match = text.match regexp if match text = text.replace(regexp, "") .replace(/^\s\s*/, '') # Remove leading spaces .replace(/\s\s*$/, '') # Remove trailing spaces append += match.length and ("&nbsp;" + match[0]) or "" $last = @parent.eq(0).children().last() if $last.get(0) isnt @element.get(0) height = height - $last.height() diff = true padding = (parseInt(@element.css('border-top-width'), 10) || 0) + (parseInt(@element.css('border-bottom-width'), 10) || 0) + (parseInt(@element.css('padding-top'), 10) || 0) + (parseInt(@element.css('padding-bottom'), 10) || 0) + (parseInt(@element.css('margin-top'), 10) || 0) + 0 (parseInt(@element.css('margin-bottom'), 10) || 0) loop outerHeight = @element.height() + padding break if outerHeight <= height or not diff if @options.format is "html" oldText = text break if not oldText text = @truncateHtml(text) diff = oldText isnt text @element.html(text) children = @element.children() if children.length lastChild = children.last() lastChild.html(lastChild.html() + append) else @element.html(@element.html() + append) else oldText = text break if not oldText text = @truncateText(oldText) diff = oldText isnt text @element.text(text + append)

Truncate a simple text string.

truncateText: (string) -> string.replace(/\W*\s(\S)*$/, '')

Truncate an HTML text string and preserve HTML tags.

truncateHtml: (string) -> string .replace(/\s*[^>\s]+\s*((<\/\w+>)*)$/,'$1') # Remove last tag/word .replace(/<(\w+)[^>]*><\/\1>/g,'') # Remove empty tags @doTruncate: () -> $("[data-ellipsis]").each () -> ellipsis = _.getInstance(this, "ellipsis") if ellipsis.options.resize ellipsis.truncate()

Cleanup

Reset the plugin for re-initialisation

reset: (options) -> if options.format is "html" @element.html(@originalText) else @element.text(@originalText)

Installation

Install the plugin into the JS library

Ellipsis.install("Ellipsis", () -> $("[data-ellipsis='html']")["#{_.namespace}ellipsis"]( format: 'html' append: '&hellip;') $("[data-ellipsis='text']")["#{_.namespace}ellipsis"]( format: 'text' append: '\u2026') $(window).on "resize", () -> clearTimeout(Ellipsis.resizing) Ellipsis.resizing = setTimeout(Ellipsis.doTruncate, 200) )