Is it possible to add a personalized parameter to an unnamed JavaScript replace function?

I am looking to customize a date value in the following format:

var d = new Date();
myobj.format(d, "dddd (ddd)   S dd'd'.MM (MMM MMMM).yyyy HH:mm:ss.fff t tt T TT (o) {Z}");

I prefer not to utilize date.js because of its large size. The issue with the format-helper from stevenlevithan is the interchange of capital and lowercase 'M' characters. I want a consistent formatString that can be used in both C# and JavaScript.

Currently, I have developed my own solution which seems to be working well.
However, after moving the "format" function into the namespace myobj, the this-context gets lost within the format-function.

When calling the function "format" with .apply(this, arguments), the correct this-context is obtained, but the argument "m" is lost.

I wish to avoid having to call ord using the namespace structure (myobj.ord(bla)), and instead, be able to call it like "this.ord(bla)" or "aaa.ord(bla)", allowing for easy changes to the namespace name.

So, how can I either pass an extra argument to the anonymous function in the replace-regex or retain the "this"-context without losing m?

/* @license: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. 
https://github.com/datejs/Datejs/blob/master/src/core.js
https://code.google.com/p/datejs/wiki/FormatSpecifiers
http://stackoverflow.com/questions/3552461/how-to-format-a-javascript-date
http://blog.stevenlevithan.com/archives/date-time-format
*/




// https://github.com/datejs/Datejs/blob/master/src/globalization/en-US.js
var $i18n =
{
    dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
    abbreviatedDayNames: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
    shortestDayNames: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
    firstLetterDayNames: ["S", "M", "T", "W", "T", "F", "S"],

    monthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
    abbreviatedMonthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],

    amDesignator: "AM",
    pmDesignator: "PM",
}




var myobj =
{
    // Pad number with 0
    p: function (val, len)
    {
        val = String(val);
        len = len || 2;
        while (val.length < len) val = "0" + val;
        return val;
    }

    // Pad Milliseconds
    , mp: function (d, n)
    {
        var i = 3, res = p(d.getMilliseconds(), 3).substr(0, n);

        for (; i < n; ++i)
            res += "0";

        return res;
    }


    , tzo: function (d)
    {
        var o = d.getTimezoneOffset();
        return (o > 0 ? "-" : "+") + p(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4)
    }


    , tz: function (date)
    {
        var timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
        timezoneClip = /[^-+\dA-Z]/g;
        return (String(date).match(timezone) || [""]).pop().replace(timezoneClip, "");
    }

    , ord: function (num)
    {
        if (num <= 0)
            return num.toString();

        switch (num % 100)
        {
            case 11:
            case 12:
            case 13:
                return num + "th";
        }

        switch (num % 10)
        {
            case 1:
                return num + "st";
            case 2:
                return num + "nd";
            case 3:
                return num + "rd";
            default:
                return num + "th";
        }

    } // End Fn ord



    , format: function (x, formatString)
    {
        // "S dd'd'.MM (MMMM).yyyy ".replace(/(\\)?(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|S)/g, 
        return formatString.replace(/d{1,4}|M{1,4}|f{1,7}|yy(?:yy)?|([HhmsTt])\1?|[oSZ]|"[^"]*"|'[^']*'/g,
            function (m, aaa)
            {
                console.log("foo");
                console.log(this);
                console.log(aaa);


                if (m.charAt(0) === "\\")
                {
                    return m.replace("\\", "");
                }

                x.h = x.getHours;

                switch (m)
                {
                    case "hh":
                        return p(x.h() < 13 ? (x.h() === 0 ? 12 : x.h()) : (x.h() - 12));
                    case "h":
                        return x.h() < 13 ? (x.h() === 0 ? 12 : x.h()) : (x.h() - 12);
                    case "HH":
                        return p(x.h());
                    case "H":
                        return x.h();
                    case "mm":
                        return p(x.getMinutes());
                    case "m":
                        return x.getMinutes();
                    case "ss":
                        return p(x.getSeconds());
                    case "s":
                        return x.getSeconds();
                    case "yyyy":
                        return p(x.getFullYear(), 4);
                    case "yy":
                        return p(x.getFullYear());
                    case "dddd":
                        return $i18n.dayNames[x.getDay()];
                    case "ddd":
                        return $i18n.abbreviatedDayNames[x.getDay()];
                    case "dd":
                        return p(x.getDate());
                    case "d":
                        return x.getDate();
                    case "MMMM":
                        return $i18n.monthNames[x.getMonth()];
                    case "MMM":
                        return $i18n.abbreviatedMonthNames[x.getMonth()];
                    case "MM":
                        return p((x.getMonth() + 1));
                    case "M":
                        return x.getMonth() + 1;
                    case "t":
                        return (x.h() < 12 ? $i18n.amDesignator.substring(0, 1) : $i18n.pmDesignator.substring(0, 1)).toLowerCase();
                    case "tt":
                        return (x.h() < 12 ? $i18n.amDesignator : $i18n.pmDesignator).toLowerCase();;
                    case "T":
                        return x.h() < 12 ? $i18n.amDesignator.substring(0, 1) : $i18n.pmDesignator.substring(0, 1);
                    case "TT":
                        return x.h() < 12 ? $i18n.amDesignator : $i18n.pmDesignator;
                    case "S":
                        console.log(this);
                        return this.ord(x.getDate());
                    case "fffffff":
                        return mp(x, 7);
                    case "ffffff":
                        return mp(x, 6);
                    case "fffff":
                        return mp(x, 5);
                    case "ffff":
                        return mp(x, 4);
                    case "fff":
                        return mp(x, 3);
                    case "ff":
                        return mp(x, 2);
                    case "f":
                        return mp(x, 1);
                    case "o":
                        return tzo(d);
                    case "Z":
                        return tz(d);
                    default:
                        return m;
                } // End Switch
            } // End Fn
            //.apply(this, arguments)
        );
    }

};




Edit: The solution is simple, just use bind instead of apply:

/* @license: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. 
https://github.com/datejs/Datejs/blob/master/src/core.js
https://code.google.com/p/datejs/wiki/FormatSpecifiers
http://stackoverflow.com/questions/3552461/how-to-format-a-javascript-date
http://blog.stevenlevithan.com/archives/date-time-format
http://stackoverflow.com/questions/6002808/is-there-any-way-to-get-current-time-in-nanoseconds-using-javascript
*/




// https://github.com/datejs/Datejs/blob/master/src/globalization/en-US.js
var $i18n =
{
    dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
    abbreviatedDayNames: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
    shortestDayNames: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
    firstLetterDayNames: ["S", "M", "T", "W", "T", "F", "S"],

    monthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
    abbreviatedMonthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],

    amDesignator: "AM",
    pmDesignator: "PM",
}




var myobj =
{
    // Pad number with 0
    p: function (val, len)
    {
        val = String(val);
        len = len || 2;
        while (val.length < len) val = "0" + val;
        return val;
    }

    // Pad Milliseconds
    , mp: function (d, n)
    {
        var i = 3, res = this.p(d.getMilliseconds(), 3).substr(0, n);

        for (; i < n; ++i)
            res += "0";

        return res;
    }


    , tzo: function (d)
    {
        var o = d.getTimezoneOffset();
        return (o > 0 ? "-" : "+") + this.p(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4)
    }


    , tz: function (date)
    {
        var timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
        timezoneClip = /[^-+\dA-Z]/g;
        return (String(date).match(timezone) || [""]).pop().replace(timezoneClip, "");
    }

    , ord: function (num)
    {
        if (num <= 0)
            return num.toString();

        switch (num % 100)
        {
            case 11:
            case 12:
            case 13:
                return num + "th";
        }

        switch (num % 10)
        {
            case 1:
                return num + "st";
            case 2:
                return num + "nd";
            case 3:
                return num + "rd";
            default:
                return num + "th";
        }

    } // End Fn ord

    ,"formatString": function(str) 
    {
        if (!str)
            return str;

        str = str.toString();

        if (arguments.length < 2) 
            return str;

        var t = typeof arguments[1],
            args = "string" == t || "number" == t ? Array.prototype.slice.call(arguments) : arguments[1];

        for (var arg in args) 
            str = str.replace(new RegExp("\\{" + arg + "\\}", "gi"), args[arg]);

        return str
    }

    , "format": function (x, formatString)
    {
        // "S dd'd'.MM (MMMM).yyyy ".replace(/(\\)?(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|S)/g, 
        return formatString.replace(/d{1,4}|M{1,4}|f{1,7}|yy(?:yy)?|([HhmsTt])\1?|[oSZ]|"[^"]*"|'[^']*'/g,
            function (m)
            {
                var  p = this.p 
                    ,mp = this.mp.bind(this) 
                    ,tzo = this.tzo.bind(this) 
                    ,tz = this.tz.bind(this) 
                    ,ord = this.ord.bind(this);


                x.h = x.getHours;

                if (m.charAt(0) === "\\")
                {
                    return m.replace("\\", "");
                }

                switch (m)
                {
                    case "hh":
                        return p(x.h() < 13 ? (x.h() === 0 ? 12 : x.h()) : (x.h() - 12));
                    case "h":
                        return x.h() < 13 ? (x.h() === 0 ? 12 : x.h()) : (x.h() - 12);
                    case "HH":
                        return p(x.h());
                    case "H":
                        return x.h();
                    case "mm":
                        return p(x.getMinutes());
                    case "m":
                        return x.getMinutes();
                    case "ss":
                        return p(x.getSeconds());
                    case "s":
                        return x.getSeconds();
                    case "yyyy":
                        return p(x.getFullYear(), 4);
                    case "yy":
                        return p(x.getFullYear());
                    case "dddd":
                        return $i18n.dayNames[x.getDay()];
                    case "ddd":
                        return $i18n.abbreviatedDayNames[x.getDay()];
                    case "dd":
                        return p(x.getDate());
                    case "d":
                        return x.getDate();
                    case "MMMM":
                        return $i18n.monthNames[x.getMonth()];
                    case "MMM":
                        return $i18n.abbreviatedMonthNames[x.getMonth()];
                    case "MM":
                        return p((x.getMonth() + 1));
                    case "M":
                        return x.getMonth() + 1;
                    case "t":
                        return (x.h() < 12 ? $i18n.amDesignator.substring(0, 1) : $i18n.pmDesignator.substring(0, 1)).toLowerCase();
                    case "tt":
                        return (x.h() < 12 ? $i18n.amDesignator : $i18n.pmDesignator).toLowerCase();;
                    case "T":
                        return x.h() < 12 ? $i18n.amDesignator.substring(0, 1) : $i18n.pmDesignator.substring(0, 1);
                    case "TT":
                        return x.h() < 12 ? $i18n.amDesignator : $i18n.pmDesignator;
                    case "S":
                        return ord(x.getDate());
                    case "fffffff":
                        return mp(x, 7);
                    case "ffffff":
                        return mp(x, 6);
                    case "fffff":
                        return mp(x, 5);
                    case "ffff":
                        return mp(x, 4);
                    case "fff":
                        return mp(x, 3);
                    case "ff":
                        return mp(x, 2);
                    case "f":
                        return mp(x, 1);
                    case "o":
                        return tzo(x);
                    case "Z":
                        return tz(x);
                    default:
                        return m;
                } // End Switch
            } // End Fn
            .bind(this)
            //.apply(this, arguments)
        );
    }

};


var x = new Date();
myobj.format(x, "dddd (ddd)   S dd'd'.MM (MMM MMMM).yyyy HH:mm:ss.fff t tt T TT (o) {Z}")



myobj.formatString("hello {foo} name", { foo: "bar" });
// myobj.formatString("hello {foo} name");

Answer №1

Transfer the method from within the replace function to a separate method in your object and utilize bind when calling the method to maintain scope.

...
dateRegExp : /d{1,4}|M{1,4}|f{1,7}|yy(?:yy)?|([HhmsTt])\1?|[oSZ]|"[^"]*"|'[^']*'/g,
format: function (x, formatString) {
        return formatString.replace(this.dateRegExp, this._formatFnc.bind(this, x));
},
_formatFnc : function (x, m, aaa) { 
    /* insert updated code here */ 
    return "qwerty"; 
}
...

If you prefer an alternative approach, store this in a variable and refer to it within the replace function.

var that = this;
return formatString.replace(..., function() {
    console.log(that);
    return "qwerty";
};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ensuring the script waits for the complete loading of iframe prior to

I'm faced with an issue on the website I'm currently working on. There's a Live Chat plugin integrated on an iframe, and I need to change an image if no agents are available. Interestingly, my code works perfectly fine when tested on the con ...

I am currently working on a website that offers different themes, and I am attempting to update the iframe to reflect the selected theme on the site

I'm feeling lost on how to accomplish this task. Despite my efforts, I have been unable to find a solution so far. Perhaps utilizing javascript might be the key here, yet I am uncertain about integrating it into the existing script that I use for modi ...

Jade iterates over each object element, assigning its children to their respective parent elements

I have a JavaScript Object named "boards". [{"id":1,"parent_board":0,"title":"Lorem 1","description":"ec40db959345153a9912"}, {"id":2,"parent_board":0,"title":"Lorem 2","description":"bb698136a211ebb1dfedb"}, {"id":3,"parent_board":1,"title":"Lorem 1-1"," ...

What is the best way to craft an if/else statement for a situation when a twig variable is undefined?

When utilizing twig to declare a variable called user: <script type="text/javascript> {% if user is defined %} var user = { example: {{ userjson | raw }} }; {% endif %} </script> If a user is not logged in, an error message a ...

Why does the for loop assign the last iteration of jQuery onclick to all elements?

I've encountered an issue with my code that I'd like to discuss var btns = $('.gotobtn'); $('#'+btns.get(0).id).click(function() { document.querySelector('#navigator').pushPage('directions.html', myInf ...

Using jQuery, how can you make fixed elements fade as the page scrolls?

How can I make a fixed element, such as a corner ad or notice, fade when the page is scrolled down to a certain point? What would be the most effective method for determining this point: using pixels, percentage, or another way? And how can I implement th ...

What is an alternative method for creating a horizontal line without the need for the <hr> tag?

Is there a way to create a slim horizontal line without using the <hr> tag ? This is what I attempted: .horizontal-line{ border-top: 1px solid #9E9E9E; border-bottom: 1px solid #9E9E9E; } While it does function, I am hoping for a thinner line. ...

Tips on ensuring the <script> section of a Vuejs single file component loads prior to the <template> section

After posing my query here, I have come to the realization that the root of my problem might be due to the template loading before the script. This causes an error when it encounters an undefined variable, halting the script execution. The issue could pote ...

Tips for successfully uploading FormData files using Axios: Resolving the TypeError of "file.mv is not a function"

When transmitting a file from one server to another using Axios, I am facing an interesting scenario where one server is an app backend and the other is a blockchain server. The destination for the file transmission is set up as follows: router.post("/a ...

Unveiling the Evasive Final Element in a JavaScript Array

Having a Javascript array named full_range: const range1 = _.range(1, 10, 0.5); const range2 = _.range(10, 100, 5); const range3 = _.range(100, 1000, 50); const range4 = _.range(1000, 10000, 500); const range5 = _.range(10000, 105000, 5000); const full_ran ...

Creating multiple tabs in PHP using the header function can be achieved by specifying the location in

I am attempting to open a new tab using Php code: header("location:print_register.php?recpt_no=".$recpt_no); In addition, I would like to open two tabs programmatically with the following code snippet: header("location:print_register.php?recpt_no=".$rec ...

Utilize $.get AJAX to extract data from a multidimensional JSON array

Struggling to make two functions work on my form that uses AJAX and jQuery to look up an array. One function is functional while the other seems to be causing confusion with over-analysis and extensive troubleshooting. Any insights into what may be missing ...

Join the geomarkers in two datasets using connecting lines

I am currently developing a leaflet.js map incorporating two distinct sets of JSON data layers stored as js-files. The first dataset comprises the geographical locations of various newsrooms along with their respective IDs, while the second dataset contai ...

What's the best way to display a component once a function has been executed?

My service controls the visibility of components using *ngIf! Currently, when I click a button, the service sets to true and the components appear instantly! I want the components to only show after a specific function has finished executing. This means I ...

Combine the values in the array with the input

I received some data from the back-end which is being written to a form, and it's in the form of an array of objects Below is the code snippet: this.companyDetailsForm = new FormGroup({ directors : new FormControl(response?.companyDirectors) ...

Using deconstruction in exporting as default

As I was diving into a new codebase, I stumbled upon this interesting setup: //index.js export { default } from './Tabs' export { default as Tab } from './Tab' //Tab.js export default class Tab extends Component { render() => &ap ...

I am attempting to adjust the color of the active tab, but I seem to be encountering issues in my code. Can anyone help me

The currently active tab should change along with the text inside the box, but it's not working as expected. I'm struggling to find out why. Here is a fiddle to demonstrate my progress so far: var btn1 = document.getElementById("btn1"); va ...

Unable to download and install jspdf version 1.5.3

Currently, I am facing an issue where I need to convert HTML to PDF using jspdf 1.5.2. However, I am encountering an error that says "Cannot read property 'charAt' of undefined" when trying to utilize html2canvas. When attempting to upgrade to j ...

Leverage the power of react-i18next in class-based components by utilizing decorators and Higher Order

Currently, I am working on implementing i18n into my React project that also utilizes Redux, with the assistance of react-i18next. In this particular project, we are using class components alongside decorators. Originally, I intended to experiment with r ...

Difficulty comprehending the response from an AJAX post is being experienced

I'm currently working on a website and facing an issue connecting JavaScript with PHP using AJAX. Specifically, I'm struggling with reading the AJAX response. My PHP script contains the following code: <?php echo "1"; In addition, I have a ...