0

I use a PHP based system to generate HTML pages from a template and series of included files.

Any scripts (whether linked or inline) are extracted from these includes and placed at the beginning or end of the generated page.

Inline scripts are combined into a single inline script.

This all works well.

The only thing I am missing is a way to combine the multiple $(document).ready jQuery functions into a single function.

Whilst it works fine having the multiple functions, for aesthetics and readibility it would be nice to have a single $(document).ready function.

To give an example, I'd want to be able to parse this:

<script language="javascript" type="text/javascript">
$(document).ready(function() {
    $('.icheck').iCheck({
        checkboxClass: 'icheckbox_minimal-green',
        radioClass: 'iradio_minimal-green',
    });
    $('.icheckblack').iCheck({
        checkboxClass: 'icheckbox_minimal',
        radioClass: 'iradio_minimal',
    });
});
$(document).on("eldarion-ajax:begin", function(evt, $el) {
    $(".noData").remove();
    $("#" + $el.data("bq")).show();
});
$(document).ready(function() {
    $(".commentToggle").each(function(index) {
        $(this).click(function() {
            var tl_id = $(this).data('tl_id');
            $("#commentForm" + tl_id).toggle();
        });
    });

});
$(function() {
    $('#email_content').redactor();
});
</script>

Into this:

<script language="javascript" type="text/javascript">
$(document).on("eldarion-ajax:begin", function(evt, $el) {
    $(".noData").remove();
    $("#" + $el.data("bq")).show();
});

$(function() {
    $('#email_content').redactor();
});

$(document).ready(function() {
    $(".commentToggle").each(function(index) {
        $(this).click(function() {
            var tl_id = $(this).data('tl_id');
            $("#commentForm" + tl_id).toggle();
        });
    });
    $('.icheck').iCheck({
        checkboxClass: 'icheckbox_minimal-green',
        radioClass: 'iradio_minimal-green',
    });
    $('.icheckblack').iCheck({
        checkboxClass: 'icheckbox_minimal',
        radioClass: 'iradio_minimal',
    });

});
</script>

I've seen similar questions which haven't really been answered, but have pointed in the direction of Tim Whitlock's jParser but this isn't very well documented and seems to be overkill for my needs.

I've considered using something based around preg_match_all, but I don't think JavaScript is consistent enough in its structure/formatting for this to be reliable.

Pandy Legend
  • 1,102
  • 3
  • 15
  • 29
  • 1
    [You can have multiple $(document).ready handlers on one page](https://stackoverflow.com/questions/1327756/can-you-have-multiple-document-readyfunction-sections) – Jared Smith Sep 28 '17 at 15:09

1 Answers1

1

I did something similar like this once. I'll try to get some psuedo code later once I get time. But the gist of it is that you read the javascript file and iterate over it line by line and use preg_match to match $(document).ready(function() { exactly. Once you match that line, start recording each subsequent line into a string. This string will record all of the functions within document ready.

Then, create a $counter variable that will count the number of open and close parenthesis and set it to 1 by default. Then as you iterate over the lines, do a preg_match_all for open parenthesis ( and another preg_match_all for closing parenthesis ) and count the number of matches for each open/close parenthesis on each line. For every open parenthesis, increment your $counter variable by 1, and for every closing parenthesis decrement the $counter variable by -1. Then after every line, check the current variable counter to see if it's at 0. Once it's at 0, that should mean that the original $(document).ready(function() { has been closed. Once all files are parsed an all functions inside the $(document).ready statement have been recorded, add them to your own $(document).ready string.

Of course, this assumes the javascript file isn't minified and $(document).ready statements start and close on their own separate lines. If the file is minified or not formatted properly, then you'll need to do some more involved stuff with strpos(). This method will be problematic if for whatever reason you have a single opening or closing parenthesis stored in a string like ')'. But if you don't think that'll be an issue, then this should work well enough.

Walker Boh
  • 750
  • 6
  • 13
  • Thanks Walker Boh - this is what I was thinking, but as you rightly pointed out, it would require that the js is correctly formatted and not minified. Whilst in most cases it will be, unfortunatley I can't guarantee it. Perhaps I could first run a js formatter, then this could be more viable, but there would be some speed cost. – Pandy Legend Oct 13 '17 at 06:07