Front end - letronghieu4897/magento GitHub Wiki
- 1. Override Order Confirmation Email
- 2. Override block, theme.........
- 3. Create new tab
- 4. Create new CMS page and add css
- 5. Add static block into sidebar left
- 6. Add static block into a block
- 7. Container and Block
- 8. Banner and Slider
- 9. Multiple languages (Translate Languages)
- 10. Fix layout of theme
- 11. Get image from Category Image
- 12. Navigation Attribute
- 13. Add static block into phtml files
- 14. Preference in di.xml
- 15. Virtual Type
- 16. Onestep checkout
- 17. Animation for add to cart
- 18. Override JS magento 2
- 19. Add script for magento 2
- 20. Product Detail
- 21. KnockoutJS
- 22. Template on JS file
- 23.Override mage/js file
- 24.Override widget js
- 25.Get price to show on product list
- 26.Show original price on product list of configurable product when apply price rule
- 27.Show label sale price on product list of configurable product when apply price rule
- 28.Show label sale price on product detail AMASTY
- 29.Add table field with add more field and multiple select on admin
- 30.Add template into html file by knockoutjs
- 31.Create widget to get best seller
- 32.Change Copyright year static to dynamic year
- 33.Change font for magento 2
- 34.Setup Grunt for magento 2
- 35.Get image path of theme
- 36.Translate generate for theme i18n
- 37.Add custom link into header link
- 38.LESS import media screen
Marketing > Email Template > Add New Template > Choose New Order > Load
$ OVERRIDE ORDER CONFIRMATION EMAIL
. ________________________________________________________________________________________
βββ design
β βββ frontend
| βββ [Vendor]
| βββ [Extention]
| βββ Magento_Sales
| βββ templates
| βββ email
| βββ items
| βββ order
| βββ default.phtml
. _________________________________________________________________________________________
Go to registration.php
\vendor\magento\module-sales\registration.php
<?php
/**
* Copyright Β© Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Magento_Sales',
__DIR__
);
Create folder in
βββ design
β βββ frontend
| βββ [Vendor]
| βββ [Extention]
With name is Magento_Sales : get from registration.php
Then create path source same path into file default.phtml [Look at Tree]
1. Go into file registration.php : -> get name of folder : [Netpower_Ghn]
2. Go to design > frontend > [Vendor] > [Theme] > Create folder with name get from [Netpower_Ghn] [1].
3. Create file name the same with file is overrided [Same path] (from template/...)
Block
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<update handle="review_product_form_component"/>
<body>
<referenceBlock name="product.info.details">
<referenceBlock name="reviews.tab" remove="true"/>
<block class="Magento\Review\Block\Product\Review" name="trustpilot.review.tab" template="Trustpilot_Reviews::review.phtml" />
</referenceBlock>
</body>
</page>
1. referenceBlock : Only need the name. [Or referenceContainer]
2. Only reference container contain the block we want to override.
<Example> Review Product </Example>
. ___________________________________________
βββ [Vendor]_[Extention]
β βββ layout
| β βββ catalog_product_view.xml
| βββ templates
| βββ review.phtml
. ____________________________________________
<1> Create theme </1>
<2> Create file same name in Core : catelog_product_view.xml</2>
<3> Create new block </3>
<4> Create template file : templates > review.phtml
catalog_product_view.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="product.info.details">
<referenceBlock name="reviews.tab" remove="true"/>
<block class="Magento\Catalog\Block\Product\View" name="trustpilot.review.tab" as="trustpilot.reviews" template="Trustpilot_Reviews::review.phtml" group="detailed_info">
<arguments>
<argument translate="true" name="title" xsi:type="string">Review</argument>
</arguments>
</block>
</referenceBlock>
</body>
</page>
$block : this variable use as Class in block declare above. [Magento\Catalog\Block\Product\View]
We can you $block as View.
1
- Create forlder follow below tree
. ________________________________________________________________________________________
βββ app
β βββ code
| βββ design
| βββ frontend
| βββ [Vendor Theme]
| βββ [Source Theme]
| βββ web
| βββ scss
| βββ helper
| βββ layout
| βββ mixins
. __________________________________________________________________________________________
2
- Create gulpfile.js in root folder
var gulp = require('gulp');
var sass = require('gulp-sass');
var livereload = require('gulp-livereload');
//var sourcemaps = require('gulp-sourcemaps');
gulp.task('sass-porto_child', function(){
return gulp.src('app/design/frontend/Smartwave/porto_child/web/css/custom.scss')
//.pipe(sourcemaps.init())
.pipe(sass({outputStyle: 'compressed'})) //expanded, nested, compact, compressed
//.pipe(sourcemaps.write())
.pipe(livereload())
.pipe(gulp.dest('app/design/frontend/Smartwave/porto_child/web/css/'))
.pipe(gulp.dest('pub/static/frontend/Smartwave/porto_child/nb_NO/css/'));
});
gulp.task('watch', function(){
livereload.listen();
gulp.watch('app/design/frontend/Smartwave/porto_child/web/css/scss/**/*', ['sass-porto_child']);
});
- Change name folder in above file
3
- Create new file package.json
- Copy package.json.sample -> package.json
- Run sudo npm install
4
- Create content for CMS Page
EXAMPLE
<h1 style="color:#4A4A4A;"><strong>DEKK OG FELG GUIDE</strong></h1>
<p style="width: 484px;">Vi vet det kan vΓ¦r forrvirende Γ₯ bestille dekk. Her for du forklaringen som kanskje gjΓΈr det litt enkeler. Alle dekk stΓ₯r det et noen tall og bokstav kombinasjoner, som sier noe om type, stΓΈrrelse og kvaliteten pΓ₯ dekket.</p>
<h2 style="color:#4A4A4A;"><strong>205<span style="color: #b4b4b4;">/55 R 16 87V</span> | SLITEBANE</strong></h2>
<p style="width: 484px;">Det fΓΈrste tallet (205) er bredden pΓ₯ dekkets slitebane i millimeter, her 205 mm.</p>
<h2 style="color:#4A4A4A;"><strong><span style="color: #b4b4b4;">205/</span>55 <span style="color: #b4b4b4;">R 16 87V </span>| PROFIL</strong></h2>
<p style="width: 484px;">Dekkets profil sier noe om dekkets hΓΈyde i forhold til bredde. 55 betyr at dekkets hΓΈyde er 55 prosent av bredden.</p>
<h2 style="color:#4A4A4A;"><strong><span style="color: #b4b4b4;">205/55</span> R <span style="color: #b4b4b4;">16 87V</span> | KONSTRUKSJON</strong></h2>
<p style="width: 484px;">Indikerer konstruksjonsmΓ₯te, i dette tilfellet radialdekk. Kan ogsΓ₯ vΓ¦re D diagonale (gammel mΓ₯te).</p>
<h2 style="color:#4A4A4A;"><strong><span style="color: #b4b4b4;">205/55 R</span> 16 <span style="color: #b4b4b4;"> 87V</span> | FELG</strong></h2>
<p style="width: 484px;">Felgens stΓΈrrelse, diameter mΓ₯lt i tommer.</p>
<h2 style="color:#4A4A4A;"><strong><span style="color: #b4b4b4;">205/55 R 16</span> 87<span style="color: #b4b4b4;">V</span> | BELASTNINGSKLASSE</strong></h2>
<p style="width: 484px;">Belastningsklasse, egen tabel som, 87 = 545 kg. <br> <br> ESK: 545 kg x 4 hjul = 2 180 kg totalvekt pΓ₯ bil.</p>
<h2 style="color:#4A4A4A;"><strong><span style="color: #b4b4b4;">205/55 R 16 87</span>V<span style="color: #b4b4b4;"></span> | HASTIGHETSKLASSE</strong></h2>
<p>Belastningsklasse, v = 240 km/h <br><br> Q = 160 km/h, <br><br> R = 170 km/h <br><br> S = 180 km/h <br><br> T = 190 km/h <br><br> H = 210 km/h <br><br> V = 240 km/h <br><br> W = 270 km/h <br><br> Y = 300 km/h</p>
5
- Code css
- Create file scss in folder layout has been already created above.
6
- Create file custom.scss in folder scss has been already created above.
Import file scss into this file.
//EXAMPLE
//IMPORT SCSS ONLY, NO CSS HERE
@import "scss/helper/variables";
@import "scss/mixins/media";
@import "scss/mixins/css3-mixins";
@import "scss/mixins/custom";
@import "scss/layout/common";
@import "scss/layout/contact";
@import "scss/layout/cart";
@import "scss/layout/checkout";
@import "scss/layout/header";
@import "scss/layout/footer";
@import "scss/layout/home";
@import "scss/layout/category";
@import "scss/layout/new-product-list";
@import "scss/layout/product";
@import "scss/layout/product-list";
@import "scss/layout/login";
@import "scss/layout/register";
@import "scss/layout/blog";
@import "scss/layout/page";
@import "scss/layout/my-profile";
@import "scss/layout/search";
@import "scss/layout/popup";
@import "scss/layout/quick-add-to-cart";
@import "scss/layout/update-cart";
@import "scss/layout/404";
/*
Example for media mixins:
@include phone{
//content goes here
}
Example for css3 mixins:
@include border-radius(2px 3px 4px 5px);
*/
7
- Next, We look at the gulpfile.js created before.
1 For only one page specific.
1. Go to Admin site
2. Content > Pages > [Your Page] > Edit > Design > Layout Update XML
3. Add to Layout Update XML the below code.
<referenceContainer name="sidebar.additional">
<block class="Magento\Cms\Block\Block" name="[sidebar_left]">
<arguments>
<argument name="block_id" xsi:type="string">[sidebar_left]</argument>
</arguments>
</block>
</referenceContainer>
2 For all page /app/design/frontend///Magento_Cms/layout/cms_page_view.xml
. ________________________________________________________________________________________
βββ app
| βββ design
| βββ frontend
| βββ [Vendor Theme]
| βββ [Source Theme]
| βββ Magento_Cms
| βββ layout
| βββ cms_page_view.xml
. __________________________________________________________________________________________
<?xml version="1.0"?>
<!--
/**
* Copyright Β© 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="sidebar.additional">
<block class="Magento\Cms\Block\Block" name="mycustomstaticblock">
<arguments>
<argument name="block_id" xsi:type="string">static_block_id</argument>
</arguments>
</block>
</referenceContainer>
</body>
</page>
1. Select Block you want to add a other block into it.
2. Insert Widget > Choose block you want to insert.
CODE LOOK LIKE THIS :
{{widget type="Magento\Cms\Block\Widget\Block" template="widget/static_block/default.phtml" block_id="135" type_name="CMS Static Block"}}
1. Container : referenceContainer is call this container, this container will contain all child. After call that , The container will echo all child. If you want to add container or block into this. CODE BELOW
2. Block : Only ready that block, not convert child of block. This is difference between Block and Container. You want to Overwrite Block. Write referenceBlock to overwrite.
1. Check where is the container you want to reference.
2. Often registration.php to see name of Folder
3. Create a Folder with name you found above
4. And then , create path the same with path of container you want to reference. With same name file.
5. Add code below
<?xml version="1.0"?>
<!--
/**
* Copyright Β© 2018 Porto. All rights reserved.
*/
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="page.top">
<container name="banner-top-container" htmlTag="div" htmlClass="banner-top" before="-">
<container name="banner-top-container-inside">
<block class="Magento\Cms\Block\Block" name="banner-top">
<arguments>
<argument name="block_id" xsi:type="string">category_banner_top</argument>
</arguments>
</block>
</container>
</container>
</referenceContainer>
</body>
</page>
Explain
<container name="banner-top-container" htmlTag="div" htmlClass="banner-top" before="-">
1. before="-" : Insert container on head.
2. before="<container-name>" : Insert container on top of this container name.
3. WITH after is opposite.
1. Inspect to check container or block base on command
<referenceBlock name="parent">
<Block name="children" class="..." template="..." />
</referenceBlock>
In block "parent" we can call child block by
$block->getChildHtml('children');
or
$block->getChildBlock('children');
1. Load or Copy extension : Banner Slider.
2. Create a banner and add banner to slider.
3. Add banner to page.
. ________________________________________________________________________________________
βββ app
| βββ design
| βββ frontend
| βββ [Vendor Theme]
| βββ [Source Theme]
| βββ i18n
| βββ nb_NO.csv
. __________________________________________________________________________________________
Translate English to Norway languages
"Add to Cart","LEGG I HANDLEKURV"
Example in Bridgestone
. ________________________________________________________________________________________
βββ app
| βββ design
| βββ frontend
| βββ Smartwave
| βββ porto
| | βββ pla pla pla
| | βββ category_filter.phtml
| βββ porto-child
| βββ pla pla pla
| βββ category_filter.phtml
. __________________________________________________________________________________________
1. Create a path the same with folder of theme.
porto : Parent theme.
porto-child : Theme overwrite.
2. Copy file from porto to porto-child
<?php
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$storeManager = $objectManager->get('\Magento\Store\Model\StoreManagerInterface');
$mediaUrl =$storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
$category = $objectManager->get('Magento\Framework\Registry')->registry('current_category'); //Get Current Category
?>
<?php if($category): ?>
<?php
$subcats = $category->getChildrenCategories();
$_helper = $this->helper('Magento\Catalog\Helper\Output');
if(count($subcats)>0){
?>
<div class="block-category-list">
<div class="block-head">
<p> <?= __('FINN DEKK') ?> </p>
</div>
<div class="block-title">
<img src="<?= $mediaUrl ?>catalog/tmp/category/<?= strtolower(preg_replace('/[^A-Za-z0-9\-]/', '', str_replace(" ", "_", $category->getName())));?>.png"/>
<strong><?php echo $category->getName() ?></strong>
</div>
<div class="block-content">
<ol class="items">
<?php
foreach($subcats as $subcat){
?>
<li class="item">
<img src="<?= $mediaUrl ?>catalog/tmp/category/<?= strtolower(preg_replace('/[^A-Za-z0-9\-]/', '', str_replace(" ", "_", $subcat->getName())));?>.png"/>
<a href="<?php echo $subcat->getUrl() ?>"><?php echo $subcat->getName() ?></a>
</li>
<?php
}
?>
</ol>
</div>
<script type="text/javascript">
require([
'jquery'
], function ($) {
$("#layered-filter-block").before($(".block.block-category-list"));
});
</script>
</div>
<?php
}
?>
<?php endif; ?>
GET MEDIA URL to combine with path image in category.
$storeManager = $objectManager->get('\Magento\Store\Model\StoreManagerInterface');
$mediaUrl =$storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
$mediaUrl ?>catalog/tmp/category/<?= strtolower(preg_replace('/[^A-Za-z0-9\-]/', '', str_replace(" ", "_", $category->getName())));
1. $mediaUrl : Above
2. catalog/tmp/category : Folder contain image in admin categories image
3. strtolower : Transfer to lower words
4. preg_replace : Remove special letters
5. str_replace : replace any word you need.
=> Purpose : Replace name of Category to a lower words without space between words. To specific image name.
YOU WANT TO CHANGE IMAGE IN MENU LEFT SIDEBAR.
1. Set the name of image with rule : <nameoficon>.
2. Load it in specific category.
DONE.
<?php
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$storeManager = $objectManager->get('\Magento\Store\Model\StoreManagerInterface');
$mediaUrl =$storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
$category = $objectManager->get('Magento\Framework\Registry')->registry('current_category'); //Get Current Category
?>
<?php if($category): ?>
<?php
$subcats = $category->getChildrenCategories();
$_helper = $this->helper('Magento\Catalog\Helper\Output');
if(count($subcats)>0){
?>
<div class="block-category-list">
<div class="block-head">
<p> <?= __('FINN DEKK') ?> </p>
</div>
<div class="block-title">
<div class="container-icon-title">
<img src="<?= $category->getImageUrl();?>"/>
</div>
<strong><?php echo $category->getName(); ?></strong>
</div>
<div class="block-content">
<ol class="items">
<?php
foreach($subcats as $subcat){
$_category = $objectManager->create('Magento\Catalog\Model\Category')->load($subcat->getId());
?>
<li class="item">
<div class="container-icon-content">
<img src="<?= $_category->getImageUrl();?>"/>
</div>
<a href="<?php echo $subcat->getUrl() ?>"><?php echo strtoupper($subcat->getName()) ?></a>
</li>
<?php
}
?>
</ol>
</div>
<script type="text/javascript">
require([
'jquery'
], function ($) {
$("#layered-filter-block").before($(".block.block-category-list"));
});
</script>
</div>
<?php
}
?>
<?php endif; ?>
<img src="<?= $category->getImageUrl();?>"/>
Get image of Category
<?php
foreach($subcats as $subcat){
******** $_category = $objectManager->create('Magento\Catalog\Model\Category')->load($subcat->getId()); ********
?>
<li class="item">
<div class="container-icon-content">
<img src="<?= $_category->getImageUrl();?>"/>
</div>
<a href="<?php echo $subcat->getUrl() ?>"><?php echo strtoupper($subcat->getName()) ?></a>
</li>
<?php
}
?>
GET IMAGE OF CHILD CATEGORY.
- Store > Product > Choose Attribute > Storefront Properties > Use in Layered Navigation -> NO
- Go to store > F12 > Check attribute =<"attribute-name">
- Copy attribute-name > Go to Admin site > Store > Product > Search Attribute with attribute-name
1. Create static block on admin (get Block ID EXAMPLE === block-id)
2. WAY 1 : insert into XML
3. WAY 2 : create template files
layout/local.xml
=====================================================================
EXAMPLE : INSERT STATIC BLOCK INSIDE after_body_start
======================================================================
<reference name="after_body_start">
<block type="cms/block" name="google_tag_block" before="-">
<action method="setBlockId"><block_id>block-id</block_id></action>
</block>
</reference>
<reference name="after_body_start">
<block type="core/template" before="-" template="page/html/google_code.phtml"/>
</reference>
page/html/google_code.phtml
=========================================================================================================
<?php echo $this->getLayout()->createBlock('cms/block')->setBlockId('block-id')->toHtml() ?>
1. Create extend layout file
2. Reference container contain Block you want to add Block
3. Add Block (static)
<block class="Magento\Cms\Block\Block" before="<block-name>">
<arguments>
<argument name="block-id" xsi:type = string>[id-block]</argument>
</arguments>
</block>
<config>
<preference for = 'Magento\...\UrlInterface'
type = 'Magento\...\Url' />
</config>
# When having request to Magento\...\UrlInterface it will be inject into Magento\...\Url
// DEPENDENCE INJECTION
<virtualType name="Netpower\...\className">
<argument name="valu" type="object">Netpower\...\TEST</argument>
</virtualType>
--- Block Netpower\...\TEST having mission is pass data into valu. [1]
--- In block Netpower\...\className can get value of argument by : getValu(); [2]
[2] get data from [1]. We can call class Netpower\...\className and use valu as real Block class.
Copy extension OnePageCheckout from BLF or Lenspower from Lenspower.
[Need append more information]
app/code/Netpower/Lenspower/view/frontend/web/js/catalog-add-to-cart.js
Check file requirejs-config.js of file need to override and copy Name or Path to your module in file requirejs-config.js
var config = {
map: {
'*': {
'Magento_Checkout/js/view/summary/abstract-total':'Netpower_Lenspower/js/view/checkout/summary/abstract-total',
configurableLens: 'Netpower_Lenspower/js/configurable',
packageLens: 'Netpower_Lenspower/js/package',
catalogAddToCart : 'Netpower_Lenspower/js/catalog-add-to-cart',
// catalogAddToCart is a name of path for catalog-add-to-cart.js in core module
}
}
};
1. Create file Magento_Theme/web/js/custom_header_script.js
2. Create file Magento_Theme/templates/html/custom_script.phtml
<script type="text/x-magento-init">
{
"*": { //======================================== APPLY FOR ALL ELEMENT
"Magento_Theme/js/custom_script": {}
}.
".page-header" : { //======================================== USE FOR $.widget with this.element = .page-header DOM
"Magento_Theme/js/custom_header_script" : {}
}
}
</script>
3. Write JS for custom_header_script.js NOTE : Using Widget.
define([
"jquery",
'mage/translate'
],
function ($, $t) {
'use strict';
$.widget('mage.headerScroll', { //============================= Declare a widget
_create: function () {
var self = this.element;
var startPos = $(".slider-container.slider-container-homepage").height() - 60;
if ($(document).width() < 768) {
$(".page-header .header.content .logo").append("<a href='javascript:void(0)' id='stickyMenUSearchBut' class='sticky-menu-search-button'></a>");
$("#stickyMenUSearchBut").click(function() {
$(".page-header .header .block-search").slideToggle(300);
});
}
$(window).on('scroll', function() {
$('#stickyMenUSearchBut').hide();
if ($(window).scrollTop() >= startPos) {
$("body").addClass("has-sticky-menu");
$(".page-header .header .block-search").hide();
$('#stickyMenUSearchBut').show();
} else {
$('#stickyMenUSearchBut').hide();
$("body").removeClass("has-sticky-menu");
$(".page-header .header .block-search").show();
}
});
},
});
return $.mage.headerScroll //============================= Return widget was declared
});
app/design/frontend/Smartwave/porto_child/Magento_Catalog/templates/product/price/amount/default.phtml
<?php
/**
* Copyright Β© Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// @codingStandardsIgnoreFile
?>
<?php /** @var \Magento\Framework\Pricing\Render\Amount $block */ ?>
<?php /** @var \Magento\Tax\Helper\Data $_taxHelper */ ?>
<?php $_taxHelper = $this->helper('Magento\Tax\Helper\Data'); ?>
<?php
$labelTax = "";
if ($_taxHelper->displayPriceIncludingTax()) {
$labelTax = strtolower($block->escapeHtml(__('Incl. Tax')));
}
if ($_taxHelper->displayPriceExcludingTax()) {
$labelTax = strtolower($block->escapeHtml(__('Excl. Tax')));
}
if ($_taxHelper->displayBothPrices()) {
$labelTax = strtolower($block->escapeHtml(__('Incl. Tax')));
}
?>
<span class="price-container <?= /* @escapeNotVerified */ $block->getAdjustmentCssClasses() ?>"
<?= $block->getSchema() ? ' itemprop="offers" itemscope itemtype="http://schema.org/Offer"' : '' ?>>
<div class="adjustment-price">
<?php if ($block->hasAdjustmentsHtml()): ?>
<?= $block->getAdjustmentsHtml() ?>
<?php endif; ?>
</div>
<div class="price">
<?php if ($labelTax): ?>
<span class="price-label"><?= /* @escapeNotVerified */ $labelTax ?></span>
<?php endif; ?>
<span <?php if ($block->getPriceId()): ?> id="<?= /* @escapeNotVerified */ $block->getPriceId() ?>"<?php endif;?>
<?= ($block->getPriceDisplayLabel()) ? 'data-label="' . $block->getPriceDisplayLabel() . $block->getPriceDisplayInclExclTaxes() . '"' : '' ?>
data-price-amount="<?= /* @escapeNotVerified */ $block->getDisplayValue() ?>"
data-price-type="<?= /* @escapeNotVerified */ $block->getPriceType() ?>"
class="price-wrapper <?= /* @escapeNotVerified */ $block->getPriceWrapperCss() ?>"
><?= /* @escapeNotVerified */ $block->formatCurrency($block->getDisplayValue(), (bool)$block->getIncludeContainer()) ?></span>
<?php if ($block->getSchema()): ?>
<meta itemprop="price" content="<?= /* @escapeNotVerified */ $block->getDisplayValue() ?>" />
<meta itemprop="priceCurrency" content="<?= /* @escapeNotVerified */ $block->getDisplayCurrencyCode() ?>" />
<?php endif; ?>
</div>
</span>
/**
* Copyright 2019 Netpower, Inc. All rights reserved.
*/
/*global define*/
define([
'jquery',
'underscore',
'Magento_Checkout/js/view/shipping',
'ko',
'Magento_Checkout/js/model/quote',
'Magento_Checkout/js/action/select-shipping-method',
'Magento_Checkout/js/action/set-shipping-information',
'Magento_Checkout/js/checkout-data',
'Magento_Checkout/js/action/get-totals',
'Magento_Checkout/js/model/address-converter',
'Magento_Customer/js/model/customer',
'Magento_Checkout/js/action/select-shipping-address',
'Magento_Customer/js/model/address-list',
'Netpower_OnePageCheckout/js/model/payment/is-loading',
'Netpower_OnePageCheckout/js/action/checkout/select-shipping-method'
], function ($,
_,
Component,
ko,
quote,
selectShippingMethodAction,
setShippingInformationAction,
checkoutData,
getTotals,
addressConverter,
customer,
selectShippingAddress,
addressList,
paymentIsLoading,
onepageShippingMethod) {
'use strict';
var self;
return Component.extend({
defaults: {
template: 'Netpower_OnePageCheckout/checkout/shipping-method'
},
isAddressFormVisible: ko.observable(addressList().length === 0),
visible: ko.observable(true),
shippingRateGroup: ko.observable(),
shippingRate: ko.observable(),
setupListener: function () {
$('#onepage-checkout-shipping-method-additional-load').on('change', 'input', function () {
setShippingInformationAction();
});
},
initialize: function () {
self = this;
this._super();
},
/**
* Set shipping information handler
*/
setShippingInformation: function () {
if (this.isAddressFormVisible()) {
var shippingAddress,
addressData;
shippingAddress = quote.shippingAddress();
addressData = addressConverter.formAddressDataToQuoteAddress(
this.source.get('shippingAddress')
);
for (var field in addressData) {
if (addressData.hasOwnProperty(field) &&
shippingAddress.hasOwnProperty(field) &&
typeof addressData[field] !== 'function' &&
_.isEqual(shippingAddress[field], addressData[field])
) {
shippingAddress[field] = addressData[field];
} else if (typeof addressData[field] !== 'function' && !_.isEqual(shippingAddress[field], addressData[field])) {
shippingAddress = addressData;
break;
}
}
if (customer.isLoggedIn()) {
shippingAddress.save_in_address_book = this.saveInAddressBook ? 1 : 0;
}
selectShippingAddress(shippingAddress);
if (customer.isLoggedIn()) {
checkoutData.setNewCustomerShippingAddress(shippingAddress);
}
}
if (quote.shippingMethod()) {
paymentIsLoading.isLoading(true);
return setShippingInformationAction().always(function () {
paymentIsLoading.isLoading(false);
});
} else {
return $.Deferred();
}
},
/**
* @param {Object} shippingMethod
* @return {Boolean}
*/
selectShippingMethod: function (shippingMethod) {
self.setShippingInformation();
onepageShippingMethod(shippingMethod);
return true;
},
// HERE ====================================================================================
setHeightForShippingMethod: function() {
var self = $(this);
var setHeightElement = $('#checkout-step-shipping_method').find('.np-checkout-shipping-method').first();
if($(setHeightElement).hasClass('clear-max-height')) {
$(setHeightElement).removeClass('clear-max-height');
}
else {
$(setHeightElement).addClass('clear-max-height');
}
}
});
});
Using It
<div data-bind="click: setHeightForShippingMethod" class="read-more-information" id="js-read-more-information">
<a>
<span data-bind="i18n: 'More Shipping'"></span>
</a>
</div>
app/code/Netpower/OnePageCheckout/view/frontend/web/js/view/checkout/summary/item/details.js
/**
* Copyright 2019 Netpower, Inc. All rights reserved.
*/
define(
[
'jquery',
'uiComponent',
'mage/storage',
'Magento_Customer/js/customer-data',
'Magento_Checkout/js/action/get-totals',
'Magento_Checkout/js/model/totals',
'Magento_Checkout/js/model/quote',
'Netpower_OnePageCheckout/js/action/reload-shipping-method',
'Magento_Checkout/js/action/get-payment-information',
'Magento_Ui/js/modal/confirm',
'Magento_Ui/js/modal/alert',
'mage/translate',
'Magento_Catalog/js/price-utils'
],
function (
$,
Component,
storage,
customerData,
getTotalsAction,
totals,
quote,
reloadShippingMethod,
getPaymentInformation,
confirm,
alertPopup,
Translate,
priceUtils
) {
"use strict";
return Component.extend({
params: '',
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
defaults: {
template: 'Netpower_OnePageCheckout/checkout/summary/item/details'
},
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
getIndex: function(index) {
return index + ' ' + $.mage.__(' pcs.');
},
getValue: function(quoteItem) {
return quoteItem.name;
},
addQty: function (data) {
this.updateQty(data.item_id, 'update', data.qty + 1);
},
minusQty: function (data) {
this.updateQty(data.item_id, 'update', data.qty - 1);
},
updateNewQty: function (data) {
this.updateQty(data.item_id, 'update', data.qty);
},
deleteItem: function (data) {
var self = this;
confirm({
content: $.mage.__('Do you want to remove the item from cart?'),
actions: {
confirm: function () {
self.updateQty(data.item_id, 'delete', '');
},
always: function (event) {
event.stopImmediatePropagation();
}
}
});
},
showOverlay: function () {
$('body').trigger('processStart');
},
hideOverlay: function () {
$('body').trigger('processStop');
},
showPaymentOverlay: function () {
$('#control_overlay_payment').show();
$('#ajax-payment').show();
},
hidePaymentOverlay: function () {
$('#control_overlay_payment').hide();
$('#ajax-payment').hide();
},
updateTotal: function(point) {
var listReward = {
'0': 'rewardpoint-earning',
'1': 'rewardpoint-spending',
'2': 'rewardpoint-use_point'
};
totals.isLoading(true);
$.ajax({
url: rewardpointConfig.urlUpdateTotal,
type: 'POST',
data: {'reward_sales_rule': 'rate', 'reward_sales_point': point},
complete: function (data) {
var arrDataReward = $.map($.parseJSON(data.responseText), function (value, index) {
return [value];
});
$.dataReward = arrDataReward;
var deferred = $.Deferred();
getPaymentInformation(deferred);
$.when(deferred).done(function () {
$.each(listReward, function (key, val) {
$('tr.' + val).show();
$('tr.' + val + ' td.amount span').text($.dataReward[key]);
})
totals.isLoading(false);
});
},
});
},
updateQty: function (itemId, type, qty) {
var params = {
itemId: itemId,
qty: qty,
updateType: type
};
var self = this;
this.showOverlay();
storage.post(
'onestepcheckout/quote/update',
JSON.stringify(params),
false
).done(
function (result) {
var miniCart = $('[data-block="minicart"]');
miniCart.trigger('contentLoading');
customerData.reload('cart', true);
miniCart.trigger('contentUpdated');
}
).fail(
function (result) {
}
).always(
function (result) {
if (result.error) {
alertPopup({
content: Translate(result.error),
autoOpen: true,
clickableOverlay: true,
focus: "",
actions: {
always: function(){
}
}
});
}
if(result.cartEmpty || result.is_virtual){
window.location.reload();
}else{
if (result.rewardpointsEarning) {
$('tr.rewardpoint-earning td.amount span').text(result.rewardpointsEarning);
}
if (result.rewardpointsSpending) {
$('tr.rewardpoint-spending td.amount span').text(result.rewardpointsSpending);
}
if (result.rewardpointsUsePoint) {
$('tr.rewardpoint-use_point td.amount span').text(result.rewardpointsUsePoint);
}
if (result.affiliateDiscount) {
$('tr td.amount span').each(function () {
if ($(this).data('th') == Translate('Affiliateplus Discount')) {
if (result.affiliateDiscount) {
$(this).text(priceUtils.formatPrice(result.affiliateDiscount, quote.getPriceFormat()));
$(this).show();
} else {
$(this).hide();
}
}
})
}
if (result.getRulesJson && window.checkoutConfig.isCustomerLoggedIn) {
var rewardSliderRules = $.parseJSON(result.getRulesJson).rate;
var $range = $("#range_reward_point");
var rewardpointConfig = result;
rewardpointConfig.checkMaxpoint = parseInt(rewardpointConfig.checkMaxpoint);
if(rewardpointConfig.checkMaxpoint){
self.updateTotal(rewardSliderRules.sliderOption.maxPoints);
$('#reward_sales_point').val(rewardSliderRules.sliderOption.maxPoints);
}
var slider = $range.data("ionRangeSlider");
slider.update({
grid:true,
grid_num:((rewardSliderRules.sliderOption.maxPoints<4)?rewardSliderRules.sliderOption.maxPoints:4),
min:rewardSliderRules.sliderOption.minPoints,
max:rewardSliderRules.sliderOption.maxPoints,
step:rewardSliderRules.sliderOption.pointStep,
from:((rewardpointConfig.checkMaxpoint)?rewardSliderRules.sliderOption.maxPoints:rewardpointConfig.usePoint),
onUpdate: function (data) {
if(rewardSliderRules.sliderOption.maxPoints == data.from){
$('#reward_max_points_used').attr('checked','checked');
}else{
$('#reward_max_points_used').removeAttr('checked');
}
$("#reward_sales_point").val(data.from);
self.updateTotal(data.from);
}
});
}
reloadShippingMethod();
getPaymentInformation().done(function () {
self.hideOverlay();
});
}
}
);
}
});
}
);
Template file
app/code/Netpower/OnePageCheckout/view/frontend/web/template/checkout/summary/item/details.html
<!--
/**
* Copyright 2019 Netpower, Inc. All rights reserved.
*/
-->
<div class="before_details">
<!-- ko foreach: getRegion('before_details') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!-- /ko -->
</div>
<div class="product-item-details">
<!-- ko foreach: getRegion('top_details') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!-- /ko -->
<div class="product-item-inner">
<div class="product-item-name" data-bind="text: $parent.name"></div>
</div>
<!-- ko foreach: getRegion('additional_details') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!-- /ko -->
<!-- ko if: (JSON.parse($parent.options).length > 0)-->
<div class="product options" data-bind="mageInit: {'collapsible':{'openedState': 'active'}}">
<span data-role="title" class="toggle"><!-- ko i18n: 'View Details' --><!-- /ko --></span>
<div data-role="content" class="content">
<strong class="subtitle"><!-- ko i18n: 'Options Details' --><!-- /ko --></strong>
<div class="item-options">
<!--ko foreach: JSON.parse($parent.options)-->
<dl>
<dt class="label" data-bind="text: label"></dt>
<!-- ko if: ($data.full_view)-->
<dd class="values" data-bind="html: full_view"></dd>
<!-- /ko -->
<!-- ko ifnot: ($data.full_view)-->
<dd class="values" data-bind="html: value"></dd>
<!-- /ko -->
</dl>
<!-- /ko -->
</div>
</div>
</div>
<!-- /ko -->
<!-- ko foreach: getRegion('bottom_details') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!-- /ko -->
</div>
<div class="details-qty">
<div class="product-item-head">
<span data-bind="i18n: 'Number of packages'"></span>
</div>
<div class="box-qty">
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
<!--<select name="qty" data-bind="value: $parent.qty, event :{change: function(){updateNewQty($parent)}}, foreach: new Array(30)">-->
<!--<option data-bind="text: $parent.getIndex($index()+1), value: $index()+1"></option>-->
<!--</select>-->
<div data-change-type="minus" class="osc-minus" data-bind="click: function(){minusQty($parent)}">-</div>
<input class="qty qty-item-display" data-bind="value: $parent.qty, event :{change: function(){updateNewQty($parent)}}">
<div data-change-type="add" class="osc-add" data-bind="click: function(){addQty($parent)}">+</div>
</div>
</div>
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
<div class="after_details">
<!-- ko foreach: getRegion('after_details') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!-- /ko -->
</div>
<div class="osc-delete" data-bind="click: function(){deleteItem($parent)}">
<span data-bind="i18n: 'Delete'"></span>
</div>
- Need override on theme (Not override on module)
- /<Vendor>/<THEME>...
1. Declare on require-js
2. create js file same path on require
EXAMPLE
define([
'jquery'
], function($){
'use strict';
return function () {
$.widget('mage.validation', $.mage.validation, {
_listenFormValidate: function() {
this.element.on('invalid-form.validate', this.listenFormValidateHandler);
}
});
return $.mage.validation;
};
});
<?php
/**
* Copyright Β© Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// @codingStandardsIgnoreFile
?>
<?php
/** @var \Magento\Catalog\Pricing\Render\FinalPriceBox $block */
/** ex: \Magento\Catalog\Pricing\Price\RegularPrice */
/** @var \Magento\Framework\Pricing\Price\PriceInterface $priceModel */
$priceModel = $block->getPriceType('regular_price');
$productId = $block->getSaleableItem()->getId();
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
//Load product by product id
$_product = $objectManager->create('Magento\Catalog\Model\Product')->load($productId);
/** ex: \Magento\Catalog\Pricing\Price\FinalPrice */
/** @var \Magento\Framework\Pricing\Price\PriceInterface $finalPriceModel */
$finalPriceModel = $block->getPriceType('final_price');
$idSuffix = $block->getIdSuffix() ? $block->getIdSuffix() : '';
$schema = ($block->getZone() == 'item_view') ? true : false;
==================== HERE ===============================================================
//var_dump($finalPriceModel->getAmount()->getValue());
//var_dump($priceModel->getAmount()->getValue());
//var_dump($this->helper('\Magento\Catalog\Helper\Data')->getTaxPrice($_product, $finalPriceModel->getAmount()->getValue()));
//var_dump($this->helper('\Magento\Catalog\Helper\Data')->getTaxPrice($_product, $priceModel->getAmount()->getValue()));
====================================================================================
?>
<?php if ($block->hasSpecialPrice()): ?>
<span class="special-price">
<?php /* @escapeNotVerified */ echo $block->renderAmount($finalPriceModel->getAmount(), [
'display_label' => __('Special Price'),
'price_id' => $block->getPriceId('product-price-' . $idSuffix),
'price_type' => 'finalPrice',
'include_container' => true,
'schema' => $schema
]); ?>
<span class="old-price">
<?php /* @escapeNotVerified */ echo $block->renderAmount($priceModel->getAmount(), [
'display_label' => __('Regular Price'),
'price_id' => $block->getPriceId('old-price-' . $idSuffix),
'price_type' => 'oldPrice',
'include_container' => true,
'skip_adjustments' => true
]); ?>
</span>
</span>
<?php else: ?>
<?php /* @escapeNotVerified */ echo $block->renderAmount($finalPriceModel->getAmount(), [
'price_id' => $block->getPriceId('product-price-' . $idSuffix),
'price_type' => 'finalPrice',
'include_container' => true,
'schema' => $schema
]); ?>
<?php endif; ?>
<?php if ($block->showMinimalPrice()): ?>
<?php if ($block->getUseLinkForAsLowAs()):?>
<a href="<?= /* @escapeNotVerified */ $block->getSaleableItem()->getProductUrl() ?>" class="minimal-price-link">
<?= /* @escapeNotVerified */ $block->renderAmountMinimal() ?>
</a>
<?php else:?>
<span class="minimal-price-link">
<?= /* @escapeNotVerified */ $block->renderAmountMinimal() ?>
</span>
<?php endif?>
<?php endif; ?>
Magento_ConfigurableProduct/templates/product/price/final_price.phtml
<?php
/**
* Copyright Β© Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// @codingStandardsIgnoreFile
?>
<?php
/** @var \Magento\ConfigurableProduct\Pricing\Render\FinalPriceBox$block */
/** @var \Magento\Framework\Pricing\Price\PriceInterface $priceModel */
$priceModel = $block->getPriceType('regular_price');
/** @var \Magento\Framework\Pricing\Price\PriceInterface $finalPriceModel */
$finalPriceModel = $block->getPriceType('final_price');
$idSuffix = $block->getIdSuffix() ? $block->getIdSuffix() : '';
$schema = ($block->getZone() == 'item_view') ? true : false;
?>
<span class="normal-price">
<?php
$arguments = [
'display_label' => __('As low as'),
'price_id' => $block->getPriceId('product-price-' . $idSuffix),
'price_type' => 'finalPrice',
'include_container' => true,
'schema' => $schema,
];
/* @noEscape */ echo $block->renderAmount($finalPriceModel->getAmount(), $arguments);
?>
</span>
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
<?php if ($block->hasSpecialPrice()): ?>
<span class="old-price sly-old-price no-display">
<?php /* @escapeNotVerified */ echo $block->renderAmount($priceModel->getAmount(), [
'display_label' => __('Regular Price'),
'price_id' => $block->getPriceId('old-price-' . $idSuffix),
'price_type' => 'oldPrice',
'include_container' => true,
'skip_adjustments' => true
]); ?>
</span>
<?php endif; ?>
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
<?php if ($block->showMinimalPrice()): ?>
<?php if ($block->getUseLinkForAsLowAs()):?>
<a href="<?= /* @escapeNotVerified */ $block->getSaleableItem()->getProductUrl() ?>" class="minimal-price-link">
<?= /* @escapeNotVerified */ $block->renderAmountMinimal() ?>
</a>
<?php else:?>
<span class="minimal-price-link">
<?= /* @escapeNotVerified */ $block->renderAmountMinimal() ?>
</span>
<?php endif?>
<?php endif; ?>
<?php
/**
* Copyright Β© Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// @codingStandardsIgnoreFile
?>
<?php
$productId = $block->getSaleableItem()->getId();
/** @var \Magento\ConfigurableProduct\Pricing\Render\FinalPriceBox$block */
/** @var \Magento\Framework\Pricing\Price\PriceInterface $priceModel */
$priceModel = $block->getPriceType('regular_price');
/** @var \Magento\Framework\Pricing\Price\PriceInterface $finalPriceModel */
$finalPriceModel = $block->getPriceType('final_price');
$idSuffix = $block->getIdSuffix() ? $block->getIdSuffix() : '';
$schema = ($block->getZone() == 'item_view') ? true : false;
?>
<span class="normal-price">
<?php
$arguments = [
'display_label' => __('As low as'),
'price_id' => $block->getPriceId('product-price-' . $idSuffix),
'price_type' => 'finalPrice',
'include_container' => true,
'schema' => $schema,
];
/* @noEscape */ echo $block->renderAmount($finalPriceModel->getAmount(), $arguments);
?>
</span>
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
<?php if ($block->hasSpecialPrice()): ?>
<?php
$finalPriceSales = $finalPriceModel->getAmount()->getValue();
$originalPriceSales = $priceModel->getAmount()->getValue();
$salePricesRule = (100 - round(($finalPriceSales/$originalPriceSales)*100));
echo $product_labels = '<div class="product-labels configurable price-rule js-configurable-price-rule-label-'.$productId.'" ><div class="product-label sale-label">'.'-'.$salePricesRule.'%'.'</div></div>';
?>
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
<span class="old-price sly-old-price no-display">
<?php /* @escapeNotVerified */ echo $block->renderAmount($priceModel->getAmount(), [
'display_label' => __('Regular Price'),
'price_id' => $block->getPriceId('old-price-' . $idSuffix),
'price_type' => 'oldPrice',
'include_container' => true,
'skip_adjustments' => true
]); ?>
</span>
<?php endif; ?>
<?php if ($block->showMinimalPrice()): ?>
<?php if ($block->getUseLinkForAsLowAs()):?>
<a href="<?= /* @escapeNotVerified */ $block->getSaleableItem()->getProductUrl() ?>" class="minimal-price-link">
<?= /* @escapeNotVerified */ $block->renderAmountMinimal() ?>
</a>
<?php else:?>
<span class="minimal-price-link">
<?= /* @escapeNotVerified */ $block->renderAmountMinimal() ?>
</span>
<?php endif?>
<?php endif; ?>
<script type="text/javascript">
require(['jquery'],
function($) {
var configurableProductSalePriceLabel = ".js-configurable-price-rule-label-" + "<?php echo $productId ?>";
var $productItemDetail = $(configurableProductSalePriceLabel).parent().parent();
var $productItemPhoto = $productItemDetail.siblings('.product-item-photo');
var $productLabelContainer = $productItemPhoto.children('.product-labels');
console.log($productLabelContainer.children('.product-label').hasClass('new-label'));
if($productLabelContainer.children('.product-label').hasClass('new-label')) {
$productLabelContainer.addClass("new-label-active");
}
})
</script>
INSTALL EXTENSION AMASTY PRODUCT LABEL
Example on BLF for shipping methods
app/code/Netpower/Blf/etc/adminhtml/system.xml
<?xml version="1.0" ?>
<!--
/**
* Copyright 2019 Netpower, Inc. All rights reserved.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
<system>
<tab id="netpower" sortOrder="0" translate="label">
<label>Netpower</label>
</tab>
<section id="blf" showInDefault="1" showInStore="1" showInWebsite="1" sortOrder="1"
translate="label">
<label>Blf</label>
<resource>Netpower_Blf::config_netpower_settings</resource>
<tab>netpower</tab>
<group id="shipping" showInDefault="1" showInStore="1" showInWebsite="1" sortOrder="10" translate="label">
<label>Shipping</label>
<field id="shipping_methods_custom_text" translate="label" sortOrder="10" showInDefault="1" showInWebsite="1"
showInStore="1">
<label>Shipping method and custom text</label>
<frontend_model>Netpower\Blf\Block\Adminhtml\System\Config\ShippingMethodTextCustom</frontend_model>
<backend_model>Magento\Config\Model\Config\Backend\Serialized\ArraySerialized</backend_model>
</field>
</group>
</section>
</system>
</config>
app/code/Netpower/Blf/Block/Adminhtml/System/Config/ShippingMethodTextCustom.php
<?php
/**
* Copyright 2019 Netpower. All rights reserved.
*/
namespace Netpower\Blf\Block\Adminhtml\System\Config;
use Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray;
/**
* Class TopAttributes
* @package Netpower\Lenspower\Block\Adminhtml\System\Config
*/
class ShippingMethodTextCustom extends AbstractFieldArray
{
protected $_itemRenderer;
protected $_itemRendererDefault;
/**
* @var bool
*/
protected $_addAfter = TRUE;
/**
* @var
*/
protected $_addButtonLabel;
/**
* Prepare to render the columns
*/
protected function _prepareToRender()
{
$this->addColumn(
'shipping_id',
[
'label' => __('Shipping methods'),
'renderer' => $this->_getShippingMethodRenderer()
]
);
$this->addColumn(
'attribute_label',
['label' => __('Description')]
);
$this->_addAfter = FALSE;
$this->_addButtonLabel = __('Add');
}
/**\
* @return template
*/
protected function _getShippingMethodRenderer() {
if (!$this->_itemRenderer) {
$this->_itemRenderer = $this->getLayout()->createBlock(
\Netpower\Blf\Block\Adminhtml\System\Config\Form\Field\shippingMethodsActive::class,
'',
[
'data' => ['is_render_to_js_template' => true]
]
);
}
return $this->_itemRenderer;
}
/**\
* @param \Magento\Framework\DataObject $row
* @throws \Magento\Framework\Exception\LocalizedException
*/
protected function _prepareArrayRow(\Magento\Framework\DataObject $row)
{
$options = [];
if ($row->getData('shipping_id')) {
$options['option_' . $this->_getShippingMethodRenderer()->calcOptionHash($row->getData('shipping_id'))] = 'selected="selected"';
}
$row->setData('option_extra_attrs', $options);
}
}
app/code/Netpower/Blf/Block/Adminhtml/System/Config/Form/Field/shippingMethodsActive.php
<?php
/**
* Copyright 2019 Netpower. All rights reserved.
*/
namespace Netpower\Blf\Block\Adminhtml\System\Config\Form\Field;
/**
* Class Attributes
* @package Netpower\Lenspower\Block\Adminhtml\System\Config\Form\Field
*/
class shippingMethodsActive extends \Magento\Framework\View\Element\Html\Select
{
/**
* @var \Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory
*/
protected $collectionFactory;
/**
* Attributes constructor.
* @param \Magento\Framework\View\Element\Context $context
* @param \Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory $collectionFactory
* @param array $data
*/
public function __construct(
\Magento\Framework\View\Element\Context $context,
array $data = []
)
{
parent::__construct(
$context,
$data
);
}
/**
* @return string
*/
public function _toHtml()
{
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$store = $objectManager->create('\Magento\Store\Model\StoreManagerInterface')->getStore();
/*
* Code to get list of active shipping methods
*/
$activeCarriers = $objectManager->create('\Magento\Shipping\Model\Config')->getActiveCarriers($store);
$shippingMethodsArray = array();
foreach ($activeCarriers as $shippingCode => $shippingModel) {
// $shippingTitle = $objectManager->create('\Magento\Framework\App\Config\ScopeConfigInterface')->getValue('carriers/' . $shippingCode . '/title');
$shippingName = $objectManager->create('\Magento\Framework\App\Config\ScopeConfigInterface')->getValue('carriers/' . $shippingCode . '/name');
$shippingMethodsArray[$shippingCode] = array(
'label' => $shippingName,
'value' => $shippingCode
);
$this->addOption($shippingCode, $shippingName);
}
return parent::_toHtml();
}
/**
* @param $value
* @return mixed
*/
public function setInputName($value)
{
return $this->setName($value);
}
}
EXAMPLE OF BLF with Front-end 29. and Back-end 28
app/code/Netpower/OnePageCheckout/view/frontend/web/template/checkout/shipping-method.html
<div class="custom-description-shipping-method">
<!-- ko foreach: $parent.getRegion('custom-description-shipping-method') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!-- /ko -->
</div>
app/code/Netpower/OnePageCheckout/view/frontend/layout/checkout_onepage_index.xml
<item name="shippingAddress" xsi:type="array">
<item name="children" xsi:type="array">
...
<item name="custom-description-shipping-method" xsi:type="array">
<item name="component" xsi:type="string">Netpower_OnePageCheckout/js/view/checkout/shipping-method-custom-description</item>
<item name="displayArea" xsi:type="string">custom-description-shipping-method</item>
</item>
</item>
component : file script contain define template file html
displayArea : Area to display template
app/code/Netpower/OnePageCheckout/view/frontend/web/js/view/checkout/shipping-method-custom-description.js
/**
* Copyright 2019 Netpower, Inc. All rights reserved.
*/
/*global define*/
define([
'jquery',
'underscore',
'uiComponent',
'ko',
], function ($,
_,
Component,
ko,
) {
'use strict';
var self;
return Component.extend({
defaults: {
template: 'Netpower_OnePageCheckout/checkout/shipping/shipping-method-custom-description'
},
isAddressFormVisible: ko.observable(addressList().length === 0),
visible: ko.observable(true),
shippingRateGroup: ko.observable(),
shippingRate: ko.observable(),
initialize: function () {
self = this;
this._super();
},
getCustomDescription: function(shippingCode) {
console.log(shippingCode);
// var shippingCustom = window.checkoutConfig.shipping.shippingMethodsCustomDescription;
// return shippingCustom[shippingCode];
}
});
});
app/code/Netpower/OnePageCheckout/view/frontend/web/template/checkout/shipping/shipping-method-custom-description.html
<div class="">
<p data-bind="text: getCustomDescription(getMethod())"></p>
</div>
1.app/code/Netpower/Lenspower/etc/widget.xml
<?xml version="1.0" ?>
<!--
/**
* Copyright 2019 Netpower, Inc. All rights reserved.
*/
-->
<widgets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:helloworld:Magento_Widget:etc/widget.xsd">
<widget class="Netpower\Lenspower\Block\Widget\MostOrder" id="np_most_order">
<label translate="true">Bestseller Products List</label>
<description translate="true">List of Best Selling Products</description>
<parameters>
<parameter name="productcount" xsi:type="text" visible="true" sort_order="1" >
<label translate="true">Product Count</label>
</parameter>
</parameters>
</widget>
</widgets>
2.app/code/Netpower/Lenspower/Block/Widget/MostOrder.php
<?php
namespace Netpower\Lenspower\Block\Widget;
use Magento\Catalog\Api\CategoryRepositoryInterface;
use Magento\Catalog\Block\Product\Context;
use Magento\Catalog\Model\Layer\Resolver;
use Magento\Framework\Data\Helper\PostHelper;
use Magento\Framework\Url\Helper\Data;
use Magento\Sales\Model\ResourceModel\Report\Bestsellers\CollectionFactory as BestSellersCollectionFactory;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
/**
* Best Seller products widget
*/
class MostOrder extends \Magento\Catalog\Block\Product\ListProduct implements \Magento\Widget\Block\BlockInterface
{
protected $_template = 'Netpower_Lenspower::catalog/product/view/mostOrder.phtml';
/**
* Default value for products count that will be shown
*/
const DEFAULT_PRODUCTS_COUNT = 10;
const DEFAULT_IMAGE_WIDTH = 150;
const DEFAULT_IMAGE_HEIGHT = 150;
/**
* Products count
*
* @var int
*/
protected $_productsCount;
/**
* @var \Magento\Framework\App\Http\Context
*/
protected $httpContext;
protected $_resourceFactory;
/**
* Catalog product visibility
*
* @var \Magento\Catalog\Model\Product\Visibility
*/
protected $_catalogProductVisibility;
/**
* Product collection factory
*
* @var \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory
*/
protected $_productCollectionFactory;
/**
* Image helper
*
* @var Magento\Catalog\Helper\Image
*/
protected $_imageHelper;
/**
* @var \Magento\Checkout\Helper\Cart
*/
protected $_cartHelper;
/**
* @var BestSellersCollectionFactory
*/
protected $_bestSellersCollectionFactory;
public function __construct(
Context $context,
PostHelper $postDataHelper,
Resolver $layerResolver,
CategoryRepositoryInterface $categoryRepository,
Data $urlHelper,
BestSellersCollectionFactory $bestSellersCollectionFactory,
CollectionFactory $productCollectionFactory,
array $data = []
)
{
$this->_bestSellersCollectionFactory = $bestSellersCollectionFactory;
$this->_productCollectionFactory = $productCollectionFactory;
parent::__construct($context, $postDataHelper, $layerResolver, $categoryRepository, $urlHelper, $data);
}
/**
* Image helper Object
*/
public function imageHelperObj()
{
return $this->_imageHelper;
}
/**
* get collection of best-seller products
* @return mixed
*/
public function getProductCollection()
{
$productIds = [];
$bestSellers = $this->_bestSellersCollectionFactory->create()
->setPeriod('month');
foreach ($bestSellers as $product) {
$productIds[] = $product->getProductId();
}
$collection = $this->_productCollectionFactory->create()->addIdFilter($productIds);
$collection->addMinimalPrice()
->addFinalPrice()
->addTaxPercents()
->addAttributeToSelect('*')
->addStoreFilter($this->getStoreId())->setPageSize($this->getProductsCount());
return $collection;
}
/**
* Get the configured limit of products
* @return int
*/
public function getProductLimit()
{
if ($this->getData('productcount') == '') {
return DEFAULT_PRODUCTS_COUNT;
}
return $this->getData('productcount');
}
/**
* Get the add to cart url
* @return string
*/
public function getAddToCartUrl($product, $additional = [])
{
return $this->_cartHelper->getAddUrl($product, $additional);
}
/**
* Return HTML block with price
*
* @param \Magento\Catalog\Model\Product $product
* @param string $priceType
* @param string $renderZone
* @param array $arguments
* @return string
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
public function getProductPriceHtml(
\Magento\Catalog\Model\Product $product,
$priceType = null,
$renderZone = \Magento\Framework\Pricing\Render::ZONE_ITEM_LIST,
array $arguments = []
)
{
if (!isset($arguments['zone'])) {
$arguments['zone'] = $renderZone;
}
$arguments['zone'] = isset($arguments['zone'])
? $arguments['zone']
: $renderZone;
$arguments['price_id'] = isset($arguments['price_id'])
? $arguments['price_id']
: 'old-price-' . $product->getId() . '-' . $priceType;
$arguments['include_container'] = isset($arguments['include_container'])
? $arguments['include_container']
: true;
$arguments['display_minimal_price'] = isset($arguments['display_minimal_price'])
? $arguments['display_minimal_price']
: true;
/** @var \Magento\Framework\Pricing\Render $priceRender */
$priceRender = $this->getLayout()->getBlock('product.price.render.default');
$price = '';
if ($priceRender) {
$price = $priceRender->render(
\Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE,
$product,
$arguments
);
}
return $price;
}
}
3.app/code/Netpower/Lenspower/view/frontend/templates/catalog/product/view/mostOrder.phtml
<?php
/**
* Copyright Β© 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
use Magento\Framework\App\Action\Action;
// @codingStandardsIgnoreFile
?>
<?php
/**
* Product list template
*
* @var $block \Magento\Catalog\Block\Product\ListProduct
*/
?>
<?php
$_productCollection = $block->getProductCollection();
$_helper = $this->helper('Magento\Catalog\Helper\Output');
$_imagehelper = $this->helper('Magento\Catalog\Helper\Image');
// Daily deal Helper
$dailydealhelper=$this->helper('Smartwave\Dailydeals\Helper\Data');
$_category_config = $this->helper('Smartwave\Porto\Helper\Data')->getConfig('porto_settings/category');
$_category_grid_config = $this->helper('Smartwave\Porto\Helper\Data')->getConfig('porto_settings/category_grid');
$_product_label_config = $this->helper('Smartwave\Porto\Helper\Data')->getConfig('porto_settings/product_label');
$move_actions = "";
$flex_grid = "";
$_lazyload = $this->helper('Smartwave\Porto\Helper\Data')->getConfig('porto_settings/optimization/lazyload');
?>
<?php $iterator = 1; ?>
<?php if (!$_productCollection->count()): ?>
<div class="message info empty"><div><?php echo __('We can\'t find products matching the selection.') ?></div></div>
<?php else: ?>
<?php echo $block->getToolbarHtml() ?>
<?php echo $block->getAdditionalHtml() ?>
<?php
if ($block->getMode() == 'grid') {
$viewMode = 'grid';
$image = 'category_page_grid';
$hover_image = 'category_page_grid-hover';
$showDescription = false;
$templateType = \Magento\Catalog\Block\Product\ReviewRendererInterface::SHORT_VIEW;
$columns = 'columns'.$_category_grid_config['columns'];
$move_actions = $_category_grid_config['move_actions'];
if(isset($_category_grid_config['flex_grid']) && $_category_grid_config['flex_grid'])
$flex_grid = "flex-grid";
} else {
$viewMode = 'list';
$image = 'category_page_list';
$hover_image = 'category_page_list-hover';
$showDescription = true;
$templateType = \Magento\Catalog\Block\Product\ReviewRendererInterface::FULL_VIEW;
$columns = '';
}
$image_width = ($_category_config['ratio_width'])?$_category_config['ratio_width']:300;
$image_height = ($_category_config['ratio_height'])?$_category_config['ratio_height']:300;
if($_category_config['aspect_ratio'])
$image_height = $image_width;
?>
<div class="products wrapper <?php echo $viewMode; ?> <?php echo $columns; ?> <?php echo $flex_grid; ?> products-<?php echo $viewMode; ?>">
<?php $iterator = 1; ?>
<ol class="products list items product-items <?php if(isset($_category_config['qty_field']) && $_category_config['qty_field']):?>has-qty<?php endif;?>">
<?php /** @var $_product \Magento\Catalog\Model\Product */ ?>
<?php foreach ($_productCollection as $_product): ?>
<?php echo($iterator++ == 1) ? '<li class="item product product-item">' : '</li><li class="item product product-item">' ?>
<div class="product-item-info" data-container="product-grid">
<?php // Product Image ?>
<div class="product photo product-item-photo">
<a href="<?php echo $_product->getProductUrl() ?>" tabindex="-1">
<?php
if($_category_config['aspect_ratio'])
$productImage = $_imagehelper->init($_product, $image)->constrainOnly(FALSE)->keepAspectRatio(TRUE)->keepFrame(FALSE)->resize($image_width);
else
$productImage = $_imagehelper->init($_product, $image)->resize($image_width, $image_height);
$productImageUrl = $productImage->getUrl();
?>
<img class="product-image-photo default_image <?php if(!$_lazyload): ?>porto-lazyload<?php endif;?>" <?php if(!$_lazyload): ?>data-<?php endif; ?>src="<?php echo $productImageUrl; ?>" width="<?php echo $image_width; ?>" height="<?php echo $image_height; ?>"/>
<?php if($_category_config['alternative_image']): ?>
<?php
if($_category_config['aspect_ratio'])
$productHoverImage = $_imagehelper->init($_product, $hover_image)->constrainOnly(FALSE)->keepAspectRatio(TRUE)->keepFrame(FALSE)->resize($image_width);
else
$productHoverImage = $_imagehelper->init($_product, $hover_image)->resize($image_width, $image_height);
$productHoverImageUrl = $productHoverImage->getUrl();
?>
<?php if($productImageUrl != str_replace("/thumbnail/","/small_image/",$productHoverImageUrl)): ?>
<img class="product-image-photo hover_image" src="<?php echo $productHoverImageUrl; ?>"/>
<?php endif; ?>
<?php endif; ?>
</a>
<?php
$product_label = "";
if($_product_label_config['sale_label']) {
$orgprice = $_product->getPrice();
$specialprice = $_product->getSpecialPrice();
$specialfromdate = $_product->getSpecialFromDate();
$specialtodate = $_product->getSpecialToDate();
$today = time();
if(!$specialprice)
$specialprice = $orgprice;
if($specialprice < $orgprice) {
if((is_null($specialfromdate) && is_null($specialtodate)) || ($today >= strtotime($specialfromdate) && is_null($specialtodate)) || ($today <= strtotime($specialtodate) && is_null($specialfromdate)) || ($today >= strtotime($specialfromdate) && $today <= strtotime($specialtodate))){
if($_product_label_config['sale_label_percent']) {
$save_percent = 100-round(($specialprice/$orgprice)*100);
$product_label .= '<div class="product-label sale-label">'.'-'.$save_percent.'%'.'</div>';
} else {
$product_label .= '<div class="product-label sale-label">'.$_product_label_config['sale_label_text'].'</div>';
}
}
}
}
if($_product_label_config['new_label']) {
$now = date("Y-m-d");
$newsFrom= substr($_product->getData('news_from_date'),0,10);
$newsTo= substr($_product->getData('news_to_date'),0,10);
if ($newsTo != '' || $newsFrom != ''){
if (($newsTo != '' && $newsFrom != '' && $now>=$newsFrom && $now<=$newsTo) || ($newsTo == '' && $now >=$newsFrom) || ($newsFrom == '' && $now<=$newsTo)) {
$product_label .= '<div class="product-label new-label">'.$_product_label_config['new_label_text'].'</div>';
}
}
}
if($product_label)
echo '<div class="product-labels">'.$product_label.'</div>';
?>
<!-- Dailydeal Product data -->
<?php if($dailydealhelper->isDealProduct($_product->getId())) : ?>
<input type="hidden" id="todate_<?php echo $iterator; ?>" value="<?php echo $dailydealhelper->getDailydealToDate($_product->getSku()); ?>" >
<input type="hidden" id="fromdate_<?php echo $iterator; ?>" value="<?php echo $dailydealhelper->getDailydealFromDate($_product->getSku()); ?>">
<div class="sw-dailydeal-wrapper" style="display:none;">
<div class="sw-dailydeal">
<p id="expired_<?php echo $iterator; ?>"></p>
<div class="countdowncontainer_<?php echo $iterator; ?>" style="display:none;">
<span class="dailydeal-label">
<?php echo __('Ends In:'); ?>
</span>
<span class="number-wrapper">
<div class="line"></div>
<span class="number day"><p id="countdown_days_<?php echo $iterator; ?>"></p></span>
<div class="caption"><?php echo __('Day(s), '); ?></div>
</span>
<span class="number-wrapper">
<div class="line"></div>
<span class="number hour"><p id="countdown_hours_<?php echo $iterator; ?>"></p></span>
<div class="caption">:</div>
</span>
<span class="number-wrapper">
<div class="line"></div>
<span class="number min"><p id="countdown_minutes_<?php echo $iterator; ?>"></p></span>
<div class="caption">:</div>
</span>
<span class="number-wrapper">
<div class="line"></div>
<span class="number sec"><p id="countdown_seconds_<?php echo $iterator; ?>"></p></span>
<div class="caption"></div>
</span>
</div>
</div>
</div>
<?php endif; ?>
<!-- Dailydeal Product End -->
<?php if($_category_config['actions'] && $move_actions): ?>
<div class="product-item-inner">
<div class="product actions product-item-actions">
<div class="actions-primary">
<?php if ($_product->isSaleable()): ?>
<?php $postParams = $block->getAddToCartPostParams($_product); ?>
<form data-role="tocart-form" action="<?php echo $postParams['action']; ?>" method="post">
<input type="hidden" name="product" value="<?php echo $postParams['data']['product']; ?>">
<input type="hidden" name="<?php echo Action::PARAM_NAME_URL_ENCODED; ?>" value="<?php echo $postParams['data'][Action::PARAM_NAME_URL_ENCODED]; ?>">
<?php if(isset($_category_config['qty_field']) && $_category_config['qty_field']):?>
<div class="qty-box">
<a href="javascript:void(0)" class="qtyminus"><i class="porto-icon-minus"></i></a>
<input type="text" name="qty" id="qty" maxlength="12" value="<?php /* @escapeNotVerified */ echo $block->getProductDefaultQty() * 1 ?>" title="<?php /* @escapeNotVerified */ echo __('Qty') ?>" class="input-text qty" data-validate="<?php echo $block->escapeHtml(json_encode($block->getQuantityValidators())) ?>"/>
<a href="javascript:void(0)" class="qtyplus"><i class="porto-icon-plus"></i></a>
</div>
<?php endif;?>
<?php echo $block->getBlockHtml('formkey')?>
<button type="submit"
title="<?php echo $block->escapeHtml(__('Add to Cart')); ?>"
class="action tocart primary">
<span><?php echo __('Add to Cart') ?></span>
</button>
</form>
<?php else: ?>
<?php if ($_product->getIsSalable()): ?>
<div class="stock available"><span><?php echo __('In stock') ?></span></div>
<?php else: ?>
<div class="stock unavailable"><span><?php echo __('Out of stock') ?></span></div>
<?php endif; ?>
<?php endif; ?>
</div>
<?php if ($block->getMode() == 'grid'): ?>
<?php if($_category_config['addtowishlist']): ?>
<?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllow()): ?>
<a href="#"
class="action towishlist actions-secondary"
title="<?php echo $block->escapeHtml(__('Add to Wish List')); ?>"
aria-label="<?php echo $block->escapeHtml(__('Add to Wish List')); ?>"
data-post='<?php echo $block->getAddToWishlistParams($_product); ?>'
data-action="add-to-wishlist"
role="button">
<span><?php echo __('Add to Wish List') ?></span>
</a>
<?php endif; ?>
<?php endif; ?>
<?php endif; ?>
<?php if($_category_config['addtocompare']): ?>
<?php
$compareHelper = $this->helper('Magento\Catalog\Helper\Product\Compare');
?>
<a href="#"
class="action tocompare actions-secondary"
title="<?php echo $block->escapeHtml(__('Add to Compare')); ?>"
aria-label="<?php echo $block->escapeHtml(__('Add to Compare')); ?>"
data-post='<?php echo $compareHelper->getPostDataParams($_product); ?>'
role="button">
<span><?php echo __('Add to Compare') ?></span>
</a>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
</div>
<div class="product details product-item-details">
<?php
$_productNameStripped = $block->stripTags($_product->getName(), null, true);
?>
<?php if(!$_category_grid_config['move_title']):?>
<strong class="product name product-item-name">
<a class="product-item-link"
href="<?php echo $_product->getProductUrl() ?>">
<?php echo $_helper->productAttribute($_product, $_product->getName(), 'name'); ?>
</a>
</strong>
<?php endif;?>
<?php if($_category_config['rating_star']): ?>
<?php
$review_html = $block->getReviewsSummaryHtml($_product, $templateType);
?>
<?php if($review_html): ?>
<?php echo $review_html; ?>
<?php else: ?>
<div class="product-reviews-summary short">
<div class="rating-summary">
<span class="label"><span>Rating:</span></span>
<div class="rating-result" title="0%">
<span style="width:0"><span>0%</span></span>
</div>
</div>
</div>
<?php endif; ?>
<?php endif; ?>
<?php if($_category_grid_config['move_title']):?>
<strong class="product name product-item-name">
<a class="product-item-link"
href="<?php echo $_product->getProductUrl() ?>">
<?php echo $_helper->productAttribute($_product, $_product->getName(), 'name'); ?>
</a>
</strong>
<?php endif;?>
<?php if ($showDescription):?>
<div class="product description product-item-description">
<?php echo $_helper->productAttribute($_product, $_product->getShortDescription(), 'short_description') ?>
<a href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $_productNameStripped ?>"
class="action more"><?php echo __('Learn More') ?></a>
</div>
<?php endif; ?>
<?php if($_category_config['product_price']): ?>
<?php echo $block->getProductPrice($_product) ?>
<?php endif; ?>
<?php echo $block->getProductDetailsHtml($_product); ?>
<?php if($_category_config['actions'] && !$move_actions): ?>
<div class="product-item-inner">
<div class="product actions product-item-actions">
<?php if ($block->getMode() == 'grid'): ?>
<?php if($_category_config['addtowishlist']): ?>
<?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllow()): ?>
<a href="#"
class="action towishlist actions-secondary <?php if(isset($_category_config['qty_field']) && $_category_config['qty_field']):?>has-qty<?php endif;?>"
title="<?php echo $block->escapeHtml(__('Add to Wish List')); ?>"
aria-label="<?php echo $block->escapeHtml(__('Add to Wish List')); ?>"
data-post='<?php echo $block->getAddToWishlistParams($_product); ?>'
data-action="add-to-wishlist"
role="button">
<span><?php echo __('Add to Wish List') ?></span>
</a>
<?php endif; ?>
<?php endif; ?>
<?php endif; ?>
<div class="actions-primary">
<?php if ($_product->isSaleable()): ?>
<?php $postParams = $block->getAddToCartPostParams($_product); ?>
<form data-role="tocart-form" action="<?php echo $postParams['action']; ?>" method="post">
<input type="hidden" name="product" value="<?php echo $postParams['data']['product']; ?>">
<input type="hidden" name="<?php echo Action::PARAM_NAME_URL_ENCODED; ?>" value="<?php echo $postParams['data'][Action::PARAM_NAME_URL_ENCODED]; ?>">
<?php if(isset($_category_config['qty_field']) && $_category_config['qty_field']):?>
<div class="qty-box">
<a href="javascript:void(0)" class="qtyminus"><i class="porto-icon-minus"></i></a>
<input type="text" name="qty" id="qty" maxlength="12" value="<?php /* @escapeNotVerified */ echo $block->getProductDefaultQty() * 1 ?>" title="<?php /* @escapeNotVerified */ echo __('Qty') ?>" class="input-text qty" data-validate="<?php echo $block->escapeHtml(json_encode($block->getQuantityValidators())) ?>"/>
<a href="javascript:void(0)" class="qtyplus"><i class="porto-icon-plus"></i></a>
</div>
<?php endif;?>
<?php echo $block->getBlockHtml('formkey')?>
<button type="submit"
title="<?php echo $block->escapeHtml(__('Add to Cart')); ?>"
class="action tocart primary">
<span><?php echo __('Add to Cart') ?></span>
</button>
</form>
<?php else: ?>
<?php if ($_product->getIsSalable()): ?>
<div class="stock available"><span><?php echo __('In stock') ?></span></div>
<?php else: ?>
<div class="stock unavailable"><span><?php echo __('Out of stock') ?></span></div>
<?php endif; ?>
<?php endif; ?>
</div>
<?php if ($block->getMode() != 'grid'): ?>
<?php if($_category_config['addtowishlist']): ?>
<?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllow()): ?>
<a href="#"
class="action towishlist actions-secondary <?php if(isset($_category_config['qty_field']) && $_category_config['qty_field']):?>has-qty<?php endif;?>"
title="<?php echo $block->escapeHtml(__('Add to Wish List')); ?>"
aria-label="<?php echo $block->escapeHtml(__('Add to Wish List')); ?>"
data-post='<?php echo $block->getAddToWishlistParams($_product); ?>'
data-action="add-to-wishlist"
role="button">
<span><?php echo __('Add to Wish List') ?></span>
</a>
<?php endif; ?>
<?php endif; ?>
<?php endif; ?>
<?php if($_category_config['addtocompare']): ?>
<?php
$compareHelper = $this->helper('Magento\Catalog\Helper\Product\Compare');
?>
<a href="#"
class="action tocompare actions-secondary <?php if(isset($_category_config['qty_field']) && $_category_config['qty_field']):?>has-qty<?php endif;?>"
title="<?php echo $block->escapeHtml(__('Add to Compare')); ?>"
aria-label="<?php echo $block->escapeHtml(__('Add to Compare')); ?>"
data-post='<?php echo $compareHelper->getPostDataParams($_product); ?>'
role="button">
<span><?php echo __('Add to Compare') ?></span>
</a>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
</div>
</div>
<?php echo($iterator == count($_productCollection)+1) ? '</li>' : '' ?>
<?php endforeach; ?>
</ol>
</div>
<?php if(isset($_category_grid_config['infinite_scroller']) && $_category_grid_config['infinite_scroller']):?>
<div class="infinite-loader"><div class="loading"><?php echo __("Loading ..."); ?></div><a href="javascript:void(0)" class="btn-load-more"><?php echo __("Load More ..."); ?></a></div>
<?php endif;?>
<?php echo $block->getToolbarHtml() ?>
<?php if ($block->getMode() == 'grid'): ?>
<script type="text/javascript">
require([
'jquery'
], function ($) {
$('.main .products.grid .product-items li.product-item:nth-child(2n)').addClass('nth-child-2n');
$('.main .products.grid .product-items li.product-item:nth-child(2n+1)').addClass('nth-child-2np1');
$('.main .products.grid .product-items li.product-item:nth-child(3n)').addClass('nth-child-3n');
$('.main .products.grid .product-items li.product-item:nth-child(3n+1)').addClass('nth-child-3np1');
$('.main .products.grid .product-items li.product-item:nth-child(4n)').addClass('nth-child-4n');
$('.main .products.grid .product-items li.product-item:nth-child(4n+1)').addClass('nth-child-4np1');
$('.main .products.grid .product-items li.product-item:nth-child(5n)').addClass('nth-child-5n');
$('.main .products.grid .product-items li.product-item:nth-child(5n+1)').addClass('nth-child-5np1');
$('.main .products.grid .product-items li.product-item:nth-child(6n)').addClass('nth-child-6n');
$('.main .products.grid .product-items li.product-item:nth-child(6n+1)').addClass('nth-child-6np1');
$('.main .products.grid .product-items li.product-item:nth-child(7n)').addClass('nth-child-7n');
$('.main .products.grid .product-items li.product-item:nth-child(7n+1)').addClass('nth-child-7np1');
$('.main .products.grid .product-items li.product-item:nth-child(8n)').addClass('nth-child-8n');
$('.main .products.grid .product-items li.product-item:nth-child(8n+1)').addClass('nth-child-8np1');
});
</script>
<?php endif; ?>
<?php endif; ?>
<script type="text/javascript">
require([
'jquery'
], function ($) {
// Timer for LEFT time for Dailydeal product
var _second = 1000;
var _minute = _second * 60;
var _hour = _minute * 60;
var _day = _hour * 24;
var timer;
function showRemaining(currentdate)
{
var count;
for (count = 2; count <= <?php echo $iterator; ?>; count++)
{
// get Value of dailydeal product
var cid='countdown_'+count;
var daysid='countdown_days_'+count;
var hoursid='countdown_hours_'+count;
var minutesid='countdown_minutes_'+count;
var secondsid='countdown_seconds_'+count;
var startdateid='fromdate_'+count;
var id='todate_'+count;
var enddate = new Date($('#'+id).val());
var dealstartdate=new Date($('#'+startdateid).val());
// Get Current Date from magentodatetime
var currentdate=new Date(currentdate);
//Get Difference between Two dates
var distance = enddate - currentdate;
$('.sw-dailydeal-wrapper').show();
if (distance < 0) {
// clearInterval(timer);
$('#expired_'+count).html("<span style='font-size:25px; color:#000;'>EXPIRED!<span>");
} else if(dealstartdate > currentdate) {
$('.countdowncontainer_'+count).hide();
var msg="<span style='font-size:15px; color:#000;'> Coming Soon..<br>Deal Start at:<br>"+$('#'+startdateid).val()+"<span>";
$('#expired_'+count).html(msg);
} else {
var days = Math.floor(distance / _day);
var hours = Math.floor((distance % _day) / _hour);
var minutes = Math.floor((distance % _hour) / _minute);
var seconds = Math.floor((distance % _minute) / _second);
if(hours < 10)
hours = "0" + hours;
if(minutes < 10)
minutes = "0" + minutes;
if(seconds < 10)
seconds = "0" + seconds;
$('.countdowncontainer_'+count).show();
$('#'+daysid).html(days);
$('#'+hoursid).html(hours);
$('#'+minutesid).html(minutes);
$('#'+secondsid).html(seconds);
}
}
}
//Set date as magentodatetime
var date = new Date('<?php echo $dailydealhelper->getcurrentDate() ?>');
var day = date.getDate();
var month = date.getMonth();
var year = date.getFullYear();
var hours = date.getHours();
var minutes = "0" + date.getMinutes();
var seconds = "0" + date.getSeconds();
var fulldate = year+'-'+(month+1)+'-'+day+' '+hours + ':' + minutes.substr(minutes.length-2) + ':' + seconds.substr(seconds.length-2);
// Set Interval
timer = setInterval(function()
{
date.setSeconds(date.getSeconds() + 1);
var month=date.getMonth();
var currentdatetime=date.getFullYear()+"-"+(month+1)+"-"+date.getDate()+" "+date.getHours()+":"+date.getMinutes()+":"+date.getSeconds();
showRemaining(currentdatetime);
}, 1000);
});
</script>
<?php
echo $block->getChildHtml('filter_toggle');
?>
4.Add widget on admin
Add widget by WYSIWYG > Choose name of widget was created
app/design/frontend/Webbhuset/Holte/Magento_Theme/templates/html/copyright.phtml
<?php
/**
* Copyright Β© Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
?>
<small class="copyright">
<span><?= /* @escapeNotVerified */ preg_replace('/(^|\s)(\d{4})(\s|$)/m', " ".date('Y'). " ", $block->getCopyright()); ?></span>
</small>
1. app/design/frontend/<your_vendor_name>/<your_theme_name>/web/css/source/_typography.less
copy from vendor/magento/theme-frontend-blank/web/css/source/_typography.less
2. app/design/frontend/<your_vendor_name>/<your_theme_name>/web/css/source/_variables.less
copy from vendor/magento/theme-frontend-luma/web/css/source/_variables.less
app/design/frontend/<your_vendor_name>/<your_theme_name>/web/css/source/_typography.less
// /**
// * Copyright Β© Magento, Inc. All rights reserved.
// * See COPYING.txt for license details.
// */
//
// Common
// _____________________________________________
& when (@media-common = true) {
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
GOOGLE FONT : <link href="https://fonts.googleapis.com/css?family=Manjari&display=swap" rel="stylesheet">
copy https://fonts.googleapis.com/css?family=Manjari and path to url to get code
paste code above to override code below.
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
.lib-font-face(
@family-name: @font-family-name__base,
@font-path: '@{baseDir}fonts/opensans/light/opensans-300',
@font-weight: 300,
@font-style: normal
);
.lib-font-face(
@family-name: @font-family-name__base,
@font-path: '@{baseDir}fonts/opensans/regular/opensans-400',
@font-weight: 400,
@font-style: normal
);
.lib-font-face(
@family-name: @font-family-name__base,
@font-path: '@{baseDir}fonts/opensans/semibold/opensans-600',
@font-weight: 600,
@font-style: normal
);
.lib-font-face(
@family-name: @font-family-name__base,
@font-path: '@{baseDir}fonts/opensans/bold/opensans-700',
@font-weight: 700,
@font-style: normal
);
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
}
//
// Desktop
// _____________________________________________
.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
h1 {
.lib-css(font-size, @h1__font-size-desktop);
.lib-css(margin-bottom, @h1__margin-bottom__desktop);
}
}
//
// Common
// _____________________________________________
& when (@media-common = true) {
.items {
.lib-list-reset-styles();
}
}
app/design/frontend/<your_vendor_name>/<your_theme_name>/web/css/source/_variables.less
// /**
// * Copyright Β© Magento, Inc. All rights reserved.
// * See COPYING.txt for license details.
// */
//
// Luma theme variables
// _____________________________________________
//
// Typography
// ---------------------------------------------
// Fonts
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
GOOGLE FONT : font-family: 'Manjari', sans-serif;
fix same font-family of google
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
@font-family-name__base: 'Manjari';
@font-family__base: @font-family-name__base, @font-family__sans-serif;
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// Colors nesting
@page__background-color: @color-white;
//
// Icons
// ---------------------------------------------
@icon-success: '\e60e';
@icon-error: '\e61f';
@icon-edit: '\e601';
@icon-print: '\e624';
@icon-star-empty: '\e625';
@icon-download: '\e626';
@icon-private: '\e629';
@icon-present: '\e62a';
@icon-gift-registry: '\e62b';
@icon-calendar__font-size: 23px;
//
// Sidebar
// ---------------------------------------------
@sidebar__background-color: @color-white-smoke; // Used in cart sidebar, Checkout sidebar, Tier Prices, My account navigation, Rating block background
//
// Sidebar blocks
// ---------------------------------------------
@block-items__counter__color: @color-gray43;
php bin/magento setup:upgrade
php bin/magento cache:clean
https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/css-topics/css_debug.html
https://aureatelabs.com/magento-2/how-to-use-grunt-in-magento-2/
cp package.json.sample package.json &&
cp Gruntfile.js.sample Gruntfile.js &&
cp grunt-config.json.sample grunt-config.json &&
npm install &&
npm update
dev/tools/grunt/configs/local-themes.js
/**
* Copyright Β© Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
'use strict';
/**
* Define Themes
*
* area: area, one of (frontend|adminhtml|doc),
* name: theme name in format Vendor/theme-name,
* locale: locale,
* files: [
* 'css/styles-m',
* 'css/styles-l'
* ],
* dsl: dynamic stylesheet language (less|sass)
*
*/
module.exports = {
grunt: {
area: 'frontend',
name: 'Hieu/Grunt',
locale: 'en_US',
files: [
'css/hieu'
],
dsl: 'less'
}
};
app/design/frontend/Hieu/Grunt/web/css/hieu.less
app/design/frontend/Hieu/Grunt/Magento_Theme/layout/default.xml
<?xml version="1.0"?>
<!--
/**
* Copyright Β© Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<page layout="3columns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<head>
<css src="css/hieu.css" />
</head>
</page>
grunt clean: This command removes static files related to your theme in both pub/static and var directories.
grunt exec: This one republishes source files symlinks to
pub/static/frontend/<Vendor>/<theme>/<locale>
grunt less: This command compiles all the css file using the symlinks in this location
pub/static/frontend/<Vendor>/<theme>/<locale>
grunt watch: This command is used to start the grunt tool to track the changes done in the main files like .less and re-compiles into CSS files.
grunt clean && grunt exec && grunt less && grunt watch
1. npm install -g livereload
2. install LiveReload browser extension Chrome
3. Create file livereload.js in pub/
4. default.xml
<?xml version="1.0"?>
<!--
/**
* Copyright Β© Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<page layout="3columns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<head>
<css src="css/hieu-one.css" />
<script src="http://magento.local:35729/livereload.js" src_type="url"></script>
// url:port/livereload.js
</head>
</page>
5. Check result : magento.local:35729/
It'll show :
tinylr "Welcome"
version "0.2.1"
6. Grunt watch and change file to see result
$block->getViewFileUrl('images/demo.jpg');
php bin/magento i18n:collect-phrases --output="app/design/frontend/<Vendor>/<Theme>/i18n/en_US.csv" app/design/frontend/<Vendor>/<Theme>
app/design/frontend///Magento_Theme/layout/default.xml
<referenceBlock name="header.links">
<block class="Magento\Framework\View\Element\Html\Link" name="add-new-header-link" after="-">
<arguments>
<argument name="label" xsi:type="string" translate="true">Contact Us</argument>
<argument name="path" xsi:type="string" translate="true">contact-us</argument>
</arguments>
</block>
</referenceBlock>
@desktop: 1200px;
@tablet: 991px;
@phone: 767px;
@small-desktop-max: (@desktop - 1);
@small-desktop-min: (@tablet + 1);
@tablet-min: (@phone + 1);
@screen-desktop: ~"only screen and (min-width: @{desktop})";
@screen-small-desktop : ~"only screen and (min-width: @{small-desktop-min}) and (max-width: @{small-desktop-max})";
@screen-tablet: ~"only screen and (min-width: @{tablet-min}) and (max-width: @{tablet})";
@screen-phone: ~"only screen and (max-width: @{phone})";
@media @screen-desktop {width: 100%}