Socket
Socket
Sign inDemoInstall

@bva/recommendations

Package Overview
Dependencies
Maintainers
2
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@bva/recommendations - npm Package Compare versions

Comparing version 0.0.3 to 0.0.4

.eslintignore

2

package.json
{
"name": "@bva/recommendations",
"version": "0.0.3",
"version": "0.0.4",
"description": "JS recommendations widget using Shopify native recommendations API",

@@ -5,0 +5,0 @@ "main": "src/index.js",

@@ -33,4 +33,4 @@ Recommendations

};
const recommendation = new Recommendations(options);
recommendation.initialize();
const recs = new Recommendations(options);
recs.initialize();
```

@@ -46,8 +46,8 @@

<script>
var options = {
var config = {
productId: 10590155084,
limit: 6
};
var recommendation = new Shopify.Recommendations(options);
recommendation.initialize();
var recs = new Shopify.Recommendations(config);
recs.initialize();
</script>

@@ -58,4 +58,7 @@ ```

## Options
## Configuration Object
A configuration is required when initializing your Recommendations instance and uses the following properties:
- **productId** - The ID of the product recommendations will be based off of
- **hiddenTag** - (default: `"recommendations::hide"`) Tag that hides specific products

@@ -66,2 +69,53 @@ - **insertion** - (default: `"[data-recommendations-insertion]"`) HTML element that the reviews will be inserted into

## Product Id
The Product ID is what will be used in the request to Shopify to figure out which products to display. It must be passed to your instance upon instantiation via 1 of the following methods.
### HTML (Recommended Method)
Add the data attribute `data-recommendations-main-product-id` to your insertion element and add the product id as a value to that. This is the recommended method because you'll usually have access to the Product ID via liquid. It is much easier for a future developer to read this and understand what's happening.
```html
<div data-recommendations-insertion data-recommendations-main-product-id="1234567890"></div>
```
In Liquid
```html
<div data-recommendations-insertion data-recommendations-main-product-id="{{ product.id }}"></div>
```
### JS
Pass the `productId` value along with your configuration object.
```javascript
const config = {
productId: 1234567890,
limit: 5,
};
const recs = Shopify.Recommendations(config);
recs.initialize();
```
In Liquid
```html
<script>
Shopify.customVariables = {
productId: {{ product.id }}
};
</script>
```
```javascript
const config = {
productId: window.Shopify.customVariables.productId,
limit: 5,
};
...
```
## Template

@@ -99,4 +153,27 @@

## Methods
### initialize
Initializes a Recommendations instance and adds it to the page.
```javascript
const recs = Shopify.Recommendations({ variantId: 1234567890 });
recs.initialize();
```
### reinitialize
*Needs documentation*
### uninitialize
*Needs documentation*
### updateOptions
*Needs documentation*
## Events
- `recommendations.initialized`: Fires when a recommendation instance is initialized. The callback you will find the product data in `event.detail.data` and the current instance in `event.detail.context`.

@@ -8,7 +8,9 @@ import setupHtmlString from './_setup-html-string';

if (!insertion) {
throw `Insertion element does not exist - ${context.options.insertion}`;
throw new Error(`Insertion element does not exist - ${context.options.insertion}`);
}
insertion.innerHTML = html;
insertion.setAttribute('data-recommendations-id', context.recommendationsId);
return true;
};

@@ -1,8 +0,13 @@

export default (options) => {
if (!options) {
throw 'Recommendations requires configuration object'
export default (config) => {
if (!config) {
return false;
}
if (!options.productId) {
throw 'Recommendations object requires a product ID';
if (config.limit && typeof config.limit !== 'number') {
throw new Error('Recommendations: property `limit` needs to be of type Number');
}
if (config.limit && config.limit > 10) {
throw new Error('Recommendations: property `limit` requires value less than 10');
}
};

@@ -13,2 +13,5 @@ import convertCentsToDollars from './helpers/convert-cents-to-dollars';

export default (data, context) => {
if (!data.products) {
throw new Error(`No products found for product ID: ${context.options.productId}`);
}
return data.products.map((product) => {

@@ -15,0 +18,0 @@ if (product.tags.includes(context.options.hiddenTag)) {

@@ -13,2 +13,3 @@ /**

import defaultOptions from './_default-options';
import getProductIdFromInsertion from './_get-product-id-from-insertion';

@@ -22,14 +23,47 @@ /**

class Recommendations {
constructor(options) {
checkIfOptionsAreValid(options);
constructor(config) {
checkIfOptionsAreValid(config);
let productId;
if (config && config.productId) {
productId = config.productId;
} else {
if (config && config.insertion) {
productId = getProductIdFromInsertion(config.insertion);
} else {
productId = getProductIdFromInsertion(defaultOptions.insertion);
}
}
if (!productId) {
throw new Error(
'`Product ID was not provided by config object nor insertion element'
);
}
this.productId = productId;
const updatedOptions = {};
_.assign(updatedOptions, defaultOptions, options);
_.assign(updatedOptions, defaultOptions);
if (config) {
_.assign(updatedOptions, config);
}
this.options = updatedOptions;
this.isInitialized = false;
this.recommendationsId = Math.floor(100000000 + Math.random() * 900000000);
}
/**
* Gets the data, sets up JS connections and renders the recs to the screen
*
* @async
* @function initialize
*/
initialize() {
const url = `/recommendations/products.json?product_id=${this.options.productId}&limit=${this.options.limit}`;
const url = `/recommendations/products.json?product_id=${this.productId}&limit=${this.options.limit}`;
const context = this;
// TODO: if data has already been stored and product id is the same, do not run another fetch
fetch(url)

@@ -54,4 +88,64 @@ .then((response) => {

});
this.isInitialized = true;
})
.catch((err) => {
throw err;
});
}
/**
* Updates the configuration object
*
* @function updateOptions
* @param {Object} updates
*/
updateOptions(config) {
_.assign(this.options, config);
}
/**
* Uninitiallizes the recs instance then initializes it with the current options
*
* @function reinitialize
*/
reinitialize() {
if (!this.isInitialized) {
throw new Error('Cannot reinitialize Recommendations object (has not been initialized)');
}
this.uninitialize();
this.initialize();
}
/**
* Removes recs instance from the page but keeps it availabe to be initialized again
*
* @function uninitialize
*/
uninitialize(preventEvent) {
if (!this.isInitialized) {
throw new Error('Cannot unitialize Recommendations object (has not been initialized)');
}
this.isInitialized = false;
const parents = document.querySelectorAll(`[data-recommendations-id="${this.recommendationsId}"]`);
if (!parent) {
throw new Error(`Cannot uninitiale Recommendations object (cannot find insertion with ID ${this.recommendationsId})`);
}
parents.forEach((parent) => {
while (parent.firstChild) {
parent.firstChild.remove();
}
});
if (!preventEvent) {
dispatchEvent('recommendations.uninitialized', {
context: this,
data: this.data,
});
}
}
}

@@ -58,0 +152,0 @@

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc