react-youtube-playlist
Version:
A react component for displaying the contents of a user's YouTube playlist.
520 lines (448 loc) • 16.1 kB
JavaScript
/*
* jQuery dotdotdot 1.8.3
*
* Copyright (c) Fred Heusschen
* www.frebsite.nl
*
* Plugin website:
* dotdotdot.frebsite.nl
*
* Licensed under the MIT license.
* http://en.wikipedia.org/wiki/MIT_License
*/
const $ = require('jquery');
module.exports = function ($, undef) {
'use strict';
if ($.fn.dotdotdot) {
return;
}
$.fn.dotdotdot = function (o) {
if (this.length === 0) {
$.fn.dotdotdot.debug('No element found for "' + this.selector + '".');
return this;
}
if (this.length > 1) {
return this.each(function () {
$(this).dotdotdot(o);
});
}
var $dot = this;
var orgContent = $dot.contents();
if ($dot.data('dotdotdot')) {
$dot.trigger('destroy.dot');
}
$dot.data('dotdotdot-style', $dot.attr('style') || '');
$dot.css('word-wrap', 'break-word');
if ($dot.css('white-space') === 'nowrap') {
$dot.css('white-space', 'normal');
}
$dot.bind_events = function () {
$dot.bind('update.dot', function (e, c) {
$dot.removeClass("is-truncated");
e.preventDefault();
e.stopPropagation();
switch (typeof opts.height) {
case 'number':
opts.maxHeight = opts.height;
break;
case 'function':
opts.maxHeight = opts.height.call($dot[0]);
break;
default:
opts.maxHeight = getTrueInnerHeight($dot);
break;
}
opts.maxHeight += opts.tolerance;
if (typeof c != 'undefined') {
if (typeof c == 'string' || 'nodeType' in c && c.nodeType === 1) {
c = $('<div />').append(c).contents();
}
if (c instanceof $) {
orgContent = c;
}
}
$inr = $dot.wrapInner('<div class="dotdotdot" />').children();
$inr.contents().detach().end().append(orgContent.clone(true)).find('br').replaceWith(' <br /> ').end().css({
'height': 'auto',
'width': 'auto',
'border': 'none',
'padding': 0,
'margin': 0
});
var after = false,
trunc = false;
if (conf.afterElement) {
after = conf.afterElement.clone(true);
after.show();
conf.afterElement.detach();
}
if (test($inr, opts)) {
if (opts.wrap == 'children') {
trunc = children($inr, opts, after);
} else {
trunc = ellipsis($inr, $dot, $inr, opts, after);
}
}
$inr.replaceWith($inr.contents());
$inr = null;
if ($.isFunction(opts.callback)) {
opts.callback.call($dot[0], trunc, orgContent);
}
conf.isTruncated = trunc;
return trunc;
}).bind('isTruncated.dot', function (e, fn) {
e.preventDefault();
e.stopPropagation();
if (typeof fn == 'function') {
fn.call($dot[0], conf.isTruncated);
}
return conf.isTruncated;
}).bind('originalContent.dot', function (e, fn) {
e.preventDefault();
e.stopPropagation();
if (typeof fn == 'function') {
fn.call($dot[0], orgContent);
}
return orgContent;
}).bind('destroy.dot', function (e) {
e.preventDefault();
e.stopPropagation();
$dot.unwatch().unbind_events().contents().detach().end().append(orgContent).attr('style', $dot.data('dotdotdot-style') || '').removeClass('is-truncated').data('dotdotdot', false);
});
return $dot;
}; // /bind_events
$dot.unbind_events = function () {
$dot.unbind('.dot');
return $dot;
}; // /unbind_events
$dot.watch = function () {
$dot.unwatch();
if (opts.watch == 'window') {
var $window = $(window),
_wWidth = $window.width(),
_wHeight = $window.height();
$window.bind('resize.dot' + conf.dotId, function () {
if (_wWidth != $window.width() || _wHeight != $window.height() || !opts.windowResizeFix) {
_wWidth = $window.width();
_wHeight = $window.height();
if (watchInt) {
clearInterval(watchInt);
}
watchInt = setTimeout(function () {
$dot.trigger('update.dot');
}, 100);
}
});
} else {
watchOrg = getSizes($dot);
watchInt = setInterval(function () {
if ($dot.is(':visible')) {
var watchNew = getSizes($dot);
if (watchOrg.width != watchNew.width || watchOrg.height != watchNew.height) {
$dot.trigger('update.dot');
watchOrg = watchNew;
}
}
}, 500);
}
return $dot;
};
$dot.unwatch = function () {
$(window).unbind('resize.dot' + conf.dotId);
if (watchInt) {
clearInterval(watchInt);
}
return $dot;
};
var opts = $.extend(true, {}, $.fn.dotdotdot.defaults, o),
conf = {},
watchOrg = {},
watchInt = null,
$inr = null;
if (!(opts.lastCharacter.remove instanceof Array)) {
opts.lastCharacter.remove = $.fn.dotdotdot.defaultArrays.lastCharacter.remove;
}
if (!(opts.lastCharacter.noEllipsis instanceof Array)) {
opts.lastCharacter.noEllipsis = $.fn.dotdotdot.defaultArrays.lastCharacter.noEllipsis;
}
conf.afterElement = getElement(opts.after, $dot);
conf.isTruncated = false;
conf.dotId = dotId++;
$dot.data('dotdotdot', true).bind_events().trigger('update.dot');
if (opts.watch) {
$dot.watch();
}
return $dot;
};
// public
$.fn.dotdotdot.defaults = {
'ellipsis': '... ',
'wrap': 'word',
'fallbackToLetter': true,
'lastCharacter': {},
'tolerance': 0,
'callback': null,
'after': null,
'height': null,
'watch': false,
'windowResizeFix': true,
'maxLength': null
};
$.fn.dotdotdot.defaultArrays = {
'lastCharacter': {
'remove': [' ', '\u3000', ',', ';', '.', '!', '?'],
'noEllipsis': []
}
};
$.fn.dotdotdot.debug = function (msg) {};
// private
var dotId = 1;
function children($elem, o, after) {
var $elements = $elem.children(),
isTruncated = false;
$elem.empty();
for (var a = 0, l = $elements.length; a < l; a++) {
var $e = $elements.eq(a);
$elem.append($e);
if (after) {
$elem.append(after);
}
if (test($elem, o)) {
$e.remove();
isTruncated = true;
break;
} else {
if (after) {
after.detach();
}
}
}
return isTruncated;
}
function ellipsis($elem, $d, $i, o, after) {
var isTruncated = false;
// Don't put the ellipsis directly inside these elements
var notx = 'a, table, thead, tbody, tfoot, tr, col, colgroup, object, embed, param, ol, ul, dl, blockquote, select, optgroup, option, textarea, script, style';
// Don't remove these elements even if they are after the ellipsis
var noty = 'script, .dotdotdot-keep';
$elem.contents().detach().each(function () {
var e = this,
$e = $(e);
if (typeof e == 'undefined') {
return true;
} else if ($e.is(noty)) {
$elem.append($e);
} else if (isTruncated) {
return true;
} else {
$elem.append($e);
if (after && !$e.is(o.after) && !$e.find(o.after).length) {
$elem[$elem.is(notx) ? 'after' : 'append'](after);
}
if (test($i, o)) {
if (e.nodeType == 3) // node is TEXT
{
isTruncated = ellipsisElement($e, $d, $i, o, after);
} else {
isTruncated = ellipsis($e, $d, $i, o, after);
}
}
if (!isTruncated) {
if (after) {
after.detach();
}
}
}
});
$d.addClass("is-truncated");
return isTruncated;
}
function ellipsisElement($e, $d, $i, o, after) {
var e = $e[0];
if (!e) {
return false;
}
var txt = getTextContent(e),
space = txt.indexOf(' ') !== -1 ? ' ' : '\u3000',
separator = o.wrap == 'letter' ? '' : space,
textArr = txt.split(separator),
position = -1,
midPos = -1,
startPos = 0,
endPos = textArr.length - 1;
// Only one word
if (o.fallbackToLetter && startPos === 0 && endPos === 0) {
separator = '';
textArr = txt.split(separator);
endPos = textArr.length - 1;
}
if (o.maxLength) {
txt = addEllipsis(txt.trim().substr(0, o.maxLength), o);
setTextContent(e, txt);
} else {
while (startPos <= endPos && !(startPos === 0 && endPos === 0)) {
var m = Math.floor((startPos + endPos) / 2);
if (m == midPos) {
break;
}
midPos = m;
setTextContent(e, textArr.slice(0, midPos + 1).join(separator) + o.ellipsis);
$i.children().each(function () {
$(this).toggle().toggle();
});
if (!test($i, o)) {
position = midPos;
startPos = midPos;
} else {
endPos = midPos;
// Fallback to letter
if (o.fallbackToLetter && startPos === 0 && endPos === 0) {
separator = '';
textArr = textArr[0].split(separator);
position = -1;
midPos = -1;
startPos = 0;
endPos = textArr.length - 1;
}
}
}
if (position != -1 && !(textArr.length === 1 && textArr[0].length === 0)) {
txt = addEllipsis(textArr.slice(0, position + 1).join(separator), o);
setTextContent(e, txt);
} else {
var $w = $e.parent();
$e.detach();
var afterLength = after && after.closest($w).length ? after.length : 0;
if ($w.contents().length > afterLength) {
e = findLastTextNode($w.contents().eq(-1 - afterLength), $d);
} else {
e = findLastTextNode($w, $d, true);
if (!afterLength) {
$w.detach();
}
}
if (e) {
txt = addEllipsis(getTextContent(e), o);
setTextContent(e, txt);
if (afterLength && after) {
var $parent = after.parent();
$(e).parent().append(after);
if (!$.trim($parent.html())) {
$parent.remove();
}
}
}
}
}
return true;
}
function test($i, o) {
return $i.innerHeight() > o.maxHeight || o.maxLength && $i.text().trim().length > o.maxLength;
}
function addEllipsis(txt, o) {
while ($.inArray(txt.slice(-1), o.lastCharacter.remove) > -1) {
txt = txt.slice(0, -1);
}
if ($.inArray(txt.slice(-1), o.lastCharacter.noEllipsis) < 0) {
txt += o.ellipsis;
}
return txt;
}
function getSizes($d) {
return {
'width': $d.innerWidth(),
'height': $d.innerHeight()
};
}
function setTextContent(e, content) {
if (e.innerText) {
e.innerText = content;
} else if (e.nodeValue) {
e.nodeValue = content;
} else if (e.textContent) {
e.textContent = content;
}
}
function getTextContent(e) {
if (e.innerText) {
return e.innerText;
} else if (e.nodeValue) {
return e.nodeValue;
} else if (e.textContent) {
return e.textContent;
} else {
return "";
}
}
function getPrevNode(n) {
do {
n = n.previousSibling;
} while (n && n.nodeType !== 1 && n.nodeType !== 3);
return n;
}
function findLastTextNode($el, $top, excludeCurrent) {
var e = $el && $el[0],
p;
if (e) {
if (!excludeCurrent) {
if (e.nodeType === 3) {
return e;
}
if ($.trim($el.text())) {
return findLastTextNode($el.contents().last(), $top);
}
}
p = getPrevNode(e);
while (!p) {
$el = $el.parent();
if ($el.is($top) || !$el.length) {
return false;
}
p = getPrevNode($el[0]);
}
if (p) {
return findLastTextNode($(p), $top);
}
}
return false;
}
function getElement(e, $i) {
if (!e) {
return false;
}
if (typeof e === 'string') {
e = $(e, $i);
return e.length ? e : false;
}
return !e.jquery ? false : e;
}
function getTrueInnerHeight($el) {
var h = $el.innerHeight(),
a = ['paddingTop', 'paddingBottom'];
for (var z = 0, l = a.length; z < l; z++) {
var m = parseInt($el.css(a[z]), 10);
if (isNaN(m)) {
m = 0;
}
h -= m;
}
return h;
}
// override jQuery.html
var _orgHtml = $.fn.html;
$.fn.html = function (str) {
if (str != undef && !$.isFunction(str) && this.data('dotdotdot')) {
return this.trigger('update', [str]);
}
return _orgHtml.apply(this, arguments);
};
// override jQuery.text
var _orgText = $.fn.text;
$.fn.text = function (str) {
if (str != undef && !$.isFunction(str) && this.data('dotdotdot')) {
str = $('<div />').text(str).html();
return this.trigger('update', [str]);
}
return _orgText.apply(this, arguments);
};
};