i-amdroid / material_base

Base theme for Drupal 7 & 8 inspirited by Material Design concept by Goggle
https://mb.4dd.pw/
24 stars 2 forks source link

Can't add body classes #3

Closed leeoocca closed 5 years ago

leeoocca commented 6 years ago

Hi. I tried to add body classes to a node by using different modules, but any of them seemed to work. The only one that actually changed something, applied the classes to the whole website.

Do you have any tips on how to solve this?

Thank you :)

i-amdroid commented 6 years ago

Hi, sure.

Which Drupal version do you use?

In Drupal 7 Context module can handle it.

In Drupal 8 I prefer to use theme functions. In YOURTHEME.theme add something like this:

/**
 * Implements hook_preprocess_HOOK() for HTML document templates.
 */
function YOURTHEME_preprocess_html(&$variables) {
  // Add class to all pages
  $variables['attributes']['class'][] = 'class-for-all-pages';

  if (\Drupal::service('path.matcher')->isFrontPage()) {
    $variables['attributes']['class'][] = 'front';
  } else {
    $variables['attributes']['class'][] = 'not-front';
  }

  // Add page alias as body class 
  $current_path = \Drupal::service('path.current')->getPath();
  $path_alias = \Drupal::service('path.alias_manager')->getAliasByPath($current_path);
  $path_alias = ltrim($path_alias, '/');
  $variables['attributes']['class'][] = 'page-' . \Drupal\Component\Utility\Html::cleanCssIdentifier($path_alias);

}
leeoocca commented 6 years ago

First of all, thank you for your quick reply. 👍

Since I'm new to Drupal I want to ask you if I understood this correctly.

If I want for example to add the class "no-sidebars" to the body of the front page, is this code correct?

function material_cascade_preprocess_html(&$variables) {
  if (\Drupal::service('path.matcher')->isFrontPage()) {
    $variables['attributes']['no-sidebars'][] = 'front';
  }
}

Thank you again :)

i-amdroid commented 6 years ago

Not exactly. The class name should go as array item value.

if (\Drupal::service('path.matcher')->isFrontPage()) {
  $variables['attributes']['class'][] = 'no-sidebars';
}
leeoocca commented 6 years ago

Thank you very much for your help so far. But still I have to ask you a couple more things.

  1. Everything seems to be working except the 'no-sidebars' and 'navbar-fixed' classes on the front page. I added them through the ***.theme file.

  2. Oh, and some classes I added to all the pages, are not applied to the front one. I tried to add the 'navbar-fixed' class globally, but it wasn't shown in the front one.

  3. How can I add a search bar in the navbar?

Thank you again for your help :)

i-amdroid commented 6 years ago

Hi.

1, 2. Paste your .theme file here so I can check.

  1. Put search block in the navbar region and add some classes to this block, for example 'navbar-item block-search search-persistent'
leeoocca commented 6 years ago
  1. The only thing I can't enable is the no-sidebars class. Here's my _materialcascade.theme file:
<?php

/**
 * @file
 * Functions to support theming in the theme.
 */

use Drupal\Core\Template\Attribute;

/**
 * Implements hook_preprocess_HOOK() for HTML document templates.
 */
function material_cascade_preprocess_html(&$variables) {
  // Add classes for apply colors.
  $variables['attributes']['class'][] = 'primary-indigo';
  $variables['attributes']['class'][] = 'accent-indigo';
  $variables['attributes']['class'][] = 'navbar-fixed';
  if (\Drupal::service('path.matcher')->isFrontPage()) {
    $variables['attributes']['class'][] = 'no-sidebars!important';
    $variables['attributes']['class'][] = 'header-bg-image';
    $variables['attributes']['class'][] = 'navbar-fixed';
    $variables['attributes']['class'][] = 'wide-one-side';
  }

  // Add page alias as body class
 $current_path = \Drupal::service('path.current')->getPath();
 $path_alias = \Drupal::service('path.alias_manager')->getAliasByPath($current_path);
 $path_alias = ltrim($path_alias, '/');
 $variables['attributes']['class'][] = 'page-' . \Drupal\Component\Utility\Html::cleanCssIdentifier($path_alias);
}
  1. Now the navbar-fixed class seems to be working.

  2. How can I make the search bar responsive? It doesn't show well on mobile. Is there a way to activate it by pressing a search button just in mobile view?

And also I noticed that

  1. the header-content has no opacity style. Only the header-bg fades away.

Thanks again 👍 You're the best 🥇

i-amdroid commented 6 years ago

First of all, you shouldn't ever use material_cascade name for your theme. You'll have conflicts or even errors with it. Copy your theme to themes folder and rename it and all relative parts.

  1. Why you place !important here $variables['attributes']['class'][] = 'no-sidebars!important'; ? It is wrong. Class name can't contain this.

  2. Great.

  3. Sure it is possible. Create custom block wth such content:

<div id="navbar-menu-toggle" ><a href="#"><i class="material-icons navbar-icon">menu</i></a></div>

Check that nothing is cropped by CKeditor.

Place block to navbar region, add this classes: navbar-item navbar-search-toggle hidden-md pull-right To search block add class visible-md

To CSS add:

#navbar-search-toggle { margin: 0 -12px; }

.navbar-search-open {
  .navbar-item { display: none !important; }
  .navbar-item.block-search { display: block !important; margin-left: auto; margin-right: auto; float: none; }
}

To custom.js add:

// navbar-search
$("#navbar-search-toggle").click(function (e) {
  $('body').addClass('navbar-search-open');
  $("#edit-key").focus();
  e.stopPropagation();
  e.preventDefault();
});

$('#edit-key').blur(function() {
  $("body").removeClass('navbar-search-open');
});

#edit-key should be replaced by your selector corresponds to search input element.

Working example https://naperstok.net/ but here I used search api instead default search.

  1. Add/replace this code in custom.js:
//header-bg-image navbar-fixed
var header = $('#header');
var headerHeight = header.outerHeight();
//var headerBg = $('.header-bg-video.navbar-fixed #header-bg');
var headerBg = $('.navbar-fixed #header-bg');
var headerCnt = $('.navbar-fixed #header-content');
var navbar = $('.navbar-fixed #navbar');
var headerBgHeight = headerHeight - 192;

$(document).scroll(function(e){
  var scrollPercent = (headerBgHeight - window.scrollY) / headerBgHeight;
  if(scrollPercent >= 0){
    headerBg.css('opacity', scrollPercent);
    headerCnt.css('opacity', scrollPercent);
  }
  if(window.scrollY > headerHeight - 128){
    navbar.addClass('navbar-bg');
  }
  else {
    navbar.removeClass('navbar-bg');
  }
  if(window.scrollY > headerHeight - 64){
    navbar.addClass('navbar-shadow');
  }
  else {
    navbar.removeClass('navbar-shadow');
  }
});
leeoocca commented 6 years ago
  1. Which folders from the main theme should I copy? Do I have to change just the name of the files and of the folder or something else, too?

  2. I was just trying to work it out. I had already tried just by typing no-sidebars but it hadn't worked. And it's not working now... I can see the no-sidebars class on the site, but since one-sidebar it's still there, the page doesn't show as it should.

  3. (A) I've decided to keep the toggle on the desktop version, too. Should I just add navbar-item navbar-search-toggle pull-right classes to the Search toggle block and navbar-item block-search search-persistent to the Search form?

  4. (B) How and where should I replace #edit-key? I hope the JavaScript isn't working because of that... I will just copy my custom.js and my custom.css so maybe you can check if I got something wrong.

(function ($) {
  $(document).ready(function() {

    // navbar-search
    $("#navbar-search-toggle").click(function (e) {
      $('body').addClass('navbar-search-open');
      $("#edit-key").focus();
      e.stopPropagation();
      e.preventDefault();
    });

    $("#actions-toggle").click(function (e) {
      e.stopPropagation();
      e.preventDefault();
    });

    $("#actions-search-toggle").click(function (e) {
      $('body').addClass('navbar-search-open');
      $("#edit-key").focus();
      e.stopPropagation();
      e.preventDefault();
    });

    $('#edit-key').blur(function() {
      $("body").removeClass('navbar-search-open');
    });

  }); 
})(jQuery);

(function ($) {
  $(document).ready(function () {

      //header-bg-image navbar-fixed
      var header = $('#header');
      var headerHeight = header.outerHeight();
      //var headerBg = $('.header-bg-video.navbar-fixed #header-bg');
      var headerBg = $('.navbar-fixed #header-bg');
      var headerCnt = $('.navbar-fixed #header-content');
      var navbar = $('.navbar-fixed #navbar');
      var headerBgHeight = headerHeight - 192;

      $(document).scroll(function(e){
          var scrollPercent = (headerBgHeight - window.scrollY) / headerBgHeight;
          if(scrollPercent >= 0){
              headerBg.css('opacity', scrollPercent);
              headerCnt.css('opacity', scrollPercent);
          }
          if(window.scrollY > headerHeight - 128){
              navbar.addClass('navbar-bg');
          }
          else {
              navbar.removeClass('navbar-bg');
          }
          if(window.scrollY > headerHeight - 64){
              navbar.addClass('navbar-shadow');
          }
          else {
              navbar.removeClass('navbar-shadow');
          }
      });
  });
}(jQuery));
#navbar-search-toggle {
    margin: 0 -12px}
.navbar-search-open .navbar-item {
    display: none}
.navbar-search-open .navbar-item .block-search {
    display: block;
    margin-left: auto;
    margin-right: auto;
    float: none}
  1. Same, I don't notice it working. If you may, check the custom.js above and tell me if I did something wrong.

Thanks again :)

i-amdroid commented 6 years ago
  1. In general, you should copy folder themes/material_base/starterkits/material_cascade, rename it for example to supertheme and place it like themes/supertheme Also, all appearings of material_cascade should be replaced by supertheme, including filenames and file contents.

  2. I think now, why you need it at all? classes no-sidebars, one-sidebar and two-sidebar adds automatically by material base theme when you have or haven't placed something in sidebars region.

  3. (A) Almost right but search form block should also have class hidden.

  4. (B) You should do it in your javascript code in custom.js. The right value which should be placed instead #edit-key you can find in browser developer tools, locate your search form and get some class or id from input element. Unfortunately, I don't remember standard search input id value.

  5. Use only one ready function definition

(function ($) {
  $(document).ready(function () {

  // code for header

  // code for search

  });
}(jQuery));