To print, or not to print?

 “Philosophy begins in wonder” – Plato

Digging in Magento’s code is like a travel to unknown place full of wonders and curiosities. Even if you have a map soon you realize that either the map is wrong or you jumped into the wrong train.

Where am I? What is this all about? Ah… the endless fields of astonishing curios…

For today I dig up a really fat worm for you. I was trying to print order from a customer dashboard and a nasty error jumped off the bushes.

jQuery is not defined
jQuery is not defined

Oh, great! This is a core. Let’s check what is going on in the code…

But before that I want to mention that since M1 a lot has changed in the frontend development. Now we have a require.js and knockout.js. Both introduce a fresh breeze into the M2. Of course, we still can use old libraries like jQuery or underscore but there are also new rules that each developer should follow. Those rules are recommended and requested by M2 developers as well.

For example, if you want to use jQuery you are no longer allowed to simply use it in script tag as follow:

According to Magento’s documentation each script should be added as a requirejs module. There are few different ways to do that however I will not discuss them here. The easiest way is to require jQuery as a module in the phtml file:

Now we have access to the library and we can use it. In common language this code above says: get jQuery library and inject it as a $ variable.

Easy as that. So as a developers we are not allowed anymore to simply include jQuery as a script. You can find more about this topic in the original documentation.

Now let’s go back to our problem. Something is wrong with jQuery library and we have to find what.

After a while of searching the answer I found that print functionality is hiding in the module-theme/view/frontend/templates/html/print.phtml

We are slowly opening the chest and the prize for our curiosity is… the heck? What’s that?

I am sure that you are wiping tears now along with me. This code is so ancient and its origin is the M1 itself. But now I got the point. jQuery should not be accessible in global scope and therefore this code should always generate an error. But it happens only from time to time.

The fun part is that the jQuery actually IS available in global scope which violate basic rules and to be frankly I am not even sure why.

Ok… we found the beast, can we kill it?

Do we need the jQuery wrapper here? In this case it works like a document.ready() method so it is good to have it because we want to print the page and we need to be sure that DOM is loaded.

The simplest solution is to overwrite the print.phtml template with the following code:

Now we are sure that before the execution our script will have access to jQuery. No more errors.

And as usual, you can find more detailed information about JavaScript in M2 on Alan’s Storm blog. I recommend to check it out so you will be able to tame the beast… eventually.

Also, if you know why jQuery is accessible in global scope eg. if we write something like jQuery(‘body’); in browser’s console even though it is not included as a script then let me know. We can share this curio.

Day saved. Let’s go home…