Skip to content
Merged

Dev #346

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
== Changelog ==
= 7.0.4 - Jul 15, 2025 =
- Improved compatibility with the Jetpack plugin to ensure storefront scripts load correctly when 'Defer Non-Essential JavaScript' is enabled.
- Applied minor fixes and general improvements for better performance and stability.

= 7.0.3 - Jun 24, 2025 =
- Internal improvements and minor fixes for Gutenberg ecommerce blocks.

Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,25 +37,25 @@ With Ecwid, you can include your ecommerce shop on multiple websites, blogs, soc

### Mobile Responsive Design

Ecwid works great on any Wordpress site, especially those running on mobile-optimized themes. Your online store looks perfect on smartphones and automatically adapts to your customer’s screen size: laptops, tablets, smart TVs or smart watches. Check out this [demo](https://ecwid.to/ecwid-demo-store)
Ecwid works great on any Wordpress site, especially those running on mobile-optimized themes. Your online store looks perfect on smartphones and automatically adapts to your customer’s screen size: laptops, tablets, smart TVs or smart watches. Check out this [demo](https://go.lightspeedhq.com/ecwid-demo-store)

### Hundreds of extensions and powerful API

There is a lot of in-house and third party extensions built on the Ecwid Ecommerce APIs. You can find a ready made plugin extending features of your online storefront the way you want or build a custom addon yourself. The existing family of third party plugins include tax automation apps like TaxJar, fulfilment services like ShipStation, customer support tools like LiveChat and many others.

### Plans start at just $5/mo

Start selling ealisy with no big investment. As your online shop grows, Ecwid grows with you. When the time is right, consider upgrading your store to one of our premium plans to get more robust features and preferred support. See also: [Ecwid plan and pricing](https://ecwid.to/ecwid-pricing)
Start selling ealisy with no big investment. As your online shop grows, Ecwid grows with you. When the time is right, consider upgrading your store to one of our premium plans to get more robust features and preferred support. See also: [Ecwid plan and pricing](https://go.lightspeedhq.com/ecwid-pricing)

### See Ecwid In Action

* [Demo Store](https://ecwid.to/ecwid-demo-store "Ecwid demo")
* [Ecwid Ecommerce Control panel](https://ecwid.to/ecwid-store-control-panel "Ecwid Control Panel") (you will be able to create an Ecwid account)
* [Showcase](https://ecwid.to/ecwid-wp-site)
* [Demo Store](https://go.lightspeedhq.com/ecwid-demo-store "Ecwid demo")
* [Ecwid Ecommerce Control panel](https://go.lightspeedhq.com/ecwid-store-control-panel "Ecwid Control Panel") (you will be able to create an Ecwid account)
* [Showcase](https://go.lightspeedhq.com/ecwid-wp-site)

### Ecwid Site

* [www.ecwid.com](https://ecwid.to/ecwid-wp-site "Ecwid site")
* [www.ecwid.com](https://go.lightspeedhq.com/ecwid-wp-site "Ecwid site")


## Installation
Expand Down
8 changes: 4 additions & 4 deletions ecwid-shopping-cart.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
Description: Ecwid by Lightspeed is a full-featured shopping cart. It can be easily integrated with any Wordpress blog and takes less than 5 minutes to set up.
Text Domain: ecwid-shopping-cart
Author: Ecwid Ecommerce
Version: 7.0.3
Author URI: https://ecwid.to/ecwid-site
Version: 7.0.4
Author URI: https://go.lightspeedhq.com/ecwid-site
License: GPLv2 or later
*/

Expand Down Expand Up @@ -1222,11 +1222,11 @@ function ecwid_get_scriptjs_code( $force_lang = null ) {
$store_id = get_ecwid_store_id();
$params = ecwid_get_scriptjs_params();

$code .= '<script data-cfasync="false" type="text/javascript" src="https://' . Ecwid_Config::get_scriptjs_domain() . '/script.js?' . $store_id . $params . '"></script>'; //phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
$code .= '<script data-cfasync="false" data-no-optimize="1" src="https://' . Ecwid_Config::get_scriptjs_domain() . '/script.js?' . $store_id . $params . '"></script>'; //phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
}

$code .= ecwid_sso();
$code .= '<script type="text/javascript">if (typeof jQuery !== undefined && jQuery.mobile) { jQuery.mobile.hashListeningEnabled = false; jQuery.mobile.pushStateEnabled=false; }</script><!--/noptimize-->';
$code .= '<script data-cfasync="false" data-no-optimize="1">if (typeof jQuery !== undefined && jQuery.mobile) { jQuery.mobile.hashListeningEnabled = false; jQuery.mobile.pushStateEnabled=false; }</script><!--/noptimize-->';

return apply_filters( 'ecwid_scriptjs_code', $code );
}
Expand Down
4 changes: 2 additions & 2 deletions includes/class-ecwid-ajax-defer-renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public function render_shortcode( $shortcode ) {

public function add_shortcodes( $content ) {
$ecwid_store_id = get_ecwid_store_id();
$before = '<script>var ecwid_shortcodes = [];</script>';
$before = '<script data-cfasync="false" data-no-optimize="1">var ecwid_shortcodes = [];</script>';

$scriptjs_domain = esc_attr( Ecwid_Config::get_scriptjs_domain() );

Expand All @@ -104,7 +104,7 @@ public function add_shortcodes( $content ) {
$script_src = "https://$scriptjs_domain/script.js?$ecwid_store_id&data_platform=wporg&lang=$lang";
ob_start();
?>
<script>
<script data-cfasync="false" data-no-optimize="1">
window.ecwid_script_defer = true;
window.ecwid_dynamic_widgets = true;

Expand Down
2 changes: 1 addition & 1 deletion includes/class-ecwid-floating-minicart.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public function display() {
data-icon='<?php echo esc_attr( $icon ); ?>'
></div>

<script>
<script data-cfasync="false" data-no-optimize="1">
if (typeof Ecwid != 'undefined'){
Ecwid.init();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public function render_callback( $params ) {

ob_start();
?>
<script>
<script data-cfasync="false" data-no-optimize="1">
Ecwid.OnAPILoaded.add(function() {
Ecwid.OnPageLoad.add(function(page) {
if ("CATEGORY" == page.type && 0 == page.categoryId && !page.hasPrevious) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public function render_callback( $params ) {
public static function get_script_for_open_filters_page() {
ob_start();
?>
<script>
<script data-cfasync="false" data-no-optimize="1">
Ecwid.OnAPILoaded.add(function() {
Ecwid.OnPageLoad.add(function(page) {
if ("CATEGORY" == page.type && 0 == page.categoryId && !page.hasPrevious) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function render_callback( $params ) {
></div>

<!--noptimize-->
<script>
<script data-cfasync="false" data-no-optimize="1">
if (typeof Ecwid != 'undefined'){
Ecwid.init();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ public function get_js_for_open_page( $page = '' ) {

ob_start();
?>
<script>
<script data-cfasync="false" data-no-optimize="1">
Ecwid.OnAPILoaded.add(function() {
Ecwid.OnPageLoad.add(function(page) {
if ("CATEGORY" == page.type && 0 == page.categoryId && !page.hasPrevious) {
Expand Down
2 changes: 1 addition & 1 deletion includes/widgets/nsf-minicart.tpl.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
></div>

<!--noptimize-->
<script>
<script data-cfasync="false" data-no-optimize="1">
if (typeof Ecwid != 'undefined') {
Ecwid.init();
}
Expand Down
146 changes: 146 additions & 0 deletions js/gutenberg/buynow.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// Import CSS.
import './style.scss';
import './editor.scss';
import {EcwidIcons} from '../icons.js';


if ( !EcwidGutenbergParams.isDemoStore ) {

const { __, _x } = wp.i18n; // Import __() from wp.i18n

const {
BlockControls,
registerBlockType,
} = wp.blocks;

const {
InspectorControls,
} = wp.editor;

const {
PanelBody,
ToggleControl,
} = wp.components;

const { withState } = wp.compose;

const {
Fragment
} = wp.element;

registerBlockType( 'ec-store/buynow', {
title: __( 'Buy Now Button', 'ecwid-shopping-cart' ),
icon: EcwidIcons.button,
category: 'ec-store', // Block category — Group blocks together based on common traits E.g. common, formatting, layout widgets, embed.
attributes: {
id: {type: 'integer'},
show_price_on_button: {type: 'boolean', default: true},
center_align: {type: 'boolean', default: true}
},
description: __( 'Display a buy button', 'ecwid-shopping-cart' ),
supports: {
customClassName: false,
className: false,
html: false,
align: true,
alignWide: false,
isPrivate: !EcwidGutenbergParams.isApiAvailable
},

/**
* The edit function describes the structure of your block in the context of the editor.
* This represents what the editor will render when the block is used.
*
* The "edit" property must be a valid function.
*
* @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/
*/
edit: function( props ) {

const { attributes } = props;

const saveCallback = function( params ) {

const attributes = {
'id': params.newProps.id
};

EcwidGutenbergParams.products[params.newProps.id] = {
name: params.newProps.product.name,
imageUrl: params.newProps.product.thumb
};

params.originalProps.setAttributes(attributes);
};

const editor = <div className="ec-store-block ec-store-block-buynow">
{ !attributes.id &&
<div>
<div className="image">
</div>

<div className="button-container">
<button className="button ec-store-block-button" onClick={ () => { var params = {'saveCallback':saveCallback, 'props': props}; ecwid_open_product_popup( params ); } }>{ EcwidGutenbergParams.chooseProduct }</button>
</div>
</div>
}

{ attributes.id &&
<div className="image">
</div>
}
</div>;

function buildToggle(props, name, label) {
return <ToggleControl
label={ label }
checked={ props.attributes[name] }
onChange={ () => props.setAttributes( { [name]: ! props.attributes[name] } ) }
/>
}

function openEcwidProductPopup( props ) {
ecwid_open_product_popup( { 'saveCallback': saveCallback, 'props': props } );
}

return ([
editor,
<InspectorControls>
{attributes.id &&
<div>
<div className="ec-store-inspector-row">
<label className="ec-store-inspector-subheader">{ __( 'Linked product', 'ecwid-shopping-cart' ) }</label>
</div>

<div className="ec-store-inspector-row">

{ EcwidGutenbergParams.products && EcwidGutenbergParams.products[attributes.id] &&
<label>{ EcwidGutenbergParams.products[attributes.id].name }</label>
}

<button className="button" onClick={ () => openEcwidProductPopup( props ) }>{ __( 'Change', 'ecwid-shopping-cart' ) }</button>
</div>
</div>
}
{!attributes.id &&
<div className="ec-store-inspector-row">
<button className="button" onClick={ () => openEcwidProductPopup( props ) }>{ __( 'Choose product', 'ecwid-shopping-cart' ) }</button>
</div>
}

<br />
<PanelBody title={ __( 'Appearance', 'ecwid-shopping-cart' ) } initialOpen={false}>
{ buildToggle( props, 'show_price_on_button', __( 'Show price inside the «Buy now» button', 'ecwid-shopping-cart' ) ) }
{ buildToggle( props, 'center_align', __( 'Center align on a page', 'ecwid-shopping-cart' ) ) }
</PanelBody>
</InspectorControls>
]);
},

save: function( props ) {
return false;
},

} );

}
97 changes: 97 additions & 0 deletions js/gutenberg/cart-page.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/**
* BLOCK: my-block
*
* Registering a basic block with Gutenberg.
* Simple block, renders and saves the same content without any interactivity.
*/

// Import CSS.
import './style.scss';
import './editor.scss';
import {EcwidIcons} from '../icons.js';
import { EcwidControls, EcwidProductBrowserBlock, EcwidImage } from '../includes/controls.js';

const { __, _x } = wp.i18n;

const {
registerBlockType,
} = wp.blocks;

const {
InspectorControls,
} = wp.editor;

const {
PanelBody,
PanelRow,
ToggleControl,
ButtonGroup,
Button,
BaseControl,
Toolbar,
ColorPalette,
ColorIndicator
} = wp.components;

const { withState } = wp.compose;

const blockName = 'ec-store/cart-page';

const blockParams = EcwidGutenbergParams.blockParams[blockName];
/**
* Register: aa Gutenberg Block.
*
* Registers a new block provided a unique name and an object defining its
* behavior. Once registered, the block is made editor as an option to any
* editor interface where blocks are implemented.
*
* @link https://wordpress.org/gutenberg/handbook/block-api/
* @param {string} name Block name.
* @param {Object} settings Block settings.
* @return {?WPBlock} The block, if it has been successfully
* registered; otherwise `undefined`.
*/
registerBlockType( 'ec-store/cart-page', {
title: __( 'Cart and Checkout', 'ecwid-shopping-cart' ), // Block title.
icon: EcwidIcons.cartPage,
category: 'ec-store', // Block category — Group blocks together based on common traits E.g. common, formatting, layout widgets, embed.
attributes: blockParams.attributes,
description: __( 'Display shopping cart and checkout page', 'ecwid-shopping-cart' ),
supports: {
customClassName: false,
className: false,
html: false,
multiple: false
},

/**
* The edit function describes the structure of your block in the context of the editor.
* This represents what the editor will render when the block is used.
*
* The "edit" property must be a valid function.
*
* @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/
*/
edit: function( props ) {

const { attributes } = props;


const editor =
<EcwidProductBrowserBlock icon={ EcwidIcons.cartPage } title={ __( 'Cart and Checkout', 'ecwid-shopping-cart' ) }>
<EcwidImage src="cart-page-preview.png" />
</EcwidProductBrowserBlock>;

function buildDangerousHTMLMessageWithTitle( title, message ) {
return <BaseControl label={ title }><div dangerouslySetInnerHTML={{ __html: message }} /></BaseControl>;
}

return ([
editor
]);
},

save: function( props ) {
return null;
}
} );
Loading