Skip to content

Custom scripts

You can use custom scripts to customize the module behaviour.
You can create javascript files in these folders:

  • /js/dynamic (create the dynamic folder if it doesn't exist)
  • /themes/[current theme]/assets/js/dynamic

The file name should be:

  • custom.js (if you want to target all products)
  • customX.js (if you want to only target the product with ID=X)
    For example, if you want to target product #10, you can create a file named custom10.js

Detecting when the module is loaded

Since the module loading is deferred, you need to listen for the dp.load event in order to execute your custom script correctly and avoid errors.

js
document.addEventListener("dp.load", function() {
	// Your code here
});

Updating the properties of a field

You can change a field properties from the custom script, for that you need to use the updateField function.
Code example:

js

window.dp.methods.updateField(field_name, props);

// This example will change the value of the width field as well as the min, max and step properties
window.dp.methods.updateField("width", {
	value: 50,
	min: 10,
	max: 100,
	step: 10
});

The props object can have these items

ts
// The props interface has this shape
export interface IFieldSettings {
	value: string | number;
	value_formatted: string;
	min: number;
	max: number;
	step: number;
	required: number;
	max_size: number;
	min_date: string;
	max_date: string;
	multiselect: boolean;
	display_value_price: number;
	display_secondary_value_price: number;
	display_in_popup: number;
}

Some field types display the value_formatted property, such as the price field.

To update it, you can use this code for example

js
window.dp.methods.updateField("price_field", {
	value: 50,
	value_formatted: '50€'
});

Get a field properties

You can use the getField function to get the properties of a field.

js
window.dp.methods.getField(field_name);
var props = window.dp.methods.getField("width");

The value of props will have this shape

js
{
	active: 1
	common: 0
	description: ""
	dir: "/dynamicproduct/images/field"
	ext: ".jpg"
	favorite: 0
	force_id: false
	id: 66
	id_group: "0"
	id_product: 11
	id_unit: 0
	image_url: null
	init: 0
	label: "Width"
	linked: "0"
	name: "width"
	options: []
	position: "2"
	settings: {
		color: null
		dir: null
		display_in_popup: null
		display_secondary_value_price: null
		display_value_price: null
		ext: ".jpg"
		extensions: null
		extra: null
		force_id: false
		hide_when_empty: 1
		id: null
		id_field: 66
		id_unit: null
		init: null
		max: null
		max_date: null
		max_size: null
		min: null
		min_date: null
		min_height: null
		min_width: null
		multiselect: null
		position: null
		price_unit: null
		required: null
		show_in_summary: 0
		step: 1
		thumb_suffix: "-thumb.jpg"
	}
	thumb_suffix: "-thumb.jpg"
	thumb_url: null
	type: 1
	unit: {
		dir: null
		displayed: 1
		ext: ".jpg"
		force_id: false
		id: null
		name: null
		position: null
		symbol: null
		thumb_suffix: "-thumb.jpg"
	}
	value: ""
}

Detecting a calculation result

You can subscribe to the module stores in order to detect the calculation results.
The module uses Vegemite stores under the hood.

Code example:

js
document.addEventListener('dp.load', function() {
	window.dp.stores.calculator.listen(function(data) {
		console.log(data);
	});
});

The data will have this shape

js
{
	customization_prices: {
		price_ht: 10
		price_ht_nr: 10
		price_ttc: 12
		price_ttc_nr: 12
	}
	debug_messages: null
	final_prices: {
		price_ht: 20
		price_ht_nr: 20
		price_ttc: 24
		price_ttc_nr: 24
	}
	formatted_prices: {
		price_ht: "€20.00"
		price_ht_nr: "€20.00"
		price_ttc: "€24.00"
		price_ttc_nr: "€24.00"
	}
	formatted_unit_prices: {
		price_ht: "€20.00"
		price_ht_nr: "€20.00"
		price_ttc: "€24.00"
		price_ttc_nr: "€24.00"
	}
	input_fields: {
		width: {
			dir: null
			ext: ".jpg"
			field: {
				// information about the field, similar to the value returned by getField
			}
			force_id: false
			id: null
			id_field: 66
			id_input: 0
			id_shop_list: []
			image_url: null
			label: "Width"
			name: "width"
			options: "[]"
			position: null
			secondary_value: "0"
			selected_options: []
			thumb_suffix: "-thumb.jpg"
			thumb_url: null
			type: 1
			value: 0
			value_formatted: 0
			visible: 1
		}
	}
	met_conditions: []
	oos: false
	success: 1
	unit_prices: {
		price_ht: 20, price_ht_nr
	:
		20, price_ttc
	:
		24, price_ttc_nr
	:
		24
	}
	use_tax: true
	visibility: {
		groups: []
	}
	weight: 0
	weight_formatted: "0 kg"
}

Detecting any change on fields

You can subscribe to the fields store to detect any change on the fields.
The result will be an object containing each field Example code

js
document.addEventListener('dp.load', function() {
	window.dp.stores.fields.listen(function(fields) {
		console.log(fields);
	});
});

The fields variable will have this shape

js
{
	width: {
		dir: null
		ext: ".jpg"
		field: {
			// information about the field, similar to the value returned by getField
		}
		force_id: false
		id: null
		id_field: 0
		id_input: 0
		id_shop_list: []
		image_url: null
		label: null
		name: "changed"
		options: ""
		position: null
		secondary_value: "0"
		selected_options: ""
		thumb_suffix: "-thumb.jpg"
		thumb_url: null
		type: 4
		value: "width"
		value_formatted: "width"
		visible: 0
	}
,
	height: {
		// same shape as the width field 
	}
,
	// ...
}

Validating the fields

If you need to validate the fields programmatically, you can use the validateFields function.

Example code:

js
var valid = window.dp.methods.validateFields();
// valid will be either true or contain error messages based on the validity of the fields
// The module will highlight errors and will scroll to the first visible error

Add the customization to cart

If you need to add the customization to cart, then you can use the addToCart function.

Example code

js
window.dp.methods.addToCart().then(function(response) {
	// response is either true or false based on the success of the operation
});

Customizing the module selectors

Since many themes have a different structure than the default one, the module allows you to change the selectors used to target the product page elements and to better position the module within the page.

Here's the default selectors structure:

ts
export type DynamicProductProps = {
	// used to position the module within the page
	hook: (container: HTMLDivElement) => void;
	// used to position the layers container within the preview images
	preview_hook: (layers_container: HTMLDivElement) => void;
	selectors: {
		price: string; // price with discount (if applicable)
		regular_price: string; // price without discount
		qty_input: string; // the quantity input
		form: string; // the product form
	};
};

Here are the default values:

ts
window.dp = {
	hook(container: HTMLDivElement) {
		const product_actions = document.querySelector('.js-product-actions');
		product_actions?.prepend(container);
	},
	preview_hook(layers_container: HTMLDivElement) {
		const images_container = document.querySelector('.js-images-container');
		images_container?.prepend(layers_container);
	},
	selectors: {
		price: '.current-price-value',
		regular_price: '.regular-price',
		qty_input: '#quantity_wanted',
		form: '#add-to-cart-or-refresh'
	}
};

To change the hook, you can use this code for example:

ts
window.dp.hook = function(container) {
	const product_actions = document.querySelector('.js-product-actions');
	product_actions?.append(container);
};

To change a selector, you can use this code for example:

ts
window.dp.selectors.price = '.product-price > span';

TIP

You can also use the custom hook in your theme tpl.

Custom fields

Check how to create custom fields here