Commit 0c90bfe3 authored by Andrew Nicols's avatar Andrew Nicols
Browse files

Merge branch 'MDL-57972-master' of git://github.com/ryanwyllie/moodle

parents 342af35a 75378ded
......@@ -56,6 +56,7 @@ lib/amd/src/chartjs-lazy.js
lib/maxmind/GeoIp2/
lib/maxmind/MaxMind/
lib/ltiprovider/
lib/amd/src/truncate.js
media/player/videojs/amd/src/video-lazy.js
media/player/videojs/amd/src/Youtube-lazy.js
media/player/videojs/videojs/
......
......@@ -57,6 +57,7 @@ lib/amd/src/chartjs-lazy.js
lib/maxmind/GeoIp2/
lib/maxmind/MaxMind/
lib/ltiprovider/
lib/amd/src/truncate.js
media/player/videojs/amd/src/video-lazy.js
media/player/videojs/amd/src/Youtube-lazy.js
media/player/videojs/videojs/
......
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
......@@ -29,14 +29,14 @@ define(['core/mustache',
'core/str',
'core/notification',
'core/url',
'core/log',
'core/config',
'core/localstorage',
'core/event',
'core/yui',
'core/log'
'core/log',
'core/truncate'
],
function(mustache, $, ajax, str, notification, coreurl, log, config, storage, event, Y, Log) {
function(mustache, $, ajax, str, notification, coreurl, config, storage, event, Y, Log, Truncate) {
// Module variables.
/** @var {Number} uniqInstances Count of times this constructor has been called. */
......@@ -261,6 +261,33 @@ define(['core/mustache',
return '"' + content + '"';
};
/**
* Shorten text helper to truncate text and append a trailing ellipsis.
*
* @method shortenTextHelper
* @private
* @param {object} context The current mustache context.
* @param {string} sectionText The text to parse the arguments from.
* @param {function} helper Used to render subsections of the text.
* @return {string}
*/
Renderer.prototype.shortenTextHelper = function(context, sectionText, helper) {
// Non-greedy split on comma to grab section text into the length and
// text parts.
var regex = /(.*?),(.*)/;
var parts = sectionText.match(regex);
// The length is the part matched in the first set of parethesis.
var length = parts[1].trim();
// The length is the part matched in the second set of parethesis.
var text = parts[2].trim();
var content = helper(text, context);
return Truncate.truncate(content, {
length: length,
words: true,
ellipsis: '...'
});
};
/**
* Add some common helper functions to all context objects passed to templates.
* These helpers match exactly the helpers available in php.
......@@ -287,6 +314,9 @@ define(['core/mustache',
context.quote = function() {
return this.quoteHelper.bind(this, context);
}.bind(this);
context.shortentext = function() {
return this.shortenTextHelper.bind(this, context);
}.bind(this);
context.globals = {config: config};
context.currentTheme = themeName;
};
......
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Description of import/upgrade into Moodle:
* 1.) Download from https://github.com/pathable/truncate
* 2.) Copy jquery.truncate.js into lib/amd/src/truncate.js
* 3.) Edit truncate.js to return the $.truncate function as truncate
* 4.) Apply Moodle changes from git commit 7172b33e241c4d42cff01f78bf8570408f43fdc2
*/
/**
* Module for text truncation.
*
* Implementation provided by Pathable (thanks!).
* See: https://github.com/pathable/truncate
*
* @module core/truncate
* @package core
* @class truncate
* @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
*/
define(['jquery'], function($) {
// Matches trailing non-space characters.
var chop = /(\s*\S+|\s)$/;
// Matches the first word in the string.
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.
$.truncate = function(html, options) {
return $('<div></div>').append(html).truncate(options).html();
};
// Truncate the contents of an element in place.
$.fn.truncate = function(options) {
if ($.isNumeric(options)) options = {length: options};
var o = $.extend({}, $.truncate.defaults, options);
return this.each(function() {
var self = $(this);
if (o.noBreaks) self.find('br').replaceWith(' ');
var ellipsisLength = o.ellipsis.length;
var text = self.text();
var textLength = lengthMultiByte(text);
var excess = textLength - o.length + ellipsisLength;
if (textLength < o.length) return;
if (o.stripTags) self.text(text);
// Chop off any partial words if appropriate.
if (o.words && excess > 0) {
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) {
excess = textLength - lengthMultiByte(start.exec(text)[0]) - ellipsisLength;
} else if (oneWord && truncated === 0) {
excess = textLength - o.length + ellipsisLength;
} else {
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;
// Iterate over each child node in reverse, removing excess text.
$.each(self.contents().get().reverse(), function(i, el) {
var $el = $(el);
var text = $el.text();
var length = lengthMultiByte(text);
// If the text is longer than the excess, remove the node and continue.
if (length <= excess) {
o.truncated = true;
excess -= length;
$el.remove();
return;
}
// Remove the excess text and append the ellipsis.
if (el.nodeType === 3) {
var splitAmount = length - excess;
splitAmount = splitAmount >= 0 ? getSliceLength(text, splitAmount) : 0;
$(el.splitText(splitAmount)).replaceWith(o.ellipsis);
return false;
}
// Recursively truncate child nodes.
$el.truncate($.extend(o, {length: length - excess + ellipsisLength}));
return false;
});
});
};
$.truncate.defaults = {
// Strip all html elements, leaving only plain text.
stripTags: false,
// Only truncate at word boundaries.
words: false,
// When 'words' is active, keeps the first word in the string
// even if it's longer than a target length.
keepFirstWord: false,
// Replace instances of <br> with a single space.
noBreaks: false,
// The maximum length of the truncated html.
length: Infinity,
// The character to use as the ellipsis. The word joiner (U+2060) can be
// used to prevent a hanging ellipsis, but displays incorrectly in Chrome
// on Windows 7.
// http://code.google.com/p/chromium/issues/detail?id=68323
//ellipsis: '\u2026' // '\u2060\u2026'
ellipsis: '\u2026' // '\u2060\u2026'
};
return {
truncate: $.truncate,
};
});
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Mustache helper shorten text.
*
* @package core
* @category output
* @copyright 2017 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core\output;
defined('MOODLE_INTERNAL') || die();
use Mustache_LambdaHelper;
use renderer_base;
/**
* This class will call shorten_text with the section content.
*
* @copyright 2017 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mustache_shorten_text_helper {
/**
* Read a length and text component from the string.
*
* {{#shortentext}}50,Some test to shorten{{/shortentext}}
*
* Both args are required. The length must come first.
*
* @param string $args The text to parse for arguments.
* @param Mustache_LambdaHelper $helper Used to render nested mustache variables.
* @return string
*/
public function shorten($args, Mustache_LambdaHelper $helper) {
// Split the text into an array of variables.
list($length, $text) = explode(',', $args, 2);
$length = trim($length);
$text = trim($text);
// Allow mustache tags in the text.
$text = $helper->render($text);
return shorten_text($text, $length);
}
}
......@@ -91,6 +91,7 @@ class renderer_base {
$quotehelper = new \core\output\mustache_quote_helper();
$jshelper = new \core\output\mustache_javascript_helper($this->page->requires);
$pixhelper = new \core\output\mustache_pix_helper($this);
$shortentexthelper = new \core\output\mustache_shorten_text_helper();
// We only expose the variables that are exposed to JS templates.
$safeconfig = $this->page->requires->get_config_for_javascript($this->page, $this);
......@@ -99,7 +100,8 @@ class renderer_base {
'str' => array($stringhelper, 'str'),
'quote' => array($quotehelper, 'quote'),
'js' => array($jshelper, 'help'),
'pix' => array($pixhelper, 'pix'));
'pix' => array($pixhelper, 'pix'),
'shortentext' => array($shortentexthelper, 'shorten'));
$this->mustache = new Mustache_Engine(array(
'cache' => $cachedir,
......
......@@ -291,4 +291,10 @@
<version>3.0.2</version>
<licenseversion>2.0</licenseversion>
</library>
<library>
<location>amd/src/truncate.js</location>
<name>Truncate.js</name>
<license>MIT</license>
<version>0.0.1</version>
</library>
</libraries>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment