mirror of
https://github.com/moodle/moodle.git
synced 2025-08-05 08:56:36 +02:00
MDL-57972 javascript: Change truncate.js behaviour
Updated truncate.js to behave closer to the moodle implementation of shorten_text. Part of MDL-55611
This commit is contained in:
parent
d74d91f49a
commit
7172b33e24
2 changed files with 94 additions and 8 deletions
2
lib/amd/build/truncate.min.js
vendored
2
lib/amd/build/truncate.min.js
vendored
|
@ -1 +1 @@
|
||||||
define(["jquery"],function(a){var b=/(\s*\S+|\s)$/,c=/^(\S*)/;return a.truncate=function(b,c){return a("<div></div>").append(b).truncate(c).html()},a.fn.truncate=function(d){a.isNumeric(d)&&(d={length:d});var e=a.extend({},a.truncate.defaults,d);return this.each(function(){var d=a(this);e.noBreaks&&d.find("br").replaceWith(" ");var f=d.text(),g=f.length-e.length;if(e.stripTags&&d.text(f),e.words&&g>0){var h=f.slice(0,e.length).replace(b,"").length;g=e.keepFirstWord&&0===h?f.length-c.exec(f)[0].length-1:f.length-h-1}g<0||!g&&!e.truncated||a.each(d.contents().get().reverse(),function(b,c){var d=a(c),f=d.text(),h=f.length;return h<=g?(e.truncated=!0,g-=h,void d.remove()):3===c.nodeType?(a(c.splitText(h-g-1)).replaceWith(e.ellipsis),!1):(d.truncate(a.extend(e,{length:h-g})),!1)})})},a.truncate.defaults={stripTags:!1,words:!1,keepFirstWord:!1,noBreaks:!1,length:1/0,ellipsis:"…"},{truncate:a.truncate}});
|
define(["jquery"],function(a){var b=/(\s*\S+|\s)$/,c=/^(\S*)/,d=/\s/,e=function(a,b){if(null==this)throw TypeError();var c=String(a),d=c.length,e=b?Number(b):0;if(e!=e&&(e=0),e<=-1||e>=d)return"";e=0|e;var f,g=c.charCodeAt(e),h=e+1,i=1;return g>=55296&&g<=56319&&d>h&&(f=c.charCodeAt(h),f>=56320&&f<=57343&&(i=2)),i},f=function(a){for(var b=0,c=0;c<a.length;c+=e(a,c))b++;return b},g=function(a,b){if(!a.length)return 0;var c=0,d=0;do c+=e(a,c),d++;while(c<a.length&&d<b);return c};return a.truncate=function(b,c){return a("<div></div>").append(b).truncate(c).html()},a.fn.truncate=function(e){a.isNumeric(e)&&(e={length:e});var h=a.extend({},a.truncate.defaults,e);return this.each(function(){var e=a(this);h.noBreaks&&e.find("br").replaceWith(" ");var i=h.ellipsis.length,j=e.text(),k=f(j),l=k-h.length+i;if(!(k<h.length)){if(h.stripTags&&e.text(j),h.words&&l>0){var m=j.slice(0,g(j,h.length-i)+1),n=m.replace(b,""),o=f(n),p=!m.match(d);l=h.keepFirstWord&&0===o?k-f(c.exec(j)[0])-i:p&&0===o?k-h.length+i:k-o-1}l>k&&(l=k-h.length),l<0||!l&&!h.truncated||a.each(e.contents().get().reverse(),function(b,c){var d=a(c),e=d.text(),j=f(e);if(j<=l)return h.truncated=!0,l-=j,void d.remove();if(3===c.nodeType){var k=j-l;return k=k>=0?g(e,k):0,a(c.splitText(k)).replaceWith(h.ellipsis),!1}return d.truncate(a.extend(h,{length:j-l+i})),!1})}})},a.truncate.defaults={stripTags:!1,words:!1,keepFirstWord:!1,noBreaks:!1,length:1/0,ellipsis:"…"},{truncate:a.truncate}});
|
|
@ -23,6 +23,8 @@
|
||||||
* @package core
|
* @package core
|
||||||
* @class truncate
|
* @class truncate
|
||||||
* @copyright 2017 Pathable
|
* @copyright 2017 Pathable
|
||||||
|
* 2017 Mathias Bynens
|
||||||
|
* 2017 Ryan Wyllie <ryan@moodle.com>
|
||||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
*/
|
*/
|
||||||
define(['jquery'], function($) {
|
define(['jquery'], function($) {
|
||||||
|
@ -33,6 +35,74 @@ define(['jquery'], function($) {
|
||||||
// Matches the first word in the string.
|
// Matches the first word in the string.
|
||||||
var start = /^(\S*)/;
|
var start = /^(\S*)/;
|
||||||
|
|
||||||
|
// Matches any space characters.
|
||||||
|
var space = /\s/;
|
||||||
|
|
||||||
|
// Special thanks to Mathias Bynens for the multi-byte char
|
||||||
|
// implementation. Much love.
|
||||||
|
// see: https://github.com/mathiasbynens/String.prototype.at/blob/master/at.js
|
||||||
|
var charLengthAt = function(text, position) {
|
||||||
|
if (this == null) {
|
||||||
|
throw TypeError();
|
||||||
|
}
|
||||||
|
var string = String(text);
|
||||||
|
var size = string.length;
|
||||||
|
// `ToInteger`
|
||||||
|
var index = position ? Number(position) : 0;
|
||||||
|
if (index != index) { // better `isNaN`
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
// Account for out-of-bounds indices
|
||||||
|
// The odd lower bound is because the ToInteger operation is
|
||||||
|
// going to round `n` to `0` for `-1 < n <= 0`.
|
||||||
|
if (index <= -1 || index >= size) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
// Second half of `ToInteger`
|
||||||
|
index = index | 0;
|
||||||
|
// Get the first code unit and code unit value
|
||||||
|
var cuFirst = string.charCodeAt(index);
|
||||||
|
var cuSecond;
|
||||||
|
var nextIndex = index + 1;
|
||||||
|
var len = 1;
|
||||||
|
if ( // Check if it’s the start of a surrogate pair.
|
||||||
|
cuFirst >= 0xD800 && cuFirst <= 0xDBFF && // high surrogate
|
||||||
|
size > nextIndex // there is a next code unit
|
||||||
|
) {
|
||||||
|
cuSecond = string.charCodeAt(nextIndex);
|
||||||
|
if (cuSecond >= 0xDC00 && cuSecond <= 0xDFFF) { // low surrogate
|
||||||
|
len = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
};
|
||||||
|
|
||||||
|
var lengthMultiByte = function(text) {
|
||||||
|
var count = 0;
|
||||||
|
|
||||||
|
for (var i = 0; i < text.length; i += charLengthAt(text, i)) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
};
|
||||||
|
|
||||||
|
var getSliceLength = function(text, amount) {
|
||||||
|
if (!text.length) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var length = 0;
|
||||||
|
var count = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
length += charLengthAt(text, length);
|
||||||
|
count++;
|
||||||
|
} while (length < text.length && count < amount);
|
||||||
|
|
||||||
|
return length;
|
||||||
|
};
|
||||||
|
|
||||||
// Return a truncated html string. Delegates to $.fn.truncate.
|
// Return a truncated html string. Delegates to $.fn.truncate.
|
||||||
$.truncate = function(html, options) {
|
$.truncate = function(html, options) {
|
||||||
return $('<div></div>').append(html).truncate(options).html();
|
return $('<div></div>').append(html).truncate(options).html();
|
||||||
|
@ -48,29 +118,42 @@ define(['jquery'], function($) {
|
||||||
|
|
||||||
if (o.noBreaks) self.find('br').replaceWith(' ');
|
if (o.noBreaks) self.find('br').replaceWith(' ');
|
||||||
|
|
||||||
|
var ellipsisLength = o.ellipsis.length;
|
||||||
var text = self.text();
|
var text = self.text();
|
||||||
var excess = text.length - o.length;
|
var textLength = lengthMultiByte(text);
|
||||||
|
var excess = textLength - o.length + ellipsisLength;
|
||||||
|
|
||||||
|
if (textLength < o.length) return;
|
||||||
if (o.stripTags) self.text(text);
|
if (o.stripTags) self.text(text);
|
||||||
|
|
||||||
// Chop off any partial words if appropriate.
|
// Chop off any partial words if appropriate.
|
||||||
if (o.words && excess > 0) {
|
if (o.words && excess > 0) {
|
||||||
var truncated = text.slice(0, o.length).replace(chop, '').length;
|
var sliced = text.slice(0, getSliceLength(text, o.length - ellipsisLength) + 1);
|
||||||
|
var replaced = sliced.replace(chop, '');
|
||||||
|
var truncated = lengthMultiByte(replaced);
|
||||||
|
var oneWord = sliced.match(space) ? false : true;
|
||||||
|
|
||||||
if (o.keepFirstWord && truncated === 0) {
|
if (o.keepFirstWord && truncated === 0) {
|
||||||
excess = text.length - start.exec(text)[0].length - 1;
|
excess = textLength - lengthMultiByte(start.exec(text)[0]) - ellipsisLength;
|
||||||
|
} else if (oneWord && truncated === 0) {
|
||||||
|
excess = textLength - o.length + ellipsisLength;
|
||||||
} else {
|
} else {
|
||||||
excess = text.length - truncated - 1;
|
excess = textLength - truncated - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The requested length is larger than the text. No need for ellipsis.
|
||||||
|
if (excess > textLength) {
|
||||||
|
excess = textLength - o.length;
|
||||||
|
}
|
||||||
|
|
||||||
if (excess < 0 || !excess && !o.truncated) return;
|
if (excess < 0 || !excess && !o.truncated) return;
|
||||||
|
|
||||||
// Iterate over each child node in reverse, removing excess text.
|
// Iterate over each child node in reverse, removing excess text.
|
||||||
$.each(self.contents().get().reverse(), function(i, el) {
|
$.each(self.contents().get().reverse(), function(i, el) {
|
||||||
var $el = $(el);
|
var $el = $(el);
|
||||||
var text = $el.text();
|
var text = $el.text();
|
||||||
var length = text.length;
|
var length = lengthMultiByte(text);
|
||||||
|
|
||||||
// If the text is longer than the excess, remove the node and continue.
|
// If the text is longer than the excess, remove the node and continue.
|
||||||
if (length <= excess) {
|
if (length <= excess) {
|
||||||
|
@ -82,12 +165,14 @@ define(['jquery'], function($) {
|
||||||
|
|
||||||
// Remove the excess text and append the ellipsis.
|
// Remove the excess text and append the ellipsis.
|
||||||
if (el.nodeType === 3) {
|
if (el.nodeType === 3) {
|
||||||
$(el.splitText(length - excess - 1)).replaceWith(o.ellipsis);
|
var splitAmount = length - excess;
|
||||||
|
splitAmount = splitAmount >= 0 ? getSliceLength(text, splitAmount) : 0;
|
||||||
|
$(el.splitText(splitAmount)).replaceWith(o.ellipsis);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recursively truncate child nodes.
|
// Recursively truncate child nodes.
|
||||||
$el.truncate($.extend(o, {length: length - excess}));
|
$el.truncate($.extend(o, {length: length - excess + ellipsisLength}));
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -115,6 +200,7 @@ define(['jquery'], function($) {
|
||||||
// used to prevent a hanging ellipsis, but displays incorrectly in Chrome
|
// used to prevent a hanging ellipsis, but displays incorrectly in Chrome
|
||||||
// on Windows 7.
|
// on Windows 7.
|
||||||
// http://code.google.com/p/chromium/issues/detail?id=68323
|
// http://code.google.com/p/chromium/issues/detail?id=68323
|
||||||
|
//ellipsis: '\u2026' // '\u2060\u2026'
|
||||||
ellipsis: '\u2026' // '\u2060\u2026'
|
ellipsis: '\u2026' // '\u2060\u2026'
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue