Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
// This file is part of Moodle - http://moodle.org/
2
//
3
// Moodle is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, either version 3 of the License, or
6
// (at your option) any later version.
7
//
8
// Moodle is distributed in the hope that it will be useful,
9
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
// GNU General Public License for more details.
12
//
13
// You should have received a copy of the GNU General Public License
14
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
15
 
16
/**
17
 * Description of import/upgrade into Moodle:
18
 * 1.) Download from https://github.com/pathable/truncate
19
 * 2.) Copy jquery.truncate.js into lib/amd/src/truncate.js
20
 * 3.) Edit truncate.js to return the $.truncate function as truncate
21
 * 4.) Apply Moodle changes from git commit 7172b33e241c4d42cff01f78bf8570408f43fdc2
22
 */
23
 
24
/**
25
 * Module for text truncation.
26
 *
27
 * Implementation provided by Pathable (thanks!).
28
 * See: https://github.com/pathable/truncate
29
 *
30
 * @module     core/truncate
31
 * @copyright  2017 Pathable
32
 *             2017 Mathias Bynens
33
 *             2017 Ryan Wyllie <ryan@moodle.com>
34
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35
 */
36
define(['jquery'], function($) {
37
 
38
  // Matches trailing non-space characters.
39
  var chop = /(\s*\S+|\s)$/;
40
 
41
  // Matches the first word in the string.
42
  var start = /^(\S*)/;
43
 
44
  // Matches any space characters.
45
  var space = /\s/;
46
 
47
  // Special thanks to Mathias Bynens for the multi-byte char
48
  // implementation. Much love.
49
  // see: https://github.com/mathiasbynens/String.prototype.at/blob/master/at.js
50
  var charLengthAt = function(text, position) {
51
    var string = String(text);
52
    var size = string.length;
53
    // `ToInteger`
54
    var index = position ? Number(position) : 0;
55
    if (index != index) { // better `isNaN`
56
      index = 0;
57
    }
58
    // Account for out-of-bounds indices
59
    // The odd lower bound is because the ToInteger operation is
60
    // going to round `n` to `0` for `-1 < n <= 0`.
61
    if (index <= -1 || index >= size) {
62
      return '';
63
    }
64
    // Second half of `ToInteger`
65
    index = index | 0;
66
    // Get the first code unit and code unit value
67
    var cuFirst = string.charCodeAt(index);
68
    var cuSecond;
69
    var nextIndex = index + 1;
70
    var len = 1;
71
    if ( // Check if it’s the start of a surrogate pair.
72
      cuFirst >= 0xD800 && cuFirst <= 0xDBFF && // high surrogate
73
      size > nextIndex // there is a next code unit
74
    ) {
75
      cuSecond = string.charCodeAt(nextIndex);
76
      if (cuSecond >= 0xDC00 && cuSecond <= 0xDFFF) { // low surrogate
77
        len = 2;
78
      }
79
    }
80
    return len;
81
  };
82
 
83
  var lengthMultiByte = function(text) {
84
    var count = 0;
85
 
86
    for (var i = 0; i < text.length; i += charLengthAt(text, i)) {
87
      count++;
88
    }
89
 
90
    return count;
91
  };
92
 
93
  var getSliceLength = function(text, amount) {
94
    if (!text.length) {
95
      return 0;
96
    }
97
 
98
    var length = 0;
99
    var count = 0;
100
 
101
    do {
102
      length += charLengthAt(text, length);
103
      count++;
104
    } while (length < text.length && count < amount);
105
 
106
    return length;
107
  };
108
 
109
  // Return a truncated html string.  Delegates to $.fn.truncate.
110
  $.truncate = function(html, options) {
111
    return $('<div></div>').append(html).truncate(options).html();
112
  };
113
 
114
  // Truncate the contents of an element in place.
115
  $.fn.truncate = function(options) {
116
    if (!isNaN(parseFloat(options))) options = {length: options};
117
    var o = $.extend({}, $.truncate.defaults, options);
118
 
119
    return this.each(function() {
120
      var self = $(this);
121
 
122
      if (o.noBreaks) self.find('br').replaceWith(' ');
123
 
124
      var ellipsisLength = o.ellipsis.length;
125
      var text = self.text();
126
      var textLength = lengthMultiByte(text);
127
      var excess = textLength - o.length + ellipsisLength;
128
 
129
      if (textLength < o.length) return;
130
      if (o.stripTags) self.text(text);
131
 
132
      // Chop off any partial words if appropriate.
133
      if (o.words && excess > 0) {
134
        var sliced = text.slice(0, getSliceLength(text, o.length - ellipsisLength) + 1);
135
        var replaced = sliced.replace(chop, '');
136
        var truncated = lengthMultiByte(replaced);
137
        var oneWord = sliced.match(space) ? false : true;
138
 
139
        if (o.keepFirstWord && truncated === 0) {
140
          excess = textLength - lengthMultiByte(start.exec(text)[0]) - ellipsisLength;
141
        } else if (oneWord && truncated === 0) {
142
          excess = textLength - o.length + ellipsisLength;
143
        } else {
144
          excess = textLength - truncated - 1;
145
        }
146
      }
147
 
148
      // The requested length is larger than the text. No need for ellipsis.
149
      if (excess > textLength) {
150
        excess = textLength - o.length;
151
      }
152
 
153
      if (excess < 0 || !excess && !o.truncated) return;
154
 
155
      // Iterate over each child node in reverse, removing excess text.
156
      $.each(self.contents().get().reverse(), function(i, el) {
157
        var $el = $(el);
158
        var text = $el.text();
159
        var length = lengthMultiByte(text);
160
 
161
        // If the text is longer than the excess, remove the node and continue.
162
        if (length <= excess) {
163
          o.truncated = true;
164
          excess -= length;
165
          $el.remove();
166
          return;
167
        }
168
 
169
        // Remove the excess text and append the ellipsis.
170
        if (el.nodeType === 3) {
171
          var splitAmount = length - excess;
172
          splitAmount = splitAmount >= 0 ? getSliceLength(text, splitAmount) : 0;
173
          $(el.splitText(splitAmount)).replaceWith(o.ellipsis);
174
          return false;
175
        }
176
 
177
        // Recursively truncate child nodes.
178
        $el.truncate($.extend(o, {length: length - excess + ellipsisLength}));
179
        return false;
180
      });
181
    });
182
  };
183
 
184
  $.truncate.defaults = {
185
 
186
    // Strip all html elements, leaving only plain text.
187
    stripTags: false,
188
 
189
    // Only truncate at word boundaries.
190
    words: false,
191
 
192
    // When 'words' is active, keeps the first word in the string
193
    // even if it's longer than a target length.
194
    keepFirstWord: false,
195
 
196
    // Replace instances of <br> with a single space.
197
    noBreaks: false,
198
 
199
    // The maximum length of the truncated html.
200
    length: Infinity,
201
 
202
    // The character to use as the ellipsis.  The word joiner (U+2060) can be
203
    // used to prevent a hanging ellipsis, but displays incorrectly in Chrome
204
    // on Windows 7.
205
    // http://code.google.com/p/chromium/issues/detail?id=68323
206
    //ellipsis: '\u2026' // '\u2060\u2026'
207
    ellipsis: '\u2026' // '\u2060\u2026'
208
 
209
  };
210
 
211
    return {
212
        truncate: $.truncate,
213
    };
214
});