PageSourceSearch

https://wizfort.com/assets/cslshoes_erp/js/compare.js

js wizfort.com collected 2026-09-27 13:40:28 UTC 7,601 bytes, 232 lines download raw bytes

1// Product Compare Functionality
2// Wrapped in IIFE to avoid global conflicts
3(function() {
4    'use strict';
5
6    // Only run on website pages, not desk
7    if (frappe.boot && frappe.boot.setup_complete === false) {
8        return;
9    }
10
11    var MAX_ITEMS = 4;
12    var STORAGE_KEY = 'csl_compare_items';
13
14    function getItems() {
15        try {
16            var items = localStorage.getItem(STORAGE_KEY);
17            return items ? JSON.parse(items) : [];
18        } catch (e) {
19            return [];
20        }
21    }
22
23    function saveItems(items) {
24        try {
25            localStorage.setItem(STORAGE_KEY, JSON.stringify(items));
26        } catch (e) {
27            console.error('[CSL Compare] Error saving items:', e);
28        }
29    }
30
31    function addItem(itemData) {
32        var items = getItems();
33
34        // Check if already exists
35        if (items.find(function(item) { return item.item_code === itemData.item_code; })) {
36            frappe.show_alert({
37                message: __('This product is already in your compare list'),
38                indicator: 'orange'
39            });
40            return false;
41        }
42
43        // Check max limit
44        if (items.length >= MAX_ITEMS) {
45            frappe.show_alert({
46                message: __('You can compare up to {0} products at a time', [MAX_ITEMS]),
47                indicator: 'orange'
48            });
49            return false;
50        }
51
52        items.push(itemData);
53        saveItems(items);
54        updateWidget();
55        updateButtonStates();
56
57        frappe.show_alert({
58            message: __('Product added to compare list'),
59            indicator: 'green'
60        });
61
62        return true;
63    }
64
65    function removeItem(itemCode) {
66        var items = getItems();
67        items = items.filter(function(item) { return item.item_code !== itemCode; });
68        saveItems(items);
69        updateWidget();
70        updateButtonStates();
71
72        frappe.show_alert({
73            message: __('Product removed from compare list'),
74            indicator: 'blue'
75        });
76    }
77
78    function clearAll() {
79        saveItems([]);
80        updateWidget();
81        updateButtonStates();
82    }
83
84    function createWidget() {
85        // Check if widget already exists
86        if (document.getElementById('compare-widget')) return;
87
88        var widgetHtml =
89            '<div class="compare-widget" id="compare-widget">' +
90                '<div class="compare-widget-header">' +
91                    '<h5>' + __('Compare Products') + '</h5>' +
92                    '<span class="compare-count">0</span>' +
93                '</div>' +
94                '<div class="compare-widget-body">' +
95                    '<div class="compare-items-list"></div>' +
96                '</div>' +
97                '<div class="compare-widget-footer">' +
98                    '<a href="/compare" class="btn btn-primary compare-now-btn">' + __('Compare Now') + '</a>' +
99                    '<button class="btn btn-outline compare-clear-all">' + __('Clear All') + '</button>' +
100                '</div>' +
101            '</div>';
102
103        $('body').append(widgetHtml);
104    }
105
106    function updateWidget() {
107        var items = getItems();
108        var $widget = $('#compare-widget');
109        var $itemsList = $widget.find('.compare-items-list');
110        var $count = $widget.find('.compare-count');
111
112        // Update count
113        $count.text(items.length);
114
115        // Show/hide widget
116        if (items.length > 0) {
117            $widget.addClass('show');
118        } else {
119            $widget.removeClass('show');
120        }
121
122        // Render items
123        $itemsList.empty();
124        items.forEach(function(item) {
125            var itemHtml =
126                '<div class="compare-item" data-item-code="' + item.item_code + '">' +
127                    '<img class="compare-item-image" src="' + (item.image || '/assets/webshop/images/cart-empty-state.png') + '" alt="' + item.name + '">' +
128                    '<span class="compare-item-name">' + item.name + '</span>' +
129                    '<button class="compare-item-remove" data-item-code="' + item.item_code + '" title="' + __('Remove') + '">' +
130                        '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">' +
131                            '<line x1="18" y1="6" x2="6" y2="18"></line>' +
132                            '<line x1="6" y1="6" x2="18" y2="18"></line>' +
133                        '</svg>' +
134                    '</button>' +
135                '</div>';
136            $itemsList.append(itemHtml);
137        });
138    }
139
140    function updateButtonStates() {
141        var items = getItems();
142        var itemCodes = items.map(function(item) { return item.item_code; });
143
144        // Update only compare-specific buttons (more specific selector)
145        $('.compare-action[data-item-code]').each(function() {
146            var $btn = $(this);
147            var itemCode = $btn.data('item-code');
148
149            if (itemCodes.indexOf(itemCode) !== -1) {
150                $btn.addClass('active');
151                $btn.find('.btn-label').text(__('Added'));
152            } else {
153                $btn.removeClass('active');
154                $btn.find('.btn-label').text(__('Compare'));
155            }
156        });
157    }
158
159    function bindEvents() {
160        // Use specific class for compare buttons to avoid conflicts
161        // Don't use stopPropagation to allow other handlers to work
162        $(document).on('click.cslcompare', '.compare-action[data-item-code]', function(e) {
163            e.preventDefault();
164
165            var $btn = $(this);
166            var itemCode = $btn.data('item-code');
167
168            if (!itemCode) return;
169
170            // Check if already in compare list
171            var items = getItems();
172            var existingItem = items.find(function(item) { return item.item_code === itemCode; });
173
174            if (existingItem) {
175                // Remove from compare
176                removeItem(itemCode);
177            } else {
178                // Add to compare
179                var itemData = {
180                    item_code: itemCode,
181                    name: $btn.data('item-name') || $btn.closest('.product-details').find('.product-title').first().text().trim() || '',
182                    image: $btn.data('item-image') || '',
183                    route: $btn.data('item-route') || window.location.pathname
184                };
185                addItem(itemData);
186            }
187        });
188
189        // Remove item from widget
190        $(document).on('click.cslcompare', '.compare-item-remove', function(e) {
191            e.preventDefault();
192            e.stopPropagation();
193            var itemCode = $(this).data('item-code');
194            removeItem(itemCode);
195        });
196
197        // Clear all button
198        $(document).on('click.cslcompare', '.compare-clear-all', function(e) {
199            e.preventDefault();
200            clearAll();
201        });
202    }
203
204    function init() {
205        createWidget();
206        bindEvents();
207        updateWidget();
208        updateButtonStates();
209    }
210
211    // Initialize when DOM is ready
212    if (typeof frappe !== 'undefined' && frappe.ready) {
213        frappe.ready(function() {
214            // Small delay to ensure other scripts have loaded
215            setTimeout(init, 100);
216        });
217    } else {
218        $(document).ready(function() {
219            setTimeout(init, 100);
220        });
221    }
222
223    // Expose minimal API for external use
224    window.cslCompare = {
225        add: addItem,
226        remove: removeItem,
227        clear: clearAll,
228        getItems: getItems,
229        updateStates: updateButtonStates
230    };
231
232})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.