PageSourceSearch

https://www.delsinrecords.com/scripts/orderlist.js?1359449221

js delsinrecords.com collected 2026-10-03 21:22:36 UTC 9,072 bytes, 238 lines download raw bytes

1// Orderlist — sorting + PDF download (uses event delegation for AJAX-loaded content)
2(function($) {
3
4    // ── Table sorting ──
5    $(document).on('click', '.b2b-lines th.sortable', function() {
6        var th = $(this);
7        var table = th.closest('table');
8        var colIndex = th.index();
9        var tbody = table.find('tbody');
10        var rows = tbody.find('tr').get();
11        var isAsc = th.hasClass('sort-asc');
12
13        table.find('thead th').removeClass('sort-asc sort-desc');
14        var dir = isAsc ? -1 : 1;
15        th.addClass(isAsc ? 'sort-desc' : 'sort-asc');
16
17        var isNumeric = (colIndex === 0 || colIndex === 6 || colIndex === 7);
18        var isDate = (colIndex === 8);
19
20        rows.sort(function(a, b) {
21            var aText = a.cells[colIndex].textContent.trim();
22            var bText = b.cells[colIndex].textContent.trim();
23            if (isNumeric) {
24                var aVal = parseFloat(aText.replace(/[^\d.\-]/g, '')) || 0;
25                var bVal = parseFloat(bText.replace(/[^\d.\-]/g, '')) || 0;
26                return (aVal - bVal) * dir;
27            }
28            if (isDate) {
29                var aD = aText ? new Date(aText) : new Date(0);
30                var bD = bText ? new Date(bText) : new Date(0);
31                return (aD - bD) * dir;
32            }
33            return aText.localeCompare(bText) * dir;
34        });
35        $.each(rows, function(i, row) { tbody.append(row); });
36    });
37
38    // Mark headers as sortable when b2b-lines content appears
39    function initSortHeaders() {
40        $('.b2b-lines thead th').addClass('sortable');
41    }
42
43    // ── PDF download ──
44    var sectionNames = {
45        ordered: 'Ordered - To Process',
46        shelflist: 'Reserved',
47        preorderlist: 'Back - Pre-Order List',
48        sold: 'Sold - Dispatched'
49    };
50
51    var jsPdfLoaded = false;
52
53    function loadJsPdf(callback) {
54        if (jsPdfLoaded && window.jspdf) {
55            callback();
56            return;
57        }
58        var s1 = document.createElement('script');
59        s1.src = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js';
60        s1.onload = function() {
61            var s2 = document.createElement('script');
62            s2.src = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.8.2/jspdf.plugin.autotable.min.js';
63            s2.onload = function() {
64                jsPdfLoaded = true;
65                callback();
66            };
67            document.head.appendChild(s2);
68        };
69        document.head.appendChild(s1);
70    }
71
72    function generatePdf(btn) {
73        var section = $(btn).data('section');
74        var h4 = $(btn).closest('h4');
75        var tableEl = h4.nextAll('.table-responsive').first().find('table')[0]
76                   || h4.nextAll('table').first()[0];
77        if (!tableEl) return;
78
79        var jsPDF = window.jspdf.jsPDF;
80        var doc = new jsPDF({ orientation: 'landscape', unit: 'mm', format: 'a4' });
81
82        var title = sectionNames[section] || section;
83        var dateStr = new Date().toLocaleDateString('en-GB');
84        var shopName = $('.b2b-lines').data('shop-name') || '';
85        var customerName = $('.b2b-lines').data('customer-name') || '';
86
87        var yPos = 15;
88        if (shopName) {
89            doc.setFontSize(18);
90            doc.setTextColor(0);
91            doc.text(shopName, 14, yPos);
92            yPos += 8;
93        }
94        if (customerName) {
95            doc.setFontSize(12);
96            doc.setTextColor(80);
97            doc.text(customerName, 14, yPos);
98            yPos += 8;
99        }
100        doc.setFontSize(14);
101        doc.setTextColor(0);
102        doc.text(title, 14, yPos);
103        yPos += 6;
104        doc.setFontSize(9);
105        doc.setTextColor(120);
106        doc.text('Generated: ' + dateStr, 14, yPos);
107        doc.setTextColor(0);
108        yPos += 4;
109
110        var headers = [];
111        $(tableEl).find('thead th').each(function() {
112            headers.push($(this).text().replace(/[↑↓↕]/g, '').trim());
113        });
114
115        var body = [];
116        $(tableEl).find('tbody tr').each(function() {
117            var row = [];
118            $(this).find('td').each(function() { row.push($(this).text().trim()); });
119            body.push(row);
120        });
121
122        var foot = [];
123        $(tableEl).find('tfoot tr').each(function() {
124            var row = [];
125            $(this).find('td').each(function() {
126                var colspan = parseInt($(this).attr('colspan')) || 1;
127                row.push($(this).text().trim());
128                for (var c = 1; c < colspan; c++) { row.push(''); }
129            });
130            foot.push(row);
131        });
132
133        doc.autoTable({
134            head: [headers],
135            body: body,
136            foot: foot,
137            startY: yPos,
138            theme: 'grid',
139            styles: { fontSize: 8, cellPadding: 2 },
140            headStyles: { fillColor: [50, 50, 50], textColor: 255, fontStyle: 'bold' },
141            footStyles: { fillColor: [240, 240, 240], textColor: 0, fontStyle: 'bold' },
142            alternateRowStyles: { fillColor: [248, 248, 248] },
143            columnStyles: {
144                0: { halign: 'center', cellWidth: 12 },
145                6: { halign: 'right' },
146                7: { halign: 'right' }
147            },
148            didParseCell: function(data) {
149                // Apply alignment to all sections (head, body, foot)
150                if (data.column.index === 0) data.cell.styles.halign = 'center';
151                if (data.column.index === 6) data.cell.styles.halign = 'right';
152                if (data.column.index === 7) data.cell.styles.halign = 'right';
153            }
154        });
155
156        doc.save('b2b-' + section + '-' + dateStr.replace(/\//g, '-') + '.pdf');
157    }
158
159    $(document).on('click', '.pdf-download', function(e) {
160        e.preventDefault();
161        var btn = this;
162        $(btn).prop('disabled', true).html('<i class="fas fa-spinner fa-spin mr-1"></i>Loading...');
163        loadJsPdf(function() {
164            generatePdf(btn);
165            $(btn).prop('disabled', false).html('<i class="fas fa-file-pdf mr-1"></i>PDF');
166        });
167    });
168
169    // Init sorting when b2b-lines loads (called via MutationObserver or after AJAX)
170    var observer = new MutationObserver(function(mutations) {
171        mutations.forEach(function() {
172            if ($('.b2b-lines').length) {
173                initSortHeaders();
174            }
175        });
176    });
177    var target = document.getElementById('scrollcontainer') || document.getElementById('maincontent');
178    if (target) {
179        observer.observe(target, { childList: true, subtree: true });
180    }
181    // Also init immediately if already present
182    initSortHeaders();
183
184    // ── Email section ──
185    $(document).on('click', '.email-section', function(e) {
186        e.preventDefault();
187        var $btn = $(this);
188        var section = $btn.data('section');
189        var origHtml = $btn.html();
190
191        if (!confirm('Email this section to your registered email address?')) return;
192
193        $btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin mr-1"></i>Sending...');
194
195        $.post('/ajax_orderlist_email.php', { section: section }, function(data) {
196            if (data && data.success) {
197                $btn.html('<i class="fas fa-check mr-1"></i>Sent!');
198                setTimeout(function() {
199                    $btn.prop('disabled', false).html(origHtml);
200                }, 3000);
201            } else {
202                alert(data.message || 'Could not send email.');
203                $btn.prop('disabled', false).html(origHtml);
204            }
205        }, 'json').fail(function() {
206            alert('Request failed. Please try again.');
207            $btn.prop('disabled', false).html(origHtml);
208        });
209    });
210
211    // ── Ship Reserved Items request ──
212    $(document).on('click', '.ship-reserved-btn', function() {
213        var $btn = $(this);
214        var $status = $btn.siblings('.ship-reserved-status');
215
216        if (!confirm('Send a request to ship all your reserved items?')) return;
217
218        $btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin mr-1"></i>Sending...');
219        $status.text('');
220
221        $.post('/ajax_ship_request.php', {}, function(data) {
222            if (data && data.success) {
223                $btn.removeClass('btn-success').addClass('btn-outline-success')
224                    .html('<i class="fas fa-check mr-1"></i>Request Sent');
225                $status.text(data.message).css('color', '#28a745');
226            } else {
227                $btn.prop('disabled', false)
228                    .html('<i class="fas fa-shipping-fast mr-1"></i>Please Ship My Reserved Items');
229                $status.text(data.message || 'Something went wrong.').css('color', '#dc3545');
230            }
231        }, 'json').fail(function() {
232            $btn.prop('disabled', false)
233                .html('<i class="fas fa-shipping-fast mr-1"></i>Please Ship My Reserved Items');
234            $status.text('Request failed. Please try again.').css('color', '#dc3545');
235        });
236    });
237
238})(jQuery);

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.