Rothrock
Rothrock

Reputation: 1512

How to replace jQuery $.trim()?

I'm using jQuery in a website has a polyfill for the built-in String.trim(). Site used to run in IE 8 a lot and needed the polyfill, but it doesn't anymore. Unfortunately I can't remove the polyfill from the page -- I don't have permissions to touch that and there is no possible way for me to remove it -- so this bit of code runs before anything I can control:

String.prototype.trim = function() {
    return this.replace(/^\s\s*/, "").replace(/\s\s*$/, "")
}

Then jQuery comes along and does this, not realizing that the native String.trim has already by messed with:

// Use native String.trim function wherever possible
trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
    function( text ) {
        return text == null ?
            "" :
            core_trim.call( text );
    } :

    // Otherwise use our own trimming functionality
    function( text ) {
        return text == null ?
            "" :
            ( text + "" ).replace( rtrim, "" );
    },

Up to now this hasn't really been much of a problem, but I'm using the Datatables plugin for jQuery and it has many places where it calls $.trim() on data that isn't a string, like number or arrays. The native code in IE 11 and Chrome (the browsers we target) knows to just return the value of $.trim(6), but the polyfill doesn't.

I tried redefining the the prototype with a function that should work:

String.prototype.trim = function(){
   if(typeof this.valueOf(this) === 'string'){
       return this.replace(/^\s\s*/, "").replace(/\s\s*$/, "");
   } else {
       return this.valueOf(this);
   }
} 

But that didn't work because jQuery has already extend using the polyfill and further changes to the prototype won't change what jQuery is using.

I tried following this thread to redefine $.trim(), but that didn't work.

Is there a way to return String.prototype.trim() to its native code?

Is there a way to redefine $.trim()?

Some other idea I haven't thought of?

Upvotes: 2

Views: 3797

Answers (3)

Rothrock
Rothrock

Reputation: 1512

Based on Jack Bashford's answer I came up with this.

String.prototype.trim = function(){
  if(typeof this.valueOf(this) === 'string'){
    return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
  } else {
    return this.valueOf(this);
  }
};

$.trim = function(e){
    return String.prototype.trim.call(e);
};

Part of the original problem was that I needed to fix it so that if $.trim(number) or $.trim(array) was called it wouldn't throw and error.

Upvotes: 1

Jack Bashford
Jack Bashford

Reputation: 44105

Simply override jQuery's $.trim() using String.prototype.trim(), then override String.prototype.trim() with your function:

var trimText = "       Some text       ";

String.prototype.trim = function() {
  return this.replace(/^\s\s*/, "").replace(/\s\s*$/, "")
}

$.trim = function(string) {
  return String.prototype.trim(string);
}

trimText = trimText.trim();

console.log(trimText);
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>

Upvotes: 1

WilliamNHarvey
WilliamNHarvey

Reputation: 2485

You can override jQuery core methods

(function(){
    var string = "       TRIM ME      ";
    console.log(jQuery.trim(string));
    // Define overriding method.
    jQuery.trim = function(string){
        return string;
    }
    console.log(jQuery.trim(string));
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Upvotes: 1

Related Questions