scss Twig / SASS / JS中的可访问下拉菜单(Wordpress / Timber-oriented)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了scss Twig / SASS / JS中的可访问下拉菜单(Wordpress / Timber-oriented)相关的知识,希望对你有一定的参考价值。

<?php

/* Returns an array with various PHP/Timber data for inserting into JS
*/


function script_data() {
  $script_data = array(
    'ajaxurl' => admin_url( 'admin-ajax.php' ),
    'mainmenu_icon_submenu' => Timber::compile_string("{% include 'partials/image-svg-sprite.twig' with {'id': 'arrow_down_med', 'classes': ['u-svg-arrow_down_med-size', 'c-main-menu__link-submenu-icon'], 'theme_link': theme_link} %}", array('theme_link' => get_template_directory_uri())),
    'mainmenu_icon_hamburger' => Timber::compile_string("{% include 'partials/image-svg-sprite.twig' with {'id': 'hamburger', 'classes': ['u-svg-hamburger-size', 'c-header__togglebutton-icon'], 'theme_link': theme_link} %}", array('theme_link' => get_template_directory_uri())),
  );
  return $script_data;
}
{
  "name": "package",
  "version": "1.0.0",
  "dependencies": {
    "focus-trap": "^2.3.0",
  }
}
{# 
  Item classes legend:
  __item — all items
  __subitem — all items on 2nd and deeper levels
  __level-x-item -- all items on specific level
#}

{% if menu %}
  {% spaceless %}
    {% set listclass = [] %}
    {% if is_submenu is defined and is_submenu == true %}
      {% set listclass = listclass|merge([ baseclass ~ '__submenu' ]) %}
      {% set first_subitem = menu|first %}
      {% set listclass = listclass|merge([ baseclass ~ '__menu_level-' ~ (first_subitem.level + 1) ]) %}
    {% else %}
      {% set listclass = listclass|merge([ baseclass ~ '__list', baseclass ~ '__menu_level-1' ]) %}
    {% endif %}
    
    <ul class="{{ listclass | join(' ') }}">
    {% for item in menu %}
      
      {# {% set itemclasses = item.classes %} #}
      {% set itemclasses = [] %}
      
      {% if is_submenu is defined and is_submenu == true %}
        {% set itemclasses = itemclasses|merge([ baseclass ~ '__item', baseclass ~ '__subitem', baseclass ~ '__item_level-' ~ (item.level + 1) ]) %}
      {% else %}
        {% set itemclasses = itemclasses|merge([ baseclass ~ '__item', baseclass ~ '__item_level-1' ]) %}
        {% if item_level_1_classes is defined %}
          {% set itemclasses = itemclasses|merge([item_level_1_classes]) %}
        {% endif %}
      {% endif %}

      {% if item.current %}
        {% set itemclasses = itemclasses|merge([ baseclass ~ '__item_current' ]) %}
      {% endif %}

      {% if item.current_item_parent %}
        {% set itemclasses = itemclasses|merge([ baseclass ~ '__item_current-parent' ]) %}
      {% endif %}

      {% if item.get_children %}
        {% set itemclasses = itemclasses|merge([ baseclass ~ '__item_has-submenu' ]) %}
      {% endif %}
      
      <li class="{{ itemclasses | join(' ') }}">
        <a class="{{ baseclass }}__link"{{ item.get_children ? ' aria-haspopup="true"' }} href="{{item.get_link}}">{{item.title}}</a>
        {% include 'partials/menu.twig' with {'menu':item.get_children, is_submenu:true } %}
      </li>
    {% endfor %}
    </ul>
  {% endspaceless %}
{% endif %}
'use strict';

/**
 * Main menu
 */
function init() {

  // !Set vars
  var overlay_sel = '[data-overlay]';
  var focus_trap = require('../../node_modules/focus-trap');
  // initiate focus trap for the overlay
  var focus_trap_overlay = focus_trap(overlay_sel, {
    clickOutsideDeactivates:true,
    escapeDeactivates:false
  });


  var menu_sets = [
    {
      nav_class:'c-main-menu',
      header_class:'c-header',
      container_outer_class:'c-header__menu-container-outer',
      container_inner_class:'c-header__menu-container-inner'
    }
  ];

  $.each(menu_sets, function(i, cl) {

    if ($('.' + cl.nav_class).length) {
      $('.' + cl.nav_class).each(function() {

        
        var $nav = $(this);
        var $header = $('.' + cl.header_class);
        var $menus_outer = $('.' + cl.container_outer_class);
        var $menus_inner = $('.' + cl.container_inner_class);


  // !Append HTML


        $menus_outer.append(`
          <button class="state-togglebutton-hamburger ${cl.header_class}__togglebutton" aria-haspopup="true" aria-expanded="false">` +
              script_data.mainmenu_icon_hamburger + 
            `</span>
          </button>
        `);

        $nav.find(`.${cl.nav_class}__item_level-1.${cl.nav_class}__item_has-submenu > .${cl.nav_class}__link`).each(function() {
          $(this).wrapInner(`<span class="${cl.nav_class}__link-inner"></span>`);
        });
        
        // add submenu icon
        $nav.find(`.${cl.nav_class}__item_level-1.${cl.nav_class}__item_has-submenu > .${cl.nav_class}__link`).append(script_data.mainmenu_icon_submenu);

        var $nav_button = $header.find(`.${cl.header_class}__togglebutton`);

        $menus_inner.attr('aria-hidden', 'true');
        
        // the component may be styled now!
        $nav.addClass('js-component-ready');



  // !Events
        
        // close by clicking elsewhere
        $(document).on('click touchstart', function(e) {
          if ($menus_outer.is('.is-menu-overlay-open')) {
            if (
              !$(e.target).closest($menus_inner).length && 
              !$(e.target).closest(`.${cl.header_class}__togglebutton`).length
            ) {
              e.preventDefault();
              toggle_overlay($nav_button, $menus_outer, $menus_inner, 'close');
            }
          }
        });


        // toggle by clicking hamburger button
        $menus_outer.on('click', `.${cl.header_class}__togglebutton`, function() {
          
          if ($(this).hasClass('state-togglebutton-hamburger')) {
            toggle_overlay($nav_button, $menus_outer, $menus_inner, 'open');
          } else if ($(this).hasClass('state-togglebutton-close')) {
            toggle_overlay($nav_button, $menus_outer, $menus_inner, 'close');
          }
        });


        // open submenus with click when mobile
        $header.on('click', `
          .is-menu-overlay-open 
            .${cl.nav_class}__item_level-1.${cl.nav_class}__item_has-submenu 
              > .${cl.nav_class}__link
        `, function(e) {
          if (!$(e.target).closest(`.${cl.nav_class}__link-inner`).length) {
            e.preventDefault();
            if ($(this).parent().hasClass(`${cl.nav_class}__item_has-submenu-displayed`)) {
              $(this).parent().removeClass(`${cl.nav_class}__item_has-submenu-displayed`);
            } else {
              $nav.find(`.${cl.nav_class}__item_has-submenu-displayed`).removeClass(`${cl.nav_class}__item_has-submenu-displayed`);
              $(this).parent().addClass(`${cl.nav_class}__item_has-submenu-displayed`);
            }
          }
        });

        
        // open submenus with hover/focus when desktop
        var menu_desktop_sel = `.${cl.container_outer_class}:not(.is-menu-overlay-open)`;
        var toggle_class = `${cl.nav_class}__item_has-submenu-displayed`;
        var link_with_submenu_sel = `${menu_desktop_sel} 
            .${cl.nav_class}__item_level-1.${cl.nav_class}__item_has-submenu 
              > .${cl.nav_class}__link`;
        var submenu_sel = `${menu_desktop_sel} 
            .${cl.nav_class}__item_level-1.${cl.nav_class}__item_has-submenu 
              > .${cl.nav_class}__submenu`;
        var open_items_sel = `${menu_desktop_sel} 
            .${cl.nav_class}__item_has-submenu-displayed`;

        $header.on('mouseenter focusin', link_with_submenu_sel, function(e) {
          $header.find(open_items_sel).removeClass(`${toggle_class}`);
          $(this).parent().addClass(`${toggle_class}`);
        });
        $header.on('mouseleave', link_with_submenu_sel, function(e) {
          $(this).parent().removeClass(`${toggle_class}`);
        });
        $header.on('mouseenter', submenu_sel, function(e) {
          $(this).parent().addClass(`${toggle_class}`);
        });
        $header.on('mouseleave', submenu_sel, function(e) {
          $(this).parent().removeClass(`${toggle_class}`);
        });
        $header.on('focusin', submenu_sel, function(e) {
          $(this).parent().addClass(`${toggle_class}`);
        });


        // close overlay with Esc key
        $(document).on('keyup', function(e) {
          if (
            e.which === 27 && 
            $menus_outer.hasClass('is-menu-overlay-open')
          ){
            toggle_overlay($nav_button, $menus_outer, $menus_inner, 'close');
          }
        });

      });
    }


  });



  // !Functions

  function toggle_overlay($nav_button, $menus_outer, $menus_inner, action) {
    switch(action) {
      case 'open':
        $menus_outer.addClass('is-menu-overlay-open');
        $menus_inner.attr('aria-hidden', 'false');
        $nav_button
          .attr('aria-expanded', 'true')
          .addClass('state-togglebutton-close').removeClass('state-togglebutton-hamburger');
        focus_trap_overlay.activate();
        break;
      case 'close':
        $menus_outer.removeClass('is-menu-overlay-open');
        $menus_inner.attr('aria-hidden', 'true');
        $nav_button
          .attr('aria-expanded', 'false')
          .addClass('state-togglebutton-hamburger').removeClass('state-togglebutton-close');
        focus_trap_overlay.deactivate();
        break;
    }
  }



  // !Append HTML




  // !Events
        



  // !Functions



}

module.exports = {
  init: init
};
// @z-index space: 110-120
@mixin c-main-menu($base:&) {

  $local-item-spacing-x:28px;
  $local-menu-desktop-shift-y:17px;

  & {
    @include mq($until: mainmenu-horizontalized) { 
      padding-top:36px;
    }
    @include mq($from: mainmenu-horizontalized) { 
      padding-top:15px; 
    }
    @include mq($from: xlarge) { 
      padding-top:30px; 
    }
  }

  @at-root {
    #{$base}__item_level-1 {
      & > #{$base}__link {
      }
      #{$base}__submenu {
        display:none; 
      }
    }
    // never display 3rd, 4th etc menu levels 
    #{$base}__item_level-2 {
      #{$base}__submenu {
        display:none; 
      }
      & > #{$base}__link {
      }
    }
    #{$base}__item_has-submenu-displayed {
      & > #{$base}__submenu {
        display:block; 
      }
    }
    #{$base}__link {
      display:block; 
    }

    // mobile 
    @include mq($until: mainmenu-horizontalized) { 
      #{$base}__link-submenu-icon {
        position:absolute; 
      }
      #{$base}__item_level-1#{$base}__item_has-submenu {
        & > #{$base}__link {
          &:hover {
            text-decoration:none; 
          }
          & > #{$base}__link-inner {
            &:hover {
              text-decoration:underline; 
            }
          }
        }
      }
      #{$base}__item_has-submenu-displayed {
        #{$base}__link-submenu-icon {
          transform:scaleY(-1);
        }
      }
      #{$base}__menu_level-2 {
      }
      #{$base}__item_level-2 {
        @include u-spacing-y(8px);
        & > #{$base}__link {
          &:focus {
            outline:white 1px dotted;
          }
        }
      }
    }

    // desktop 
    @include mq($from: mainmenu-horizontalized) { 
      #{$base}__item_current,
      #{$base}__item_current-parent {
        & > #{$base}__link {
          color:$color-link; 
        }
      }
      #{$base}__link-submenu-icon {
        position:absolute; 
      }
      #{$base}__list {
        @include u-spacing-x(-$local-item-spacing-x, margin);
      }
      #{$base}__item_level-1 {
        flex:1 1 auto;
        & > #{$base}__link {
          @include u-spacing-x($local-item-spacing-x);
          padding-top:26px; 
          padding-bottom:28px; 
          white-space:nowrap; 
        }
      }
      #{$base}__menu_level-2 {
        text-align:left; 
        position:absolute; 
        min-width:200px; 
        max-width:300px; 
        z-index:112; 
      }
      #{$base}__item_has-submenu-displayed {
        & > #{$base}__link {
          box-shadow:$box-shadow; 
          background-color:white; 
          z-index:111; 
        }
      }
      #{$base}__item_level-2 {
        & > #{$base}__link {
          border-top:#f2f2f2 1px solid; 
          @include u-spacing-y(20px);
          font-weight:normal; 
        }
        &:first-child > #{$base}__link {
          border-top:none; 
        }
      }
    }
  }
}
// @z-index space: 100-110
.c-header {

  $local-spacing-top:10px;

  @include t-page-wrapper;
  padding-top:$local-spacing-top; 
  display:flex;
  &__logo {
    @include mq($until: mainmenu-horizontalized) {
      @include u-spacing-x(auto, margin);
    }
    @include mq($from: mainmenu-horizontalized) {
      flex:0 1 auto;
    }
    @include mq($from: large, $until: xlarge) {
      padding-top:14px; 
    }
    &-image {
      width:177px; 
      @include mq($from: medium) {
        width:239px; 
      }
      @include mq($from: large) {
        width:170px; 
      }
      @include mq($from: xlarge) {
        width:250px; 
      }
      display:block; 
      max-width:100%;
      height:auto;  
    }
  }
  &__menu {
    @include mq($from: mainmenu-horizontalized) { 
      margin-left:5.4%; 
      flex:1 1 100%;
    }
  }
  &__menu-container-outer {
    @include mq($from: mainmenu-horizontalized) { 
      flex:1 1 100%;
    }
  }
  &__menu-container-inner {
    display:none; 
    .is-menu-overlay-open & {
      display:block; 
    }
    @include mq($until: mainmenu-horizontalized) { 
      background-color:white; 
      width:span(7); 
      text-align:center; 
      position:fixed; 
      overflow-y:auto; 
      -webkit-overflow-scrolling: touch;
      height:100%; 
      right:0; 
      top:0; 
      box-shadow:-10px 0 20px 0 rgba(0, 0, 0, 0.2);
      z-index:100; 
    }
    @include mq($until: small) { 
      width:100%; 
    }
    @include mq($from: mainmenu-horizontalized) { 
      display:block; 
    }
  }
  &__togglebutton {
    @include u-remove-button-styling;
    z-index:101;
    fill:$color-sand-brown; 
    display:none; 
    @include mq($until: mainmenu-horizontalized) { 
      display:block; 
      position:absolute; 
      right:17px; 
      &.state-togglebutton-close {
        position:fixed; 
        top:$local-spacing-top; 
      }
    }
  }
  &__togglebutton-icon {
    display:block; 
  }
}

以上是关于scss Twig / SASS / JS中的可访问下拉菜单(Wordpress / Timber-oriented)的主要内容,如果未能解决你的问题,请参考以下文章

Vue js 和 scss 或 Sass

如何使用js更改sass文件中的变量

将 json 数据作为 .scss 文件中的 sass 变量导入 Nuxt

Vue 融入flexible.js scss(sass)文件 添加scss文件 sass

SCSS 在 Vue JS 中无需 SASS-loader 即可工作

我的 .scss 文件出现 Vue.js webpack sass-loader 问题