Commit c24e354c by lmf

Merge branch 'haowei/topmenu' into developer

parents b4b945f6 3d3b7581
...@@ -9,7 +9,6 @@ static ...@@ -9,7 +9,6 @@ static
errors errors
media media
opt opt
code
/app/etc/env.php /app/etc/env.php
generated generated
var var
......
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Joshine\Category\Block\Html;
use Magento\Framework\Data\Tree\Node;
use Magento\Framework\Data\Tree\Node\Collection;
use Magento\Theme\Block\Html\Topmenu as JoshineMenu;
/**
* Html page top menu block
*
* @api
* @since 100.0.2
*/
class Topmenu extends JoshineMenu
{
/**
* Remove children from collection when the parent is not active
*
* @param Collection $children
* @param int $childLevel
* @return void
*/
private function removeChildrenWithoutActiveParent(Collection $children, int $childLevel): void
{
/** @var Node $child */
foreach ($children as $child) {
if ($childLevel === 0 && $child->getData('is_parent_active') === false) {
$children->delete($child);
}
}
}
/**
* Retrieve child level based on parent level
*
* @param int $parentLevel
*
* @return int
*/
private function getChildLevel($parentLevel): int
{
return $parentLevel === null ? 0 : $parentLevel + 1;
}
/**
* Check if new column should be added.
*
* @param array $colBrakes
* @param int $counter
* @return bool
*/
private function shouldAddNewColumn(array $colBrakes, int $counter): bool
{
return count($colBrakes) && $colBrakes[$counter]['colbrake'];
}
protected function _getMenuItemClasses(\Magento\Framework\Data\Tree\Node $item)
{
$classes = [
'level' . $item->getLevel(),
$item->getPositionClass(),
];
if ($item->getIsCategory()) {
$classes[] = 'category-item';
}
if ($item->getIsFirst()) {
$classes[] = 'first';
}
if ($item->getIsActive()) {
$classes[] = 'active';
} elseif ($item->getHasActive()) {
$classes[] = 'has-active';
}
if ($item->getIsLast()) {
$classes[] = 'last';
}
if ($item->getClass()) {
$classes[] = $item->getClass();
}
if ($item->hasChildren()) {
$classes[] = 'parent';
}
if ($item->getLevel() != 0) {
$classes = $this->_getColumns($classes, $item);
}
return $classes;
}
private function _getColumns($classes, $item)
{
$parentSetMyColumns = $item->getParent()->getSubmenuColumnsSingle();
$selfColumns = $item->getSelfColumns();
$defaultColumns = '3';
if ($item->getLevel() > 1) {
$defaultColumns = '12';
}
$columns = ($selfColumns ?? $parentSetMyColumns) ?? $defaultColumns;
$classes[] = 'joshine-col-lg-'.$columns;
return $classes;
}
protected function _getHtml(
Node $menuTree,
$childrenWrapClass,
$limit,
array $colBrakes = []
) {
$html = '';
$children = $menuTree->getChildren();
$childLevel = $this->getChildLevel($menuTree->getLevel());
$this->removeChildrenWithoutActiveParent($children, $childLevel);
$counter = 1;
$childrenCount = $children->count();
$parentPositionClass = $menuTree->getPositionClass();
$itemPositionClassPrefix = $parentPositionClass ? $parentPositionClass . '-' : 'nav-';
/** @var Node $child */
foreach ($children as $child) {
$child->setLevel($childLevel);
$child->setIsFirst($counter === 1);
$child->setIsLast($counter === $childrenCount);
$child->setPositionClass($itemPositionClassPrefix . $counter);
$outermostClassCode = '';
$outermostClass = $menuTree->getOutermostClass();
if ($childLevel === 0 && $outermostClass) {
$outermostClassCode = ' class="' . $outermostClass . '" ';
$this->setCurrentClass($child, $outermostClass);
}
if ($this->shouldAddNewColumn($colBrakes, $counter)) {
$html .= '</ul></li><li class="column"><ul>';
}
$html .= '<li ' . $this->_getRenderedMenuItemAttributes($child) . '>';
$html .= '<a href="' . $child->getUrl() . '" ' . $outermostClassCode . '><span>' . $this->escapeHtml(
$child->getName()
) . '</span>'.$this->_addBadge($child).'</a>' . $this->_addSubMenu(
$child,
$childLevel,
$childrenWrapClass,
$limit
) . '</li>';
$counter++;
}
if (is_array($colBrakes) && !empty($colBrakes) && $limit) {
$html = '<li class="column"><ul>' . $html . '</ul></li>';
}
return $html;
}
private function _addBadge($child )
{
$badge = $child->getBadge();
if (!$badge || !json_decode($badge)) {
return "";
}
$json = json_decode($badge, true);
$class = $json['class'];
$text = $json['text'];
return "<span class='{$class}'>".$this->escapeHtml($text) .'</span>';
}
protected function _addSubMenu($child, $childLevel, $childrenWrapClass, $limit)
{
$html = '';
if (!$child->hasChildren()) {
return $html;
}
$colStops = [];
if ($childLevel == 0 && $limit) {
$colStops = $this->_columnBrake($child->getChildren(), $limit);
}
$sumMenuColumnsTotal = $child->getSubmenuColumnsTotal();
$columns = $sumMenuColumnsTotal ?? '12';
if ($childLevel == 0) {
$html = "<div class=\"level{$childLevel} {$childrenWrapClass}\">";
$html .= "<div class=\"row \">
<ul class=\"subchildmenu joshine-col-lg-push-1 mega-columns joshine-clearfix joshine-col-lg-{$columns} {$child->getMenuImage()}\">
{$this->_getHtml($child, $childrenWrapClass, $limit, $colStops)}
</ul>";
$html .= $this->appendImage($child);
$html .= "</div></div>";
} else {
$html .= '<ul class="level' . $childLevel . '">';
$html .= $this->_getHtml($child, $childrenWrapClass, $limit, $colStops);
$html .= '</ul>';
}
return $html;
}
private function appendImage($child)
{
$html = "";
if (!$child->getMenuImage()) {
return $html;
}
if ($child->getMenuImage()) {
$html .= "<div class=\" pull-right joshine-col-lg-3 joshine-col-lg-push-1 joshine-hidden-xs joshine-hidden-sm joshine-hidden-md \">";
$html .= "<img src='{$child->getMenuImage()}'/>";
$html .= "</div>";
}
return $html;
}
}
<?php
namespace Joshine\Category\Controller\Adminhtml\Category\Image;
use Magento\Framework\Controller\ResultFactory;
/**
* Class Upload
*/
class Upload extends \Magento\Backend\App\Action
{
protected $baseTmpPath;
protected $imageUploader;
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Catalog\Model\ImageUploader $imageUploader
) {
$this->imageUploader = $imageUploader;
parent::__construct($context);
}
public function execute() {
try {
$result = $this->imageUploader->saveFileToTmpDir('menu_image');
$result['cookie'] = [
'name' => $this->_getSession()->getName(),
'value' => $this->_getSession()->getSessionId(),
'lifetime' => $this->_getSession()->getCookieLifetime(),
'path' => $this->_getSession()->getCookiePath(),
'domain' => $this->_getSession()->getCookieDomain(),
];
} catch (\Exception $e) {
$result = ['error' => $e->getMessage(), 'errorcode' => $e->getCode()];
}
return $this->resultFactory->create(ResultFactory::TYPE_JSON)->setData($result);
}
}
\ No newline at end of file
<?php
namespace Joshine\Category\Model\Category\Attribute\Source;
use function Joshine\Model\Category\Attribute\Source\count;
class Badge extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
{
protected $_optionsData;
/**
* Constructor
*
* @param array $options
*/
public function __construct(array $options = [])
{
$this->_optionsData = $options;
}
/**
* getAllOptions
*
* @return array
*/
public function getAllOptions()
{
if (!$this->_optionsData) {
$this->_optionsData = [
['value' => '', 'label' => '----'],
['value' => json_encode(['text'=>'HOT!', 'class'=>'ui-menu-icon-3 ui-icon-3']), 'label' => 'Hot'],
['value' => json_encode(['text'=>'NEW!', 'class'=>'ui-menu-icon-1 ui-icon-1']), 'label' => 'New'],
['value' => json_encode(['text'=>'SALE!','class'=>'ui-menu-icon-2 ui-icon-2']), 'label' => 'Sale'],
];
}
return $this->_optionsData;
}
}
<?php
namespace Joshine\Category\Model\Category\Attribute\Source;
class Columns extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
{
protected $_optionsData;
/**
* Constructor
*
* @param array $options
*/
public function __construct(array $options = [])
{
$this->_optionsData = $options;
}
/**
* getAllOptions
*
* @return array
*/
public function getAllOptions()
{
if (!$this->_optionsData) {
$this->_optionsData = [
['value' => '', 'label' => '----'],
['value' => '1', 'label' => '1-columns'],
['value' => '2', 'label' => '2-columns'],
['value' => '3', 'label' => '3-columns'],
['value' => '4', 'label' => '4-columns'],
['value' => '5', 'label' => '5-columns'],
['value' => '6', 'label' => '6-columns'],
['value' => '7', 'label' => '7-columns'],
['value' => '8', 'label' => '8-columns'],
['value' => '9', 'label' => '9-columns'],
['value' => '10', 'label' => '10-columns'],
['value' => '11', 'label' => '11-columns'],
['value' => '12', 'label' => '12-columns'],
];
}
return $this->_optionsData;
}
}
\ No newline at end of file
<?php
namespace Joshine\Category\Model\Category;
class DataProvider extends \Magento\Catalog\Model\Category\DataProvider
{
protected function getFieldsMap()
{
$fields = parent::getFieldsMap();
$fields['content'][] = 'menu_image'; // custom image field
return $fields;
}
}
\ No newline at end of file
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace Joshine\Category\Plugin\Block;
use Magento\Catalog\Plugin\Block\Topmenu as Menu;
use Magento\Framework\Data\Collection;
use Magento\Framework\Data\Tree\Node;
/**
* Plugin for top menu block
*/
class Topmenu extends Menu
{
/**
* Catalog category
*
* @var \Magento\Catalog\Helper\Category
*/
protected $catalogCategory;
/**
* @var \Magento\Catalog\Model\ResourceModel\Category\StateDependentCollectionFactory
*/
private $collectionFactory;
/**
* @var \Magento\Store\Model\StoreManagerInterface
*/
private $storeManager;
/**
* @var \Magento\Catalog\Model\Layer\Resolver
*/
private $layerResolver;
/**
* Initialize dependencies.
*
* @param \Magento\Catalog\Helper\Category $catalogCategory
* @param \Magento\Catalog\Model\ResourceModel\Category\StateDependentCollectionFactory $categoryCollectionFactory
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
* @param \Magento\Catalog\Model\Layer\Resolver $layerResolver
*/
public function __construct(
\Magento\Catalog\Helper\Category $catalogCategory,
\Magento\Catalog\Model\ResourceModel\Category\StateDependentCollectionFactory $categoryCollectionFactory,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Catalog\Model\Layer\Resolver $layerResolver
) {
parent::__construct($catalogCategory, $categoryCollectionFactory, $storeManager, $layerResolver);
$this->collectionFactory = $categoryCollectionFactory;
$this->storeManager = $storeManager;
$this->layerResolver = $layerResolver;
}
/**
* Build category tree for menu block.
*
* @param \Magento\Theme\Block\Html\Topmenu $subject
* @param string $outermostClass
* @param string $childrenWrapClass
* @param int $limit
* @return void
* @SuppressWarnings("PMD.UnusedFormalParameter")
*/
public function beforeGetHtml(
\Magento\Theme\Block\Html\Topmenu $subject,
$outermostClass = '',
$childrenWrapClass = '',
$limit = 0
) {
$rootId = $this->storeManager->getStore()->getRootCategoryId();
$storeId = $this->storeManager->getStore()->getId();
/** @var \Magento\Catalog\Model\ResourceModel\Category\Collection $collection */
$collection = $this->getCategoryTree($storeId, $rootId);
$currentCategory = $this->getCurrentCategory();
$mapping = [$rootId => $subject->getMenu()]; // use nodes stack to avoid recursion
foreach ($collection as $category) {
$categoryParentId = $category->getParentId();
if (!isset($mapping[$categoryParentId])) {
$parentIds = $category->getParentIds();
foreach ($parentIds as $parentId) {
if (isset($mapping[$parentId])) {
$categoryParentId = $parentId;
}
}
}
/** @var Node $parentCategoryNode */
$parentCategoryNode = $mapping[$categoryParentId];
$categoryNode = new Node(
$this->getCategoryAsArray(
$category,
$currentCategory,
$category->getParentId() == $categoryParentId
),
'id',
$parentCategoryNode->getTree(),
$parentCategoryNode
);
$parentCategoryNode->addChild($categoryNode);
$mapping[$category->getId()] = $categoryNode; //add node in stack
}
}
/**
* Get current Category from catalog layer
*
* @return \Magento\Catalog\Model\Category
*/
private function getCurrentCategory()
{
$catalogLayer = $this->layerResolver->get();
if (!$catalogLayer) {
return null;
}
return $catalogLayer->getCurrentCategory();
}
/**
* Convert category to array
*
* @param \Magento\Catalog\Model\Category $category
* @param \Magento\Catalog\Model\Category $currentCategory
* @param bool $isParentActive
* @return array
*/
private function getCategoryAsArray($category, $currentCategory, $isParentActive)
{
$categoryId = $category->getId();
return [
'name' => $category->getName(),
'id' => 'category-node-' . $categoryId,
'url' => $this->catalogCategory->getCategoryUrl($category),
'badge' => $category->getData('badge'),
'submenu_columns_total' => $category->getData('submenu_columns_total'),
'self_columns' => $category->getData('self_columns'),
'submenu_columns_single' => $category->getData('submenu_columns_single'),
'menu_image' => $category->getData('menu_image'),
'has_active' => in_array((string)$categoryId, explode('/', (string)$currentCategory->getPath()), true),
'is_active' => $categoryId == $currentCategory->getId(),
'is_category' => true,
'is_parent_active' => $isParentActive
];
}
/**
* Get Category Tree
*
* @param int $storeId
* @param int $rootId
* @return \Magento\Catalog\Model\ResourceModel\Category\Collection
* @throws \Magento\Framework\Exception\LocalizedException
*/
protected function getCategoryTree($storeId, $rootId)
{
/** @var \Magento\Catalog\Model\ResourceModel\Category\Collection $collection */
$collection = $this->collectionFactory->create();
$collection->setStoreId($storeId);
$collection->addAttributeToSelect('name');
$collection->addAttributeToSelect('badge');
$collection->addAttributeToSelect('submenu_columns_total');
$collection->addAttributeToSelect('submenu_columns_single');
$collection->addAttributeToSelect('self_columns');
$collection->addAttributeToSelect('menu_image');
$collection->addFieldToFilter('path', ['like' => '1/' . $rootId . '/%']); //load only from store root
$collection->addAttributeToFilter('include_in_menu', 1);
$collection->addIsActiveFilter();
$collection->addNavigationMaxDepthFilter();
$collection->addUrlRewriteToResult();
$collection->addOrder('level', Collection::SORT_ORDER_ASC);
$collection->addOrder('position', Collection::SORT_ORDER_ASC);
$collection->addOrder('parent_id', Collection::SORT_ORDER_ASC);
$collection->addOrder('entity_id', Collection::SORT_ORDER_ASC);
return $collection;
}
}
<?php
namespace Joshine\Category\Setup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
class InstallData implements InstallDataInterface
{
private $eavSetupFactory;
public function __construct(EavSetupFactory $eavSetupFactory)
{
$this->eavSetupFactory = $eavSetupFactory;
}
public function install(
ModuleDataSetupInterface $setup,
ModuleContextInterface $context
)
{
$eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
$eavSetup->addAttributeGroup(
\Magento\Catalog\Model\Category::ENTITY,
$eavSetup->getDefaultAttributeSetId(\Magento\Catalog\Model\Category::ENTITY),
'Custom Menu',
99
);
$eavSetup->addAttribute(
\Magento\Catalog\Model\Category::ENTITY,
'badge',
[
'type' => 'varchar',
'label' => 'badge',
'input' => 'select',
'sort_order' => 100,
'source' => '\Joshine\Category\Model\Category\Attribute\Source\Badge',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
'visible_on_front' => true,
'required' => false,
'user_defined' => false,
'default' => null,
'group' => 'Custom Menu',
'backend' => ''
]
);
}
}
<?php
namespace Joshine\Category\Setup;
use Magento\Framework\Module\Setup\Migration;
use Magento\Framework\Setup\UpgradeDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Catalog\Setup\CategorySetupFactory;
/**
* Data migration:
* - Config Migration from version 2.0.1 JSON file store to 2.0.2+ Magento config way
*
*/
class UpgradeData implements UpgradeDataInterface
{
private $categorySetupFactory;
public function __construct(CategorySetupFactory $categorySetupFactory)
{
$this->categorySetupFactory = $categorySetupFactory;
}
/**
* Run data upgrade.
*
* @param ModuleDataSetupInterface $setup
* @param ModuleContextInterface $context
*/
public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
$setup->startSetup();
if (version_compare($context->getVersion(), '1.0.1') < 0) {
$categorySetup = $this->categorySetupFactory->create(['setup' => $setup]);
$entityTypeId = $categorySetup->getEntityTypeId(\Magento\Catalog\Model\Category::ENTITY);
$attributeSetId = $categorySetup->getDefaultAttributeSetId($entityTypeId);
$idg = $categorySetup->getAttributeGroupId($entityTypeId, $attributeSetId, 'Custom Menu');
$categorySetup->addAttribute(
\Magento\Catalog\Model\Category::ENTITY,
'menu_image',
[
'type' => 'varchar',
'label' => 'badge',
'visible_on_front' => true,
'user_defined' => false,
'default' => null,
'group' => 'Custom Menu',
'input' => 'image',
'backend' => 'Magento\Catalog\Model\Category\Attribute\Backend\Image',
'required' => false,
'sort_order' => 70,
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
]
);
$categorySetup->addAttributeToGroup(
$entityTypeId,
$attributeSetId,
$idg,
'menu_image',
1
);
}
$categorySetup = $this->categorySetupFactory->create(['setup' => $setup]);
$entityTypeId = $categorySetup->getEntityTypeId(\Magento\Catalog\Model\Category::ENTITY);
$attributeSetId = $categorySetup->getDefaultAttributeSetId($entityTypeId);
$menu_attributes = [
'submenu_columns_total' =>
[
'type' => 'varchar',
'label' => 'Submenu Columns Total',
'input' => 'select',
'sort_order' => 101,
'source' => '\Joshine\Category\Model\Category\Attribute\Source\Columns',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
'visible_on_front' => true,
'required' => false,
'user_defined' => false,
'default' => null,
'group' => 'Custom Menu',
'backend' => ''
],
'self_columns' =>
[
'type' => 'varchar',
'label' => 'self_columns',
'input' => 'select',
'sort_order' => 101,
'source' => '\Joshine\Category\Model\Category\Attribute\Source\Columns',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
'visible_on_front' => true,
'required' => false,
'user_defined' => false,
'default' => null,
'group' => 'Custom Menu',
'backend' => ''
],
'submenu_columns_single' =>
[
'type' => 'varchar',
'label' => 'Submenu Columns Single',
'input' => 'select',
'sort_order' => 101,
'source' => '\Joshine\Category\Model\Category\Attribute\Source\Columns',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
'visible_on_front' => true,
'required' => false,
'user_defined' => false,
'default' => null,
'group' => 'Custom Menu',
'backend' => ''
]
];
foreach($menu_attributes as $item => $data) {
$categorySetup->addAttribute(\Magento\Catalog\Model\Category::ENTITY, $item, $data);
}
$idg = $categorySetup->getAttributeGroupId($entityTypeId, $attributeSetId, 'Custom Menu');
foreach($menu_attributes as $item => $data) {
$categorySetup->addAttributeToGroup(
$entityTypeId,
$attributeSetId,
$idg,
$item,
$data['sort_order']
);
}
$setup->endSetup();
}
}
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Joshine\Category\Controller\Adminhtml\Category\Image\Upload">
<arguments>
<argument name="imageUploader" xsi:type="object">Magento\Catalog\CategoryImageUpload</argument>
</arguments>
</type>
<virtualType name="Magento\Catalog\CategoryImageUpload" type="Magento\Catalog\Model\ImageUploader">
<arguments>
<argument name="baseTmpPath" xsi:type="string">catalog/tmp/category</argument>
<argument name="basePath" xsi:type="string">catalog/category</argument>
<argument name="allowedExtensions" xsi:type="array">
<item name="jpg" xsi:type="string">jpg</item>
<item name="jpeg" xsi:type="string">jpeg</item>
<item name="gif" xsi:type="string">gif</item>
<item name="png" xsi:type="string">png</item>
</argument>
</arguments>
</virtualType>
</config>
\ No newline at end of file
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="admin">
<route id="categorylist" frontName="categorylist">
<module name="Joshine_Category" before="Magento_Backend" />
</route>
</router>
</config>
\ No newline at end of file
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Catalog\Plugin\Block\Topmenu" type="Joshine\Category\Plugin\Block\Topmenu" />
<preference for="Magento\Theme\Block\Html\Topmenu" type="Joshine\Category\Block\Html\Topmenu" />
</config>
<?xml version="1.0"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Joshine_Category" setup_version="1.1.2"/>
</config>
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Joshine_Category',
__DIR__
);
<?xml version="1.0" ?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<fieldset name="custom_menu">
<settings>
<collapsible>true</collapsible>
<label translate="false">Custom Menu</label>
</settings>
<field name="badge" sortOrder="300">
<argument name="data" xsi:type="array">
<item name="options" xsi:type="object">Joshine\Category\Model\Category\Attribute\Source\Badge</item>
<item name="config" xsi:type="array">
<item name="required" xsi:type="boolean">false</item>
<item name="validation" xsi:type="array">
<item name="required-entry" xsi:type="boolean">false</item>
</item>
<item name="dataType" xsi:type="string">string</item>
<item name="formElement" xsi:type="string">select</item>
<item name="label" translate="false" xsi:type="string">Badge</item>
</item>
</argument>
</field>
<field name="menu_image">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="dataType" xsi:type="string">string</item>
<item name="source" xsi:type="string">category</item>
<item name="label" xsi:type="string" translate="true">Menu Image</item>
<item name="visible" xsi:type="boolean">true</item>
<item name="formElement" xsi:type="string">imageUploader</item>
<item name="elementTmpl" xsi:type="string">ui/form/element/uploader/uploader</item>
<item name="previewTmpl" xsi:type="string">Magento_Catalog/image-preview</item>
<item name="required" xsi:type="boolean">false</item>
<item name="sortOrder" xsi:type="number">40</item>
<item name="uploaderConfig" xsi:type="array">
<item name="url" xsi:type="url" path="categorylist/category_image/upload"/>
</item>
</item>
</argument>
</field>
<field name="submenu_columns_total" sortOrder="300">
<argument name="data" xsi:type="array">
<item name="options" xsi:type="object">Joshine\Category\Model\Category\Attribute\Source\Columns</item>
<item name="config" xsi:type="array">
<item name="required" xsi:type="boolean">false</item>
<item name="validation" xsi:type="array">
<item name="required-entry" xsi:type="boolean">false</item>
</item>
<item name="dataType" xsi:type="string">string</item>
<item name="formElement" xsi:type="string">select</item>
<item name="label" translate="false" xsi:type="string">Submenu Columns Total</item>
</item>
</argument>
</field>
<field name="self_columns" sortOrder="300">
<argument name="data" xsi:type="array">
<item name="options" xsi:type="object">Joshine\Category\Model\Category\Attribute\Source\Columns</item>
<item name="config" xsi:type="array">
<item name="required" xsi:type="boolean">false</item>
<item name="validation" xsi:type="array">
<item name="required-entry" xsi:type="boolean">false</item>
</item>
<item name="dataType" xsi:type="string">string</item>
<item name="formElement" xsi:type="string">select</item>
<item name="label" translate="false" xsi:type="string">Self Columns</item>
</item>
</argument>
</field>
<field name="submenu_columns_single" sortOrder="300">
<argument name="data" xsi:type="array">
<item name="options" xsi:type="object">Joshine\Category\Model\Category\Attribute\Source\Columns</item>
<item name="config" xsi:type="array">
<item name="required" xsi:type="boolean">false</item>
<item name="validation" xsi:type="array">
<item name="required-entry" xsi:type="boolean">false</item>
</item>
<item name="dataType" xsi:type="string">string</item>
<item name="formElement" xsi:type="string">select</item>
<item name="label" translate="false" xsi:type="string">Submenu Columns Single(will overwrite by Self Columns)</item>
</item>
</argument>
</field>
</fieldset>
</form>
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
* Copyright © Magento, Inc. All rights reserved. * Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details. * See COPYING.txt for license details.
*/ */
namespace Magento\Theme\Block\Html; namespace Magento\Theme\Block\Html;
use Magento\Backend\Model\Menu; use Magento\Backend\Model\Menu;
...@@ -58,8 +57,7 @@ class Topmenu extends Template implements IdentityInterface ...@@ -58,8 +57,7 @@ class Topmenu extends Template implements IdentityInterface
NodeFactory $nodeFactory, NodeFactory $nodeFactory,
TreeFactory $treeFactory, TreeFactory $treeFactory,
array $data = [] array $data = []
) ) {
{
parent::__construct($context, $data); parent::__construct($context, $data);
$this->nodeFactory = $nodeFactory; $this->nodeFactory = $nodeFactory;
$this->treeFactory = $treeFactory; $this->treeFactory = $treeFactory;
...@@ -194,169 +192,9 @@ class Topmenu extends Template implements IdentityInterface ...@@ -194,169 +192,9 @@ class Topmenu extends Template implements IdentityInterface
$colStops = $this->_columnBrake($child->getChildren(), $limit); $colStops = $this->_columnBrake($child->getChildren(), $limit);
} }
$name = $child->getData('name'); $html .= '<ul class="level' . $childLevel . ' ' . $childrenWrapClass . '">';
$name = strtoupper($name);
if ($name == 'BODYSUITS' || $name == 'SUPERDEAL' || $name == 'CONTROL PANTIES' || $name == 'CONTROL PANTIES' || $name == 'CORSETS& WAIST TRAINER' ) {
$html .= '<div class="level' . $childLevel . ' ' . $childrenWrapClass . '">';
$html .= '<div class="row">';
$html .= '<ul class="subchildmenu col-sm-12 mega-columns columns4">';
$html .= $this->_getHtmlStyle1($child, $childrenWrapClass, $limit, $colStops);
$html .= '</ul>';
$html .= '</div>';
$html .= '</div>';
} elseif ($name == 'SHAPEWEAR') {
$html .= '<div class="level' . $childLevel . ' ' . $childrenWrapClass . '">';
$html .= '<div class="row">';
$html .= '<ul class="subchildmenu col-sm-8 mega-columns columns4">';
$html .= $this->_getHtmlStyle2($child, $childrenWrapClass, $limit, $colStops);
$html .= '</ul>';
$html .= '<div class="menu-right-block col-sm-4">';
$html .= $this->getLayout()
->createBlock(\Magento\Cms\Block\Block::class)
->setBlockId('catpic') //replace my_cmsblock_identifier with real CMS bock identifier
->toHtml();
$html .= '</div>';
$html .= '</div>';
$html .= '</div>';
} elseif ($name == 'SERVICES') {
$html .= '<div class="level' . $childLevel . ' ' . $childrenWrapClass . ' col-sm-11">';
$html .= '<div class="row">';
$html .= '<ul class="subchildmenu col-sm-9">';
$html .= $this->_getHtml($child, $childrenWrapClass, $limit, $colStops);
$html .= '</ul>';
$html .= '</div>';
$html .= '</div>';
} else if($childLevel == 0) {
$html .= '<div class="level' . $childLevel . ' ' . $childrenWrapClass . '">';
$html .= '<div class="row">';
$html .= '<ul class="subchildmenu col-sm-12 mega-columns columns4">';
$html .= $this->_getHtmlStyle1($child, $childrenWrapClass, $limit, $colStops);
$html .= '</ul>';
$html .= '</div>';
$html .= '</div>';
} else{
$html .= '<ul class="level' . $childLevel . '">';
$html .= $this->_getHtml($child, $childrenWrapClass, $limit, $colStops); $html .= $this->_getHtml($child, $childrenWrapClass, $limit, $colStops);
$html .= '</ul>'; $html .= '</ul>';
}
return $html;
}
protected function _getHtmlStyle1(Node $menuTree,
$childrenWrapClass,
$limit,
array $colBrakes = []
)
{
$html = '';
$children = $menuTree->getChildren();
$childLevel = $this->getChildLevel($menuTree->getLevel());
$this->removeChildrenWithoutActiveParent($children, $childLevel);
$counter = 1;
$childrenCount = $children->count();
$parentPositionClass = $menuTree->getPositionClass();
$itemPositionClassPrefix = $parentPositionClass ? $parentPositionClass . '-' : 'nav-';
/** @var Node $child */
foreach ($children as $child) {
$child->setLevel($childLevel);
$child->setIsFirst($counter === 1);
$child->setIsLast($counter === $childrenCount);
$child->setPositionClass($itemPositionClassPrefix . $counter);
$outermostClassCode = '';
$outermostClass = $menuTree->getOutermostClass();
if ($childLevel === 0 && $outermostClass) {
$outermostClassCode = ' class="' . $outermostClass . '" ';
$this->setCurrentClass($child, $outermostClass);
}
if ($this->shouldAddNewColumn($colBrakes, $counter)) {
$html .= '</ul></li><li class="column"><ul>';
}
$html .= '<li ' . $this->_getRenderedMenuItemAttributes($child) . '>';
$html .= '<a href="' . $child->getUrl() . '" ' . $outermostClassCode . '><span>' . $this->escapeHtml(
$child->getName()
) . '</span></a>' . $this->_addSubMenu(
$child,
$childLevel,
$childrenWrapClass,
$limit
) . '</li>';
$counter++;
}
if (is_array($colBrakes) && !empty($colBrakes) && $limit) {
$html = '<li class="column"><ul>' . $html . '</ul></li>';
}
return $html;
}
protected function _getHtmlStyle2(Node $menuTree,
$childrenWrapClass,
$limit,
array $colBrakes = []
)
{
$html = '';
$children = $menuTree->getChildren();
$childLevel = $this->getChildLevel($menuTree->getLevel());
$this->removeChildrenWithoutActiveParent($children, $childLevel);
$counter = 1;
$childrenCount = $children->count();
$parentPositionClass = $menuTree->getPositionClass();
$itemPositionClassPrefix = $parentPositionClass ? $parentPositionClass . '-' : 'nav-';
/** @var Node $child */
foreach ($children as $child) {
$child->setLevel($childLevel);
$child->setIsFirst($counter === 1);
$child->setIsLast($counter === $childrenCount);
$child->setPositionClass($itemPositionClassPrefix . $counter);
$outermostClassCode = '';
$outermostClass = $menuTree->getOutermostClass();
if ($childLevel === 0 && $outermostClass) {
$outermostClassCode = ' class="' . $outermostClass . '" ';
$this->setCurrentClass($child, $outermostClass);
}
if ($this->shouldAddNewColumn($colBrakes, $counter)) {
$html .= '</ul></li><li class="column"><ul>';
}
$html .= '<li ' . $this->_getRenderedMenuItemAttributes($child) . '>';
$html .= '<a href="' . $child->getUrl() . '" ' . $outermostClassCode . '><span>' . $this->escapeHtml(
$child->getName()
) . '</span></a>' . $this->_addSubMenu(
$child,
$childLevel,
$childrenWrapClass,
$limit
) . '</li>';
$counter++;
}
if (is_array($colBrakes) && !empty($colBrakes) && $limit) {
$html = '<li class="column"><ul>' . $html . '</ul></li>';
}
return $html; return $html;
} }
...@@ -375,8 +213,7 @@ class Topmenu extends Template implements IdentityInterface ...@@ -375,8 +213,7 @@ class Topmenu extends Template implements IdentityInterface
$childrenWrapClass, $childrenWrapClass,
$limit, $limit,
array $colBrakes = [] array $colBrakes = []
) ) {
{
$html = ''; $html = '';
$children = $menuTree->getChildren(); $children = $menuTree->getChildren();
......
<style>
@media (min-width: 1024px) {
#joshine-navigation span.ui-menu-icon-1 {
top: -13px;
right: 12px;
background-color: #0cc485;
position: absolute;
text-transform: uppercase;
font: inherit;
font-size: 9px;
padding: 3px;
border-radius: 2px;
line-height: 1.2;
color: #ffffff;
min-width: 35px;
text-align: center;
}
#joshine-navigation span.ui-menu-icon-1.ui-icon-1:before {
border-top-color: #0cc485;
}
#joshine-navigation span.ui-menu-icon-2 {
top: -13px;
right: 24px;
background-color: #eb2771;
position: absolute;
text-transform: uppercase;
font: inherit;
font-size: 9px;
padding: 3px;
border-radius: 2px;
line-height: 1.2;
color: #ffffff;
min-width: 35px;
text-align: center;
}
#joshine-navigation span.ui-menu-icon-2.ui-icon-2:before {
border-top-color: #eb2771;
}
#joshine-navigation span.ui-menu-icon-3 {
top: -13px;
right: 24px;
background-color: #df0e0e;
position: absolute;
text-transform: uppercase;
font: inherit;
font-size: 9px;
padding: 3px;
border-radius: 2px;
line-height: 1.2;
color: #ffffff;
min-width: 35px;
text-align: center;
}
#joshine-navigation span.ui-menu-icon-3.ui-icon-3:before {
border-top-color: #df0e0e;
}
#joshine-navigation span.ui-menu-icon-1:before,
#joshine-navigation span.ui-menu-icon-2:before,
#joshine-navigation span.ui-menu-icon-3:before {
left: 3px;
bottom: -6px;
}
#joshine-navigation span.ui-menu-icon-1:before,
#joshine-navigation span.ui-menu-icon-2:before,
#joshine-navigation span.ui-menu-icon-3:before {
content: "";
position: absolute;
width: 3px;
height: 3px;
border: 3px solid transparent;
}
#joshine-navigation .submenu span.ui-menu-icon-1,
#joshine-navigation .submenu span.ui-menu-icon-2,
#joshine-navigation .submenu span.ui-menu-icon-3 {
position: relative;
left: 6px;
top: 0;
}
#joshine-navigation .submenu span.ui-menu-icon-1:before,
#joshine-navigation .submenu span.ui-menu-icon-2:before,
#joshine-navigation .submenu span.ui-menu-icon-3:before {
content: "";
position: absolute;
width: 3px;
height: 3px;
border: 3px solid transparent;
top: 8px;
left: -6px;
}
#joshine-navigation .submenu span.ui-menu-icon-1:before {
border-right-color: #0cc485;
}
#joshine-navigation .submenu span.ui-menu-icon-2:before {
border-right-color: #eb2771;
}
#joshine-navigation .submenu span.ui-menu-icon-3:before {
border-right-color: #df0e0e;
}
}
@media (max-width: 1024px) {
#joshine-navigation span.ui-menu-icon-1 {
top: 50%;
right: 36px;
margin-top: -7px;
position: absolute;
text-transform: uppercase;
font: inherit;
font-size: 9px;
padding: 2px;
border-radius: 2px;
line-height: 1;
color: #fff;
}
#joshine-navigation span.ui-menu-icon-1.ui-icon-1 {
background-color: #0cc485 !important;
}
#joshine-navigation span.ui-menu-icon-1:before {
content: "";
position: absolute;
width: 3px;
height: 3px;
border: 3px solid transparent;
left: -6px;
bottom: 3px;
}
#joshine-navigation span.ui-menu-icon-1.ui-icon-1:before {
border-right-color: #0cc485 !important;
}
#joshine-navigation span.ui-menu-icon-2 {
top: 50%;
right: 36px;
margin-top: -7px;
position: absolute;
text-transform: uppercase;
font: inherit;
font-size: 9px;
padding: 2px;
border-radius: 2px;
line-height: 1;
color: #fff;
}
#joshine-navigation span.ui-menu-icon-2.ui-icon-2 {
background-color: #eb2771 !important;
}
#joshine-navigation span.ui-menu-icon-2:before {
content: "";
position: absolute;
width: 3px;
height: 3px;
border: 3px solid transparent;
left: -6px;
bottom: 3px;
}
#joshine-navigation span.ui-menu-icon-2.ui-icon-2:before {
border-right-color: #eb2771 !important;
}
#joshine-navigation span.ui-menu-icon-3 {
top: 50%;
right: 36px;
margin-top: -7px;
position: absolute;
text-transform: uppercase;
font: inherit;
font-size: 9px;
padding: 2px;
border-radius: 2px;
line-height: 1;
color: #fff;
}
#joshine-navigation span.ui-menu-icon-3.ui-icon-3 {
background-color: #df0e0e !important;
}
#joshine-navigation span.ui-menu-icon-3:before {
content: "";
position: absolute;
width: 3px;
height: 3px;
border: 3px solid transparent;
left: -6px;
bottom: 3px;
}
#joshine-navigation span.ui-menu-icon-3.ui-icon-3:before {
border-right-color: #df0e0e !important;
}
}
</style>
<?php <?php
/** /**
* Copyright © Magento, Inc. All rights reserved. * Copyright © Magento, Inc. All rights reserved.
...@@ -14,7 +207,7 @@ $columnsLimit = $block->getColumnsLimit() ?: 0; ...@@ -14,7 +207,7 @@ $columnsLimit = $block->getColumnsLimit() ?: 0;
$_menuHtml = $block->getHtml('level-top', 'submenu', $columnsLimit) $_menuHtml = $block->getHtml('level-top', 'submenu', $columnsLimit)
?> ?>
<div class="nav-sections"> <div class="nav-sections">
<nav class="navigation" data-action="navigation"> <nav class="navigation" data-action="navigation" id="joshine-navigation">
<ul data-mage-init='{"menu":{"responsive":true,"dropdown":"div", "expanded":true, "position":{"my":"left top","at":"left bottom"}}}'> <ul data-mage-init='{"menu":{"responsive":true,"dropdown":"div", "expanded":true, "position":{"my":"left top","at":"left bottom"}}}'>
<li class="level0 nav-0 level-top"><a href="/" class="level-top"><span>Home</span></a></li> <li class="level0 nav-0 level-top"><a href="/" class="level-top"><span>Home</span></a></li>
<?= /* @noEscape */ $_menuHtml?> <?= /* @noEscape */ $_menuHtml?>
......
...@@ -1350,42 +1350,29 @@ footer{ ...@@ -1350,42 +1350,29 @@ footer{
.submenu{ .submenu{
width: 100%; width: 100%;
margin-top: 16px; margin-top: 16px;
padding: 60px 30px 60px 20px; padding: 24px 30px 60px 20px;
} }
.subchildmenu.mega-columns > li{ .subchildmenu.mega-columns > li{
float: left; float: left;
} }
.navigation li.level0 .submenu li.level1{ .navigation li.level0 .submenu li.level1{
border-right: 1px solid #e1e1e1; border-right: 1px solid #e1e1e1;
padding: 0 20px; padding: 0 6px;
} }
.navigation .subchildmenu.col-sm-8.mega-columns.columns4 li.level1:last-child{ .navigation .subchildmenu li.level1:last-child{
border: none; border: none !important;
}
.navigation .subchildmenu.mega-columns.columns4 > li{
width: 25%;
}
.navigation .subchildmenu.col-sm-8.mega-columns.columns4 > li{
width: 18%;
}
.navigation .subchildmenu.mega-columns.columns4 > li:nth-child(4n+1){
clear: both;
}
.navigation .menu-right-block.col-sm-4{
float: right;
width: 38%;
} }
.navigation ul li.level0{ .navigation ul li.level0{
padding: 0 1px; padding: 0 1px;
} }
.navigation ul li.level0 > a > span{ .navigation ul li.level0 > a > span{
text-transform: uppercase; text-transform: uppercase;
font-size: 13px; font-size: 14px;
font-weight: 500; font-weight: 500;
} }
.navigation .submenu li.level1 > a{ .navigation .submenu li.level1 > a{
font-size: 14px; font-size: 14px;
font-weight: 500; font-weight: 500;
...@@ -1399,26 +1386,25 @@ footer{ ...@@ -1399,26 +1386,25 @@ footer{
text-transform: none; text-transform: none;
} }
.navigation .subchildmenu.col-sm-8.mega-columns.columns4 ul.level1{ .navigation .subchildmenu ul.level1{
display: block !important; display: block !important;
} }
.navigation .subchildmenu.col-sm-8.mega-columns.columns4 li.level1.parent>a::after{ .navigation .subchildmenu li.level1.parent>a::after{
content: none; content: none;
} }
.navigation .subchildmenu.col-sm-8.mega-columns.columns4 li.level1.parent>a>span{ .navigation .subchildmenu li.level1.parent>a>span{
font-size: 14px; font-size: 16px;
font-weight: 500; font-weight: 500;
color: #000001; color: #000001;
font-family: 'Outfit-Regular', sans-serif; font-family: 'Outfit-Regular', sans-serif;
} }
.navigation .subchildmenu.col-sm-8.mega-columns.columns4 li.level1.parent ul li.level2>a>span{ .navigation .subchildmenu li.level1.parent ul li.level2>a>span{
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
color: #666666; color: #666666;
font-family: 'Outfit-Regular', sans-serif; font-family: 'Outfit-Regular', sans-serif;
} }
.navigation .subchildmenu.col-sm-9 li{ .navigation .subchildmenu.col-sm-9 li{
position: relative; position: relative;
border: none; border: none;
...@@ -2620,4 +2606,6 @@ strong#block-related-heading,strong#block-upsell-heading{ font-weight: 600; colo ...@@ -2620,4 +2606,6 @@ strong#block-related-heading,strong#block-upsell-heading{ font-weight: 600; colo
width: 4%; width: 4%;
z-index: 10; z-index: 10;
} }
/*导入Joshine工具类*/
@import "./_joshine_col";
...@@ -38,26 +38,6 @@ ...@@ -38,26 +38,6 @@
} }
$('li.parent > ul', this.element).hide(); $('li.parent > ul', this.element).hide();
$('li.nav-1', this.element)
.children('a')
.filter(function () {
return $(this).children('.ui-icon-1').length === 0;
})
.prepend('<span class="ui-menu-icon-1 ui-icon-1">NEW</span>');
$('li.nav-8', this.element)
.children('a')
.filter(function () {
return $(this).children('.ui-icon-2').length === 0;
})
.prepend('<span class="ui-menu-icon-2 ui-icon-2">SALE</span>');
$('li.nav-6', this.element)
.children('a')
.filter(function () {
return $(this).children('.ui-icon-3').length === 0;
})
.prepend('<span class="ui-menu-icon-3 ui-icon-3">HOT!</span>');
$('li.parent', this.element).on('keydown.menu', function (e) { $('li.parent', this.element).on('keydown.menu', function (e) {
var dropdown = $(this).children(self.options.dropdown), var dropdown = $(this).children(self.options.dropdown),
......
<IfVersion < 2.4>
order allow,deny
deny from all
</IfVersion>
<IfVersion >= 2.4>
Require all denied
</IfVersion>
...@@ -30,27 +30,6 @@ define([ ...@@ -30,27 +30,6 @@ define([
*/ */
_create: function () { _create: function () {
$('li.nav-1', this.element)
.children('a')
.filter(function () {
return $(this).children('.ui-icon-1').length === 0;
})
.prepend('<span class="ui-menu-icon-1 ui-icon-1">NEW</span>');
$('li.nav-8', this.element)
.children('a')
.filter(function () {
return $(this).children('.ui-icon-2').length === 0;
})
.prepend('<span class="ui-menu-icon-2 ui-icon-2">SALE</span>');
$('li.nav-6', this.element)
.children('a')
.filter(function () {
return $(this).children('.ui-icon-3').length === 0;
})
.prepend('<span class="ui-menu-icon-3 ui-icon-3">HOT!</span>');
var self = this; var self = this;
this.delay = this.options.delay; this.delay = this.options.delay;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment