How to correctly add Javascript to this PHP ‘Page Not Found’ Page?

Problem

The Short Version

The problem isn’t how you’re using those scripts or where you’re placing them – it’s how the authors of those scripts wrote them.

The Long Version

Your “superfish” script which controls the functionality of your navigation menu is throwing errors because $.browser is undefined. While $.browser was deprecated more than 3 years ago, WordPress loads the “jQuery Migrate Plugin” by default, which should alleviate the issue by providing functionality for deprecated code – unless one of 49 scripts loaded between jQuery Migrate and Superfish is over-writing $.browser for some reason: and here we get to the meat of the problem.

The “widget scripts” described in your answer all load even more scripts and libraries on top of the 68 others on the page, including different versions of the jQuery and jQuery UI components that your site has already loaded. Your site itself loads jQuery v1.12.4 while the “widget scripts” load v1.9.1. Using your browser’s JavaScript console, you can check the version in memory at the end of page load by executing jQuery.fn.jquery or $.fn.jquery – which on your site produces 1.9.1.

This reveals a problematic issue – the “widget scripts” from “idxhome” are not properly encapsulated, nor do they load jQuery in compatibility mode. The result is that they’re completely overwriting the window.jQuery and window.$ variables, which includes erasing the $.browser variable – thus causing the superfish error and breaking your navigation. The other massive side-effect is that it’s incredibly difficult to determine which code on your page is executing with which version of jQuery, which has a high potential to produce all manner of bizarre bugs – especially since the version that the idx widgets are injecting is almost 4 years older than the one your site loads.

Normally, you could use jQuery’s jQuery.noConflict() function to restore the jQuery and $ global variables as they existed before something else clobbered them (in this case, the other jQuery library loaded by the widget scripts) – however since each idx widget loads it’s own jQuery library, even the “backup copies” of these variables point to the wrong jQuery code after two or more widgets are loaded.

On a side note regarding the code you posted, it’s worth a comment that there’s usually no good reason to place non-text-related HTML (things other than elements like <span>, <strong>, and <em>) inside of the WordPress translation functions such as _e(), as it is most commonly desirable for the markup to remain the same regardless of the active language.


Solutions

If you have no intention of learning WordPress and web development, you might consider hiring a developer to optimize your site (combining scripts and stylesheets, removing unnecessary and redundant ones, performing version updates where beneficial, etc.). It’s a great looking site – but it could use some technical love!

In any scenario, one of the most worthwhile solutions is probably to contact the authors of the IDX scripts regarding this issue – I feel they should update their scripts to be more courteous to the environments which they are loaded into (say, improving encapsulation and using noConflict() where necessary). Even if they don’t, they may be able to provide a solution if this problem is something that comes up frequently.

Otherwise, one solution I would look into are implementing the widgets yourself (ideally, check out the JavaScript and HTML in the remote files and create WordPress shortcodes to print more compatible versions) instead of loading those “widget scripts” such that you can control which libraries are loaded and how they do so.

Hacks

I believe all of the easy solutions are “hacks” that add duct-tape on top of duct-tape, and ideally should be avoided on a production site. Among them:

  • Manually imitate jQuery.noConflict() by saving the global jQuery variables before the idx widget scripts, and restoring them afterwards. However, if the jQuery libraries inserted by the idx scripts are loaded asynchronously, there’s a chance that the restoration would occur too early and the idx jQuery library could still overwrite the site’s instance:

    Before:

    <script type="text/javascript">
      window._wpse232741_jQuery = window.jQuery;
    </script>
    

    After:

    <script type="text/javascript">
      window.jQuery = window.$ = window._wpse232741_jQuery;
    </script>
    
  • As $.browser was deprecated 3+ years ago, it seems likely that your site is using an outdated version of superfish. Updating it to one which does not rely on $.browser should remove the error (though the problem of competing jQuery libraries would remain).

  • Execute the jQuery Migrate script (again) responsible for setting jQuery.browser after the widget scripts (though, again, the competing library versions issue still remains – and there’s still the chance that if the IDX scripts loading jQuery asynchronously could break this):

    After:

    <script type="text/javascript" src="https://wordpress.stackexchange.com/wp-includes/js/jquery/jquery-migrate.min.js?ver=1.4.1"></script>
    
  • You should be able to maintain the proper version of jQuery by applying jQuery.noConflict() where IDX failed to – yet, once again, if the IDX jQuery is loaded asynchronously this might not work.

    After Each IDX <script> Element:

    <script type="text/javascript">jQuery.noConflict(true);</script>