2

My THEME.info.yml file reads:

name: 'name'
type: theme
description: 'description'
core: 8.x
base theme: stark
screenshot: images/image.png
libraries:
  - THEME/navbar

and my THEME.libraries.yml reads:

navbar:
  css:
    theme:
      css/navbar.css: {}
  js:
    js/scrolling.js: {}
  dependencies:
    - core/jquery

From all the guides I've found online, this should mean that navbar.css and scrolling.js get included on all pages that use the theme. But that isn't happening. What have I done wrong here, or what steps do I need to take to figure out why it isn't working?


In case it's relevant, the file structure is:

drupal_root
    themes
        custom
            THEME
                css
                    navbar.css
                js
                    scrolling.js
                images
                    image.png
                THEME.info.yml
                THEME.libraries.yml
                THEME.theme

The jQuery code in scrolling.js is just:

$(window).on("scroll", function() {
  if ($(this).scrollTop() > 50) {
    document.getElementById("logo").style.width = '150px';
    document.getElementById("logo").style.marginTop = '0px';
  } else {
    document.getElementById("logo").style.width = '300px';
    document.getElementById("logo").style.marginTop = '20px';
  }
});

When I manually add

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript" src="{{ theme_path }}/js/scrolling.js"></script>
<link rel="stylesheet" href="{{ theme_path }}/css/navbar.css">

to the top of html.html.twig everything works fine. But as I understand it, this is not considered the proper way of going about things, so if possible I'd prefer to do it using libraries.


The extremely helpful comment added by (I think) Ivan Jaros which was unfortunately and rather rudely removed helped me to find that I needed to add <head-placeholder token="{{ placeholder_token|raw }}">, <css-placeholder token="{{ placeholder_token|raw }}"> and <js-placeholder token="{{ placeholder_token|raw }}"> to my html.html.twig file. This helped somewhat: it's now including the CSS file. However:

  1. It didn't manage to include the js file, for whatever reason.

  2. The head-placeholder token is mostly useful, but seems to be overriding the favicon that I had already specified. Is there a way to keep the other stuff it gives without the link rel="shortcut icon" that it's including from core?

1
  • Comments have been removed. Please don't use them as extended discussion. Add any relevant information in the question itself.
    – avpaderno
    Commented Dec 4, 2015 at 11:26

3 Answers 3

1

In D8 believe you need to wrap your code around this tags in order for Drupal to recognize it.

(function ($, Drupal, window) {

 // code goes here

})(jQuery, Drupal, window);

So try

(function ($, Drupal, window) {
   $(window).on("scroll", function() {
     if ($(this).scrollTop() > 50) {
       document.getElementById("logo").style.width = '150px';
       document.getElementById("logo").style.marginTop = '0px';
     } else {
       document.getElementById("logo").style.width = '300px';
       document.getElementById("logo").style.marginTop = '20px';
     }
   });
})(jQuery, Drupal, window);
5
  • 1
    His files are not being included.
    – user21641
    Commented Dec 4, 2015 at 8:45
  • he still needs to use the correct jQuery format...
    – No Sssweat
    Commented Dec 4, 2015 at 8:50
  • 1
    When I include the files by manually putting them in the html.html.twig file, it all works as expected. Ivan Jaros is correct that the problem seems to be that the css and js files are not being included for whatever reason. Putting that wrapper around the js file (while including it manually, at least) actually seems to make it stop working. EDIT: Though, at least for the moment, the navbar is also being manually included in the page.html.twig file. I plan to figure out how to include it in a more modular way in the future, and perhaps your syntax will be necessary then.
    – Jim Cullen
    Commented Dec 4, 2015 at 8:50
  • @NoSssweat For some reason, your code here seems to stop things working in Firefox and Safari, but removing those lines makes it not work in Chrome…
    – Jim Cullen
    Commented Dec 8, 2015 at 8:40
  • Never mind. When I use the code as shown above, I get "ReferenceError: Can't find variable: Drupal" in Safari and "ReferenceError: Drupal is not defined" in Firefox. When I remove those lines and go with what I originally had, Chrome gives "Uncaught TypeError: $ is not a function". However, wrapping in simply "(function ($) {" and "})(jQuery);" works just fine.
    – Jim Cullen
    Commented Dec 8, 2015 at 9:08
1

To get the CSS to appear, I needed to put <css-placeholder token="{{ placeholder_token|raw }}"> into the html.html.twig file's header. For JavaScript, <js-placeholder token="{{ placeholder_token|raw }}"> seems to add some useless cruft, and the actual JavaScript created added to the library (including the jQuery dependency) is inserted in through <js-bottom-placeholder token="{{ placeholder_token|raw }}">, which goes at the bottom of the body of the page.

<head-placeholder token="{{ placeholder_token|raw }}"> adds some useful metadata, but was overriding my custom favicons. Moving it up to the top above where I had defined the favicons seems to have fixed this.

To get the JavaScript to work in all browsers, it needed to be wrapped in (function ($) { and })(jQuery);, so my full JS code ended up as:

(function ($) {
  $(window).on("scroll", function() {
    if ($(this).scrollTop() > 50) {
      document.getElementById("logo").style.width = '150px';
      document.getElementById("logo").style.marginTop = '0px';
    } else {
      document.getElementById("logo").style.width = '300px';
      document.getElementById("logo").style.marginTop = '20px';
    }
  });
})(jQuery);

Without wrapping it, it didn't work in anything but Chrome, but with the wrapping as suggested by @No Sssweat, it worked in everything but Chrome.

1
  • 2
    If you are interested in why the wrapping is needed (it is typically called "an anonymous closure with global imports"), Drupal 7 and later use jQuery.noConflict() to avoid clashes with the $ variable. The jQuery object is passed in so it can be renamed to the normal $ and also to limit polluting the global namespace in the loaded file.
    – mpdonadio
    Commented Dec 9, 2015 at 2:27
0

If you want to add your custom css or any custom js for global then you should add this into global libraries.For better understanding please follow the theme instructions. Theme Instructions Drupal 8

global-css: css: theme: css/style.css: {}

After Changing in libraires then i have put into hook_preprocess_page in my themename.theme file as given below:

function MYTHEMENAME_preprocess_page(&$variables) {
 if ($variables['is_front']) {
 $variables['#attached']['library'][] = 'mycustompopup/fancybox/lib/jquery.mousewheel-3.0.6.pack.js';
 $variables['#attached']['library'][] = 'mycustompopup/fancybox/source/jquery.fancybox.css';
 $variables['#attached']['library'][] = 'mycustompopup/fancybox/source/jquery.fancybox.pack.js';
}
}   
2
  • I've used that guide rather extensively for learning. I was of the understanding that the names he used: global-css and global-js were just names with no particular semantic significance, and that it was the inclusion of them under libraries: in the info.yml file that made them work globally. Even so, I just tried changing the names to match his (just in case), and that still didn't work.
    – Jim Cullen
    Commented Dec 4, 2015 at 8:59
  • I have update my answer please check it.. it will work in my case Commented Dec 4, 2015 at 11:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.