How do you add a simple javascript function in Sage 9?

Give this a try

window.do_something = function() {
  console.log('doing something');
}
<script>
  jQuery(document).ready(function($){
    console.log('ready');
    do_something();
  });
</script>

As mentioned, webpack does not add functions/variables to the global scope; adding window.something adds something to the window scope, which any template file can use.

Apologies if this has been covered already; I’ll be honest, I mostly skimmed this thread :sweat_smile:

@kculmback 's solution should work for you, and as much as this is an issue somewhat related to webpack, it’s much more a general Javascript issue, you could create the same pattern / problem easily using just jQuery.

Not all browsers support dynamic imports, so webpack uses closures to polyfill them when transpiling down to ES5 / Older JS, this means that each individual JS file is effectively within it’s own closure, thus any functions defined within it are limited in scope to that closure.

Take the following code that uses an IIFE (which is used often to run code in jQuery’s ‘no conflict mode’ within WordPress themes) - same issue arrises even if the code is printed directly into the doc via the script tag, no webpack whatsoever involved.

<script>
// Is immediately invoked on definition
(function(){
// defined within the closure
  function do_something() {
    console.log('doing something');
  }
})()

jQuery(document).ready(function(){
  // will result in 'ReferenceError: do_something is not defined'
  do_something();
});
</script>

@kculmback’s example works as it defines the function in the global scope, though these days people recommend pretty heavily against doing that, as the global namespace can easily become pretty polluted (a lot of things get added to it so clashes can occur easily ) so you’d be better off doing something like

// Creates if undefined
window.myNamespacedSiteObject = window.myNamespacedSiteObject || {};

window.myNamespacedSiteObject.doSomething = function(){ 
    console.log( 'doing something' );  
};

From your blade template

jQuery(document).ready( function( $ ){ 
     myNamespacedSiteObject.doSomething(); 
 } );

Beyond these closure issues, I’d argue the whole pattern of printing out JS in php templates is less than ideal, but if you have your reasons for doing that then there’s no reason why technically it can’t work .

3 Likes