0

I am trying to use an HTML truncating function called 'cutKeepingTags()' found and demonstrated online (https://jsfiddle.net/7mbxf5hq/) but when I try to run it I get a console error: Uncaught TypeError: Cannot read property 'match' of undefined at cutKeepingTags ((index):566). I am using the framework Codeigniter 3, the OS is Windows 10 latest, the version of jQuery is 3.3.1, PHP version 7.4.7 and I am using Vscode as my editor.

The function code is:

function cutKeepingTags(elem, reqCount) {
    var grabText = '',
        missCount = reqCount;
    $(elem).contents().each(function() {
        switch (this.nodeType) {
            case Node.TEXT_NODE:
                // Get node text, limited to missCount.
                grabText += this.data.substr(0, missCount);
                missCount -= Math.min(this.data.length, missCount);
                break;
            case Node.ELEMENT_NODE:
                // Explore current child:
                var childPart = cutKeepingTags(this, missCount);
                grabText += childPart.text;
                missCount -= childPart.count;
                break;
        }
        if (missCount === 0) {
            // We got text enough, stop looping.
            return false;
        }
    });
    return {
        text:
            // Wrap text using current elem tag.
            elem.outerHTML.match(/^<[^>]+>/m)[0] + grabText + '</' + elem.localName + '>',
        count: reqCount - missCount
    };
}

and the line objected to is the penultimate line containing 'match(/^<[^>]+>/m)[0]'. As the demo works it should work for me as 'advertised'. Why is Javascript throwing the error?

Mike Heath
  • 51
  • 2
  • 8

1 Answers1

1

When you select an element by class (.), it always returns an array regardless of whether or not you have more than one. The element being passed in the first argument must be a native dom element, not an array of dom elements.

var target = $('.truncated'); is not the same as var target = $('.truncated')[0];

Under the hood, JQuery is doing this: document.getElementsByClassName('truncated')[0];

Any Day
  • 418
  • 2
  • 9
  • Thanks for responding. For the first argument I am passing a variable containing html from a database but for test purposes I am simply using the word TEST. I'm thinking that there is something amiss with the regex syntax. Could it be that my PHP version is expecting something different (delimiters maybe) or that VSCode is displaying the wrong characters? What I can't understand is how the example works in jsfiddle but not for me unless it's a version thing. – Mike Heath Jun 09 '21 at 12:50
  • No I don't think its Regex, your function is identifying that it's a variable, just not a dom element. If it's from a database, you're likely trying to pass a string of html, which again, isn't a valid dom element. In order to pass it a correct format, you can use this: https://stackoverflow.com/questions/494143/creating-a-new-dom-element-from-an-html-string-using-built-in-dom-methods-or-pro – Any Day Jun 09 '21 at 13:15
  • Thanks for that. I have a variable 'postext = TEST' and I then ran your jsfiddle function to turn it into an object - which appeared to succeed - on logging to the console I now get [object Text] BUT still the same TypeError relating to the regex line so there appears to be another issue. – Mike Heath Jun 09 '21 at 14:47
  • Can you edit the JSFiddle and show me the exact variable you're trying to pass? `postext = 'TEST'` is not html, that's a string. `postext = '

    TEST

    '` is, so is `postext = 'TEST'`. You're trying to pass a string to a truncate function that expects HTML.
    – Any Day Jun 09 '21 at 15:12
  • Instead of doing that, I added p tags to my TEST string and to my delight it appears to have worked - the TypeError has gone and postext now logs as [object HTMLParagraphElement]. I thought that a text string was just a simple case of tagless html but now I know better. The next issue I have is to use the output. I have set up a variable 'let cut = cutKeepingTags(postext, 300);' and it logs to the console as [object Object] - therefore it exists. When I do, say, $('.content').text(cut); I get an error that cut is undefined? – Mike Heath Jun 09 '21 at 15:51
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/233566/discussion-between-mike-heath-and-any-day). – Mike Heath Jun 09 '21 at 16:00