PageSourceSearch

https://reift.ch/js/shop.js?r=27922

js reift.ch collected 2026-09-24 10:10:36 UTC 150,166 bytes, 4,362 lines download raw bytes

1/************************************************************\
2 *
3 * File					shop.js
4 *
5 * Type					source
6 * Language			javascript
7 *
8 * Author				capt
9 * Creation			20210226
10 *
11 * Project			bootiq
12 * Package		
13 * 
14 * Description	Javascript functions for reift shop
15 *
16 * Copyright (C) digicapt.ch
17 *
18 * Modifications
19\************************************************************/
20
21
22const REIFT_SHOP_TYPE_BOOK = 1;
23const REIFT_SHOP_TYPE_CD = 2;
24const REIFT_SHOP_TYPE_VOUCHER = 3;
25const REIFT_SHOP_TYPE_MP3 = 4;
26const REIFT_SHOP_TYPE_CATALOG = 5;
27const REIFT_SHOP_TYPE_PLAYALONG = 6;
28const REIFT_SHOP_TYPE_TOPSALES = 7;
29
30const REIFT_BOOK_EXTERNAL_CATEGORY_DIFFICULTY = 0;
31const REIFT_BOOK_EXTERNAL_CATEGORY_EDITION = 1;
32const REIFT_BOOK_EXTERNAL_CATEGORY_COUNT = 2;
33
34const ReiftShop = {
35    bootiq: null,
36    //rootCategoryId: [ 2698 ]],
37    rootCategoryId: [ 2700, 2702, 2829, 2909, 2699 ],
38    catalogCategoryId: 3092,
39    allCategoryFetched: false,
40    searchParamSet: false,
41    fetchedCategory: [ false, false, false, false, false, false ],
42    shopType: REIFT_SHOP_TYPE_BOOK,
43    poppedUrl: false,
44    firstSearch: true,
45    
46    text: {
47        messageTitle: "Editions Marc Reift",
48        message: {
49            itemNotFound: "No item matches that number",
50            noMatch: "No matching result",
51            urlCopied: "The url was copied in clipboard",
52            noClipboard: "Your browser does not allow to access clipboard",
53            commentSent: "Your message has been submitted",
54            commentNotSent: "Error while submitting message",
55        },
56        bootiq: {
57            item: {
58                detailButton: "Details",
59                onlyForDownload: "Only for download",
60                readyForDownload: "Available as instant download",
61                rentable: "Rentable",
62                multipleMp3: "Multiple MP3",
63                downloadCd: "Download CD",
64                downloadCdN: "Download CD {CD}",
65            },
66            relation: {
67                availableOnCD: "Available on CD",
68                similar: "Similar to",
69                bookHeader: {
70                    code: "Code",
71                    name: "Name",
72                    contributor: "Composer/arranger",
73                    difficulty: "Diff.",
74                    length: "Length",
75                },
76                    
77            }
78        }
79    },
80
81
82
83    /**
84     * Inialization function
85     * Type : See constants
86     */
87    init: function(shopType) {
88        window.addEventListener("popstate",
89                                function() {
90                                    ReiftShop.poppedUrl = true;
91                                    ReiftShop.initialFetch(event.state.searchUrl);
92                                });
93
94        let menu = "reift-menu-shop"
95
96        if (shopType == REIFT_SHOP_TYPE_CD)
97            menu = "reift-menu-cd";
98        else if (shopType == REIFT_SHOP_TYPE_CATALOG)
99            menu = "reift-menu-catalog";
100        else if (shopType == REIFT_SHOP_TYPE_VOUCHER)
101            menu = "reift-menu-voucher";
102        else if (shopType == REIFT_SHOP_TYPE_PLAYALONG)
103            menu = "reift-menu-playalong";
104        else if (shopType == REIFT_SHOP_TYPE_TOPSALES)
105            menu = "reift-menu-top-sales";
106            
107        ReiftCommon.init(menu);
108
109        BootiqConfig.languageId = 1;
110        BootiqRegistration.useCurrency = true;
111        
112
113        ReiftLogin.init(ReiftShop.loggedIn,
114                        ReiftShop.loggedOut,
115                        null);
116
117        // Set configuration
118        BootiqConfig.texts.itemDetailButton = ReiftShop.text.bootiq.item.detailButton;
119        BootiqConfig.texts.rentable = ReiftShop.text.bootiq.item.rentable;
120        BootiqRegistration.server = ReiftCommon.server;
121        BootiqRegistration.profileId = ReiftCommon.profileId;
122        ReiftShop.shopType = shopType;
123        
124        BootiqConfig.tags.download = ReiftShop.text.bootiq.item.onlyForDownload;
125        BootiqConfig.tags.multipleMp3 = ReiftShop.text.bootiq.item.multipleMp3;
126
127        let classPrefix = "s-";
128
129        if (shopType == REIFT_SHOP_TYPE_VOUCHER)
130            classPrefix = "v-";
131
132        // Bootiq
133        ReiftShop.bootiq = new Bootiq(ReiftCommon.server,
134                                      ReiftCommon.profileId,
135                                      classPrefix);
136        ReiftCart.init(ReiftShop.bootiq);
137
138        if (shopType == REIFT_SHOP_TYPE_CD) {
139            if (ReiftCommon.environment == "test"
140                || ReiftCommon.environment == "dev")
141                ReiftShop.rootCategoryId = [ 2914, 2915, 2916, 2960 ];
142            else
143                ReiftShop.rootCategoryId = [ 2914, 2915, 2916, 2940 ];
144
145            ReiftShop.bootiq.addCategoryListDiv(document.getElementById("category-formation"),
146                                                ReiftShop.rootCategoryId[0]);
147            ReiftShop.bootiq.addCategoryListDiv(document.getElementById("category-instrument"),
148                                                ReiftShop.rootCategoryId[1]);
149            ReiftShop.bootiq.addCategoryListDiv(document.getElementById("category-style"),
150                                                ReiftShop.rootCategoryId[2]);
151            ReiftShop.bootiq.addCategoryListDiv(document.getElementById("category-artist"),
152                                                ReiftShop.rootCategoryId[3]);
153        }
154        else if (shopType == REIFT_SHOP_TYPE_CATALOG) {
155            ReiftShop.bootiq.resetSelectedExternalCategoryList(1);
156
157            if (ReiftCommon.environment == "test") {
158                ReiftShop.rootCategoryId = [ 3099 ];
159                ReiftShop.catalogCategoryId = 3092;	// SURE ?
160            }
161            else if (ReiftCommon.environment == "dev") {
162                ReiftShop.rootCategoryId = [ 3077 ];
163                ReiftShop.catalogCategoryId = 3076;
164            }
165            else {
166                ReiftShop.rootCategoryId = [ 3093 ];
167                ReiftShop.catalogCategoryId = 3092;
168            }
169
170            ReiftShop.bootiq.setSelectedExternalCategoryList(0,
171                                                             [ ReiftShop.catalogCategoryId ]);
172            
173            ReiftShop.bootiq.addCategoryListDiv(document.getElementById("category-catalog-type"),
174                                                ReiftShop.rootCategoryId[0]);
175
176
177        }
178        else if (shopType == REIFT_SHOP_TYPE_VOUCHER)
179            ReiftShop.rootCategoryId = [ ];
180        else if (shopType == REIFT_SHOP_TYPE_PLAYALONG)  {
181            ReiftShop.bootiq.resetSelectedExternalCategoryList(1);
182            ReiftShop.bootiq.setSelectedExternalCategoryList(0,
183                                                             [ 2849 ]);
184            ReiftShop.rootCategoryId = [ ];
185        }
186        else {
187            if (ReiftCommon.environment == "test")
188                ReiftShop.rootCategoryId = [ 2700, 2702, 2829, 2909, 2699 ];
189            else if (ReiftCommon.environment == "dev")
190                ReiftShop.rootCategoryId = [ 2700, 2702, 2829, 2909, 2699 ];
191
192            ReiftShop.bootiq.addCategoryListDiv(document.getElementById("category-formation"),
193                                                ReiftShop.rootCategoryId[0]);
194            ReiftShop.bootiq.addCategoryListDiv(document.getElementById("category-instrument"),
195                                                ReiftShop.rootCategoryId[1]);
196            ReiftShop.bootiq.addCategoryListDiv(document.getElementById("category-accompaniment"),
197                                                ReiftShop.rootCategoryId[2]);
198            ReiftShop.bootiq.addCategoryListDiv(document.getElementById("category-collection"),
199                                                ReiftShop.rootCategoryId[3]);
200            ReiftShop.bootiq.addCategoryListDiv(document.getElementById("category-style"),
201                                                ReiftShop.rootCategoryId[4]);
202        }
203
204        //ReiftShop.bootiq.setItemWithRelation(true);	 no, read when displaying details
205        ReiftShop.bootiq.setItemListDiv(document.getElementById("reift-item-list"));
206        ReiftShop.bootiq.setItemCountDiv(document.getElementById("reift-item-count"));
207        ReiftShop.bootiq.setCartDivList(document.getElementById("reift-cart"),
208                                        document.getElementById("reift-cart-item-value"),
209                                        null,
210                                        null,
211                                        null,
212                                        null,
213                                        null);
214        ReiftShop.bootiq.setMiniCartDiv(document.getElementById("reift-minicart"));
215        ReiftShop.bootiq.setWaitingDiv(document.getElementById("waiting"));
216        ReiftShop.bootiq.setCartDisplayMode(BootiqConstant.CART_DISPLAY_MODE_GROUP_DESCRIPTION
217                                            | BootiqConstant.CART_DISPLAY_MODE_GROUP_PRICE);
218        //ReiftShop.bootiq.setSearchDiv(document.getElementById("reift-search"));
219        ReiftShop.bootiq.setSearchInput(document.getElementById("reift-search-text"));
220
221        if (shopType == REIFT_SHOP_TYPE_CATALOG)
222            ReiftShop.bootiq.setDetailMode(BootiqConstant.DETAIL_MODE_BLOCK_CLICK);
223        else if (shopType == REIFT_SHOP_TYPE_PLAYALONG)
224            ReiftShop.bootiq.setDetailMode(BootiqConstant.DETAIL_MODE_NONE);
225        else
226            ReiftShop.bootiq.setDetailMode(BootiqConstant.DETAIL_MODE_BUTTON_CLICK);
227
228        if (shopType == REIFT_SHOP_TYPE_CD) {
229            ReiftShop.bootiq.setSelectedExternalItemTypeList([2]);
230            ReiftShop.bootiq.setSearchInComponent(true);
231            ReiftShop.bootiq.setItemSortBy(BootiqConstant.ITEM_SORT_BY_START_DATE_DESC);
232            ReiftShop.bootiq.setUseWordMatch(true);
233        }
234        else if (shopType == REIFT_SHOP_TYPE_CATALOG) {
235            ReiftShop.bootiq.setSelectedExternalItemTypeList([5]);
236            ReiftShop.bootiq.setSearchInComponent(false);
237            ReiftShop.bootiq.setItemSortBy(BootiqConstant.ITEM_SORT_BY_SEQUENCE_START_DATE_DESC);
238        }
239        else if (shopType == REIFT_SHOP_TYPE_VOUCHER) {
240            ReiftShop.bootiq.setSelectedExternalItemTypeList([4]);
241            ReiftShop.bootiq.setSearchInComponent(false);
242            ReiftShop.bootiq.setItemSortBy(BootiqConstant.ITEM_SORT_BY_NAME);
243        }
244        else if (shopType == REIFT_SHOP_TYPE_PLAYALONG) {
245            ReiftShop.bootiq.setSelectedExternalItemTypeList([1]);
246            ReiftShop.bootiq.setSearchInComponent(false);
247            ReiftShop.bootiq.setItemSortBy(BootiqConstant.ITEM_SORT_BY_NAME);
248        }
249        else if (shopType == REIFT_SHOP_TYPE_TOPSALES) {
250            ReiftShop.bootiq.setItemSortBy(BootiqConstant.ITEM_SORT_BY_SALES_COUNT_DESC);
251        }
252        else {
253            ReiftShop.bootiq.setSelectedExternalItemTypeList([1]);
254            ReiftShop.bootiq.setSearchInComponent(false);
255            ReiftShop.bootiq.setItemSortBy(BootiqConstant.ITEM_SORT_BY_NAME);
256            ReiftShop.bootiq.setUseWordMatch(true);
257        }
258
259        ReiftShop.bootiq.setStickerUrlCallback(ReiftShop.stickerUrlCallback);
260        ReiftShop.bootiq.setMissingPictureCallback(ReiftShop.missingPictureCallback);
261        ReiftShop.bootiq.setMissingPicture("../resources/images/reift-missing-cover.png");
262        ReiftShop.bootiq.setGroupItemDescription(true);
263
264        if (shopType == REIFT_SHOP_TYPE_TOPSALES)
265            ReiftShop.bootiq.setItemPerPage(25);
266        else
267            ReiftShop.bootiq.setItemPerPage(10);
268        
269        ReiftShop.bootiq.setItemCartAction(BootiqConstant.ITEM_CART_ACTION_CLEAR);
270        ReiftShop.bootiq.setMiniCartToggleCallback(ReiftCart.toggleCart);
271        //ReiftShop.bootiq.setCartItemSelectedCallback(ReiftShop.itemSelectedCallback);
272
273        if (shopType == REIFT_SHOP_TYPE_PLAYALONG)
274            ReiftShop.bootiq.setCanFetchItemWithoutSearch(false);
275        else
276            ReiftShop.bootiq.setCanFetchItemWithoutSearch(true);
277
278        ReiftShop.bootiq.setSearchMode(BootiqConstant.SEARCH_MODE_ALL);
279        ReiftShop.bootiq.setSearchInCode(true);
280        //ReiftShop.bootiq.setSearchCallback(ReiftShop.searchCallback);
281        ReiftShop.bootiq.setItemSelectedCallback(ReiftShop.itemSelectedCallback);
282        ReiftShop.bootiq.setPageSelectedCallback(ReiftShop.pageSelectedCallback);
283        ReiftShop.bootiq.setDrawItemTypeBlock(false);
284        ReiftShop.bootiq.setItemCategoryClickCallback(ReiftShop.itemCategoryClickCallback);
285        //ReiftShop.bootiq.setCanCommentItemInList(true);
286        ReiftShop.bootiq.setItemListFillingCallback(ReiftShop.itemListFillingCallback);
287        ReiftShop.bootiq.setItemListFilledCallback(ReiftShop.itemListFilledCallback);
288        ReiftShop.bootiq.setItemDrawnInListCallback(ReiftShop.itemDrawnInListCallback);
289        ReiftShop.bootiq.setItemDrawnCallback(ReiftShop.itemDrawnCallback);
290
291        if (shopType == REIFT_SHOP_TYPE_PLAYALONG) {
292            ReiftShop.bootiq.setItemWithCategory(false);
293            ReiftShop.bootiq.setItemWithDetail(false);
294            ReiftShop.bootiq.setItemWithTag(false);
295            ReiftShop.bootiq.setCartActive(false);
296        }            
297        else {
298            ReiftShop.bootiq.setItemWithCategory(true);
299            ReiftShop.bootiq.setItemWithTag(true);
300        }
301            
302        if (ReiftShop.shopType != REIFT_SHOP_TYPE_CATALOG
303            && ReiftShop.shopType != REIFT_SHOP_TYPE_PLAYALONG)
304            ReiftShop.bootiq.setItemWithRootCategoryOnly(true);
305
306        ReiftShop.bootiq.setItemWithContributor(true);
307        //ReiftShop.bootiq.setItemWithOtherCurrency(true);
308        ReiftShop.bootiq.setItemCategoryCount(10);
309        ReiftShop.bootiq.setFetchCategoryChildrenWhenNeeded(false);
310        //ReiftShop.bootiq.setOneCategorySelectedAtOnce(true);	// ONE
311        ReiftShop.bootiq.setOneCategoryExpandedAtOnce(false);
312        //ReiftShop.bootiq.setCategorySelectToggle(false);	// ONE
313        ReiftShop.bootiq.setCategorySelectCallback(ReiftShop.categorySelectCallback);
314        ReiftShop.bootiq.setCategoryUnselectCallback(ReiftShop.categoryUnselectCallback);
315        ReiftShop.bootiq.setCategoryCollapseToggle(false);
316        ReiftShop.bootiq.addItemNavigationConfig(new BootiqItemNavigationConfig("top",
317                                                                                "",
318                                                                                document.getElementById("reift-item-list-navigation-top"),
319                                                                                5));
320        ReiftShop.bootiq.addItemNavigationConfig(new BootiqItemNavigationConfig("bottom",
321                                                                                "",
322                                                                                document.getElementById("reift-item-list-navigation-bottom"),
323                                                                                5));
324
325        //ReiftShop.bootiq.drawSearchCriteria();
326        let categoryRootCount = ReiftShop.rootCategoryId.length;
327
328        if (categoryRootCount == 0)
329            ReiftShop.search(false, 0);
330        else 
331            for (let i = 0 ; i < categoryRootCount ; i++)
332                ReiftShop.bootiq.fetchCategoryList(i,
333                                                   0,
334                                                   function(categoryList,
335                                                            index) {
336                                                       ReiftShop.categoryListFetchedCallback(categoryList,
337                                                                                             index);
338                                                   },
339                                                   null);
340
341
342        // Check if someone is logged
343        BootiqRegistration.checkLogin(
344            function(registration,
345                     anonymous) {
346                ReiftShop.setRegistrationInformation(registration);
347                ReiftShop.bootiq.drawMiniCart();
348                //ReiftShop.bootiq.fetchItemList(0, true); only on search
349                ReiftShop.bootiq.fetchCart(0,
350                                           false,
351                                           function(cart) {
352                                               ReiftShop.initialFetch
352("");
353                                           },
354                                           null);
355            },
356            function() {
357                ReiftShop.bootiq.drawMiniCart();
358                //ReiftShop.bootiq.fetchItemList(0, true); only on search
359                ReiftShop.bootiq.fetchCart(0,
360                                           false,
361                                           function(cart) {
362                                               ReiftShop.initialFetch("");
363                                           },
364                                           null);
365            },
366            function(errorList) {
367	              // TODO : show error
368                ReiftShop.bootiq.drawMiniCart();
369                //ReiftShop.bootiq.fetchItemList(0, true); only on search
370                ReiftShop.bootiq.fetchCart(0,
371                                           false,
372                                           function(cart) {
373                                               ReiftShop.initialFetch("");
374                                           },
375                                           null);
376            });
377
378        // Get eventual discounts
379        ReiftShop.getDiscountList();
380    },
381
382
383
384    /**
385     * Sets the title
386     */
387    setTitle: function(title) {
388        let e = document.getElementById("title");
389
390        if (e == null)
391            return;
392
393        e.innerHTML = title;
394
395        if (title == "")
396            e.style.display = "none";
397        else
398            e.style.display = "";
399    },
400
401
402    /**
403     * Initial fetch
404     */
405    initialFetch: function(url) {
406        ReiftShop.bootiq.setContributorId(0);
407
408        // Check url
409        let pathList = window.location.pathname.split("/");
410
411        let code = "";
412        let edition = "";
413        let contributor = "";
414        let selection = "";
415        let selectionStart = "";
416        let selectionEnd = "";
417        let name = "";
418        let exact = false;
419        let headerTitle = "";
420        let headerDescription = "";
421
422        if (pathList.length >= 2) {
423            let count = pathList.length;
424
425            let action = pathList[2];
426            let param = decodeURI(pathList[3]);
427
428            for (let i = 4 ; i < count ; i++)
429                param += "/" + decodeURI(pathList[i]);
430            
431            if (action == "edition") {
432                if (param.toLowerCase() == "bim")
433                    edition = "2";
434                else
435                    edition = "1";
436            }
437            
438            if (action == "contributor") {
439                contributor = param;
440                headerTitle = contributor;
441                headerDescription = contributor;
442            }
443            
444            if (action == "selection") {
445                selection = param;
446                headerTitle = selection;
447                headerDescription = selection;
448            }
449
450            if (action == "emr" || action == "cd" || action == "catalog")
451                code = param;
452            
453            if (action == "title") {
454                name = param;
455                exact = true;
456
457                headerTitle = name;
458                headerDescription = name;
459            }
460
461            if (action == "playalong")
462                code = param;
463        }
464
465        // Check parameters
466        let params = null;
467        
468        if (url == "")
469            params = new URLSearchParams(window.location.search);
470        else
471            params = new URLSearchParams(url);
472
473        if (code == "")
474            code = params.get("code");
475        
476        let search = params.get("search");
477        let recent = params.get("recent");
478
479        if (contributor == "")
480            contributor = params.get("contributor");
481        
482        let categoryId = params.get("categoryId");
483
484        if (name == "") {
485            name = params.get("name");
486            exact = (params.get("exact") == 1);
487        }
488
489        if (edition == "")
490            edition = params.get("searchEdition");
491        
492        let contributorNameList = params.getAll("searchContributorName[]");
493        let contributorRoleList = params.getAll("searchContributorRole[]");
494        let difficulty = params.get("searchDifficulty");
495        let saleRent = params.get("searchSaleRent");
496        let page = parseInt(params.get("page"));
497
498        let fetch = true;
499
500        // Selection
501        if (selection == "")
502            selection = params.get("selection");
503
504        // Code
505        if (code != null) {
506            ReiftShop.setSearchCode(code);
507            ReiftShop.searchByCode(code, 0);
508            return;
509        }
510
511        // Category
512        // Job is done when lists are loaded
513
514        // Recent
515        if (recent != null) {
516            if (ReiftShop.setSelectedRecent(recent,
517                                            false))
518                fetch = true;
519        }
520
521        // Search text
522        if (search != null) {
523            ReiftShop.setSearchText(search);
524            //ReiftShop.bootiq.setSearchCriteria(search);
525            fetch = true;
526        }
527
528        // Contributor
529        if (contributor != null) {
530            ReiftShop.bootiq.setContributor(contributor);
531            fetch = true;
532
533            let e = document.getElementById("criteria");
534            
535            if (e != null) {
536                let name = ReiftShop.bootiq.contributorName;
537                let firstName = ReiftShop.bootiq.contributorFirstName;
538                let lastName = ReiftShop.bootiq.contributorLastName;
539
540                if (name != "")
541                    e.innerHTML = name;
542
543                if (firstName != "") {
544                    if (e.innerHTML == "")
545                        e.innerHTML = firstName;
546                    else
547                        e.innerHTML += ", " + firstName;
548                }
549
550                if (lastName != "") {
551                    if (e.innerHTML == "")
552                        e.innerHTML = lastName;
553                    else
554                        e.innerHTML += " " + lastName;
555                }
556
557                e.style.display = "";
558            }
559        }
560
561        // Selection
562        if (selection != null) {
563            selectionStart = params.get("from");
564            
565            ReiftShop.bootiq.setSelectionStart(params.get("from"));
566            ReiftShop.bootiq.setSelectionEnd(params.get("to"));
567            fetch = true;
568
569            let e = document.getElementById("criteria");
570            
571            if (e != null) {
572                e.innerHTML = selection;
573                e.style.display = "";
574            }
575        }
576
577        // Advanced
578        let advanced = false;
579        let advancedName = "";
580        let advancedComposer = "";
581        let advancedArranger = "";
582        let advancedDifficulty = [];
583        let advancedEdition = [];
584        let advancedSaleRent = [];
585
586        // Advanced - title
587        if (name && name != "") {
588            fetch = true;
589            advanced = true;
590            advancedName = name;
591            //ReiftShop.bootiq.setItemNameCriteria(name);
592        }
593
594
595        // Advanced - Contributor name with role
596        if (contributorNameList != null
597            && contributorNameList.length > 0
598            && contributorRoleList != null
599            && contributorRoleList.length > 0
600            && contributorRoleList != null
601            && contributorRoleList.length > 0) {
602            fetch = true;
603            advanced = true;
604            
605            let countn = contributorNameList.length;
606            let countr = contributorRoleList.length;
607            
608            let count = countn;
609
610            if (countr < count)
611                count = countr;
612            
613            for (let i = 0 ; i < count ; i++) {
614                let roleList = contributorRoleList[i].split(",");
615                
616                for (let j = 0 ; j < count ; j++) {
617                    if (roleList[j] == "composer"
618                        || roleList[j] == "composer-arr")
619                        advancedComposer = contributorNameList[i];
620                    else if (roleList[j] == "arranger"
621                             || roleList[j] == "adapter")
622                        advancedArranger = contributorNameList[i];
623                }
624
625                //ReiftShop.bootiq.addContributorCriteria(contributorNameList[i],
626                //                                      roleList);
627            }
628        }
629
630        // Advanced difficulty
631        if (difficulty != null && difficulty != "") {
632            advancedDifficulty = difficulty.split(",");
633            fetch = true;
634            advanced = true;
635        }
636
637        // Advanced edition
638        if (edition != null && edition != "") {
639            advancedEdition = edition.split(",");
640            fetch = true;
641            advanced = true;
642        }
643
644        // Advanced saleRent
645        if (saleRent != null && saleRent != "") {
646            advancedSaleRent = saleRent.split(",");
647            fetch = true;
648            advanced = true;
649        }
650
651        if (advanced)
652            ReiftShop.setAdvancedSearch(advancedName,
653                                        exact,
654                                        advancedComposer,
655                                        advancedArranger,
656                                        advancedDifficulty,
657                                        advancedEdition,
658                                        advancedSaleRent);
659
660        ReiftShop.searchParamSet = true;
661        
662        if (ReiftShop.allCategoryFetched && ReiftShop.searchParamSet)
663            ReiftShop.search(false,
664                             page);
665
666        // Change header if needed
667        if (headerTitle != "")
668            document.title = headerTitle;
669
670        if (headerDescription) {
671            let meta = document.getElementsByTagName("meta")  
672            meta.description.content = headerDescription.substr(0, 250);
673        }
674
675    },
676
677
678
679
680
681
682    /**
683     * Sets the search text
684     */
685    setSearchText: function(text) {
686        let e = document.getElementById("reift-search-text");
687        
688        if (e == null)
689            return;
690
691        e.value = text;
692    },
693    
694
695    /**
696     * Resets the advanced search content
697     */
698    resetAdvancedSearch: function(search) {
699        let elist = document.getElementsByClassName("reift-search-advanced-input");
700        let count = elist.length;
701
702        for (let i = 0 ; i < count ; i++)
703            elist[i].value = "";
704
705        // Exact name
706        let e = document.getElementById("reift-search-advanced-name-exact");
707
708        if (e != null)
709            e.checked = false;
710
711        // Difficulties
712        elist = document.getElementsByClassName("reift-search-extra-difficulty");
713        count = elist.length;
714
715        for (let i = 0 ; i < count ; i++)
716            BootiqCheckbox.uncheck(elist[i]);
717
718        // Editions
719        elist = document.getElementsByClassName("reift-search-extra-edition");
720        count = elist.length;
721
722        for (let i = 0 ; i < count ; i++)
723            BootiqCheckbox.uncheck(elist[i]);
724
725        // SaleRents
726        elist = document.getElementsByClassName("reift-search-extra-saleRent");
727        count = elist.length;
728
729        for (let i = 0 ; i < count ; i++)
730            BootiqCheckbox.uncheck(elist[i]);
731
732        
733        if (search)
734            ReiftShop.search(false, 0);
735    },
736
737
738    /** 
739     * Unchecks exact search
740     */
741    uncheckExactSearch: function() {
742        let e = document.getElementById("reift-search-advanced-name-exact");
743
744        if (e != null)
745            e.checked = false;
746    },
747    
748
749
750    /**
751     * Sets the search code
752     */
753    setSearchCode: function(code) {
754        ReiftShop.toggleCodeSearch(false, true);
755
756        let e = document.getElementById("reift-search-code");
757
758        if (e != null)
759            e.value = code;
760    },
761
762
763    /**
764     * Sets the advanced search
765     */
766    setAdvancedSearch: function(name,
767                                exact,
768                                composer,
769                                arranger,
770                                difficultyList,
771                                editionList,
772                                saleRentList) {
773        let e = document.getElementById("reift-search-advanced-name");
774
775        if (name != "" || composer != "" || arranger != "")
776            ReiftShop.toggleAdvancedSearch(false, true);
777
778
779        if (e != null)
780            e.value = name;
781
782        e = document.getElementById("reift-search-advanced-name-exact");
783
784        if (e != null)
785            e.checked = exact;
786
787        e = document.getElementById("reift-search-advanced-composer");
788
789        if (e != null)
790            e.value = composer;
791
792        e = document.getElementById("reift-search-advanced-arranger");
793
794        if (e != null)
795            e.value = arranger;
796
797        let count = difficultyList.length;
798
799        for (let i = 0 ; i < count ; i++) {
800            e = document.getElementById("reift-search-extra-difficulty-" + difficultyList[i]);
801
802            if (e != null)
803                BootiqCheckbox.check(e);
804        }
805
806        count = editionList.length;
807
808        for (let i = 0 ; i < count ; i++) {
809            e = document.getElementById("reift-search-extra-edition-" + editionList[i]);
810
811            if (e != null)
812                BootiqCheckbox.check(e);
813        }
814
815        count = saleRentList.length;
816
817        for (let i = 0 ; i < count ; i++) {
818            let srid = "";
819
820            if (saleRentList[i] == "1")
821                srid = "sale";
822            else if (saleRentList[i] == "2")
823                srid = "rent";
824            
825            e = document.getElementById("reift-search-extra-saleRent-" + srid);
826
827            if (e != null)
828                BootiqCheckbox.check(e);
829        }
830
831    },
832
833
834
835    /**
836     * Closes all search blocks
837     */
838    closeAllAdvancedSearchBlock: function(search) {
839        ReiftShop.resetAdvancedSearch(search);
840
841        let e = document.getElementById("reift-search-advanced-block");
842
843        if (e != null)
844            e.style.display = "none";
845
846        e = document.getElementById("reift-search-code-block");
847
848        if (e != null)
849            e.style.display = "none";
850
851        e = document.getElementById("reift-search-advanced-close");
852
853        if (e != null)
854            e.style.display = "none";
855    },
856
857
858    /** 
859     * Toggles advanced search
860     */
861    toggleAdvancedSearch: function(focus,
862                                   open) {
863        ReiftShop.closeAllAdvancedSearchBlock(false);
864
865        let e = document.getElementById("reift-search-advanced-block");
866
867        if (e == null)
868            return;
869
870        if (e.style.display == "" && ! open)
871            e.style.display = "none";
872        else {
873            e.style.display = "";
874
875            let eclose = document.getElementById("reift-search-advanced-close");
876            
877            if (eclose != null)
878                eclose.style.display = "";
879
880            if (focus) {
881                e = document.getElementById("reift-search-advanced-name");
882                
883                if (e != null)
884                    e.focus();
885            }
886        }
887
888    },
889
890
891    /** 
892     * Toggles search by code
893     */
894    toggleCodeSearch: function(focus,
895                               open) {
896        ReiftShop.closeAllAdvancedSearchBlock(false);
897
898        let e = document.getElementById("reift-search-code-block");
899
900        if (e == null)
901            return;
902
903        if (e.style.display == "" && ! open)
904            e.style.display = "none";
905        else {
906            e.style.display = "";
907
908            let eclose = document.getElementById("reift-search-advanced-close");
909            
910            if (eclose != null)
911                eclose.style.display = "";
912
913            if (focus) {
914                e = document.getElementById("reift-search-code");
915                
916                if (e != null)
917                    e.focus();
918            }
919        }
920    },
921
922
923
924    /**
925     * Toggles the category
926     */
927    toggleCategory: function(categoryBlock,
928                             forceClose) {
929        let listElement = categoryBlock.children[1];
930        let toggleElement = categoryBlock.children[0].children[1].children[1];
931
932        if (listElement.style.display == "none"
933            && ! forceClose) {
934            //ReiftShop.closeAllCategoryToggle();
935            
936            listElement.style.display = "";
937            toggleElement.classList.remove("fa-caret-up");
938            toggleElement.classList.add("fa-caret-down");
939        }
940        else {
941            listElement.style.display = "none";
942            toggleElement.classList.remove("fa-caret-down");
943            toggleElement.classList.add("fa-caret-up");
944        }
945    },
946
947
948
949
950    /**
951     * Closes all categories toggles
952     */
953    closeAllCategoryToggle: function() {
954        let headerList = document.getElementsByClassName("category-header");
955        let count = headerList.length;
956        
957        for (let i = 0 ; i < count ; i++) {
958            let e = headerList[i];
959            let listElement = e.parentNode.children[1];
960            let toggleElement = e.children[1].children[1];
961
962            listElement.style.display = "none";
963            toggleElement.classList.remove("fa-caret-down");
964            toggleElement.classList.add("fa-caret-up");
965        }
966    },
967
968
969
970
971    /**
972     * Closes untargeted categories toggles
973     */
974    closeUntargetedCategoryToggle: function(mouseEvent) {
975        let target = mouseEvent.target;
976        
977        let headerList = document.getElementsByClassName("category-header");
978        let count = headerList.length;
979        
980        for (let i = 0 ; i < count ; i++) {
981            let e = headerList[i];
982
983            if (e.parentNode.contains(target))
984                continue;
985            
986            let listElement = e.parentNode.children[1];
987            let toggleElement = e.children[1].children[1];
988
989            listElement.style.display = "none";
990            toggleElement.classList.remove("fa-caret-down");
991            toggleElement.classList.add("fa-caret-up");
992        }
993    },
994
995    
996
997
998    /** 
999     * Sets the selected recent
1000     */
1001    setSelectedRecent: function(dayCount,
1002                                search) {
1003        let ecategoryBlock = document.getElementById("reift-recent-block");
1004
1005        if (ecategoryBlock == null)
1006            return false;
1007        
1008        let children = ecategoryBlock.children[1].children;
1009        let count = children.length;
1010
1011        for (let i = 0 ; i < count ; i++) {
1012            let e = children[i];
1013
1014            if (e.children[0].getAttribute("day") == dayCount) {
1015                ReiftShop.selectRecent(dayCount,
1016                                       e,
1017                                       search);
1018                return true;
1019            }
1020        }
1021        
1022        return false;
1023    },
1024
1025    
1026
1027
1028    /** 
1029     * Selects the recent
1030     */
1031    selectRecent: function(dayCount,
1032                           recentItemElement,
1033                           search) {
1034        let ecategoryBlock = document.getElementById("reift-recent-block");
1035        let etitleBlock = document.getElementById("reift-recent-title-block");
1036        let etitle = null;
1037        
1038        if (etitleBlock != null)
1039            etitle = etitleBlock.children[0];
1040
1041        if (recentItemElement != null) {
1042            if (recentItemElement.getAttribute("_active") == "1")
1043                dayCount = 0;
1044        }
1045
1046        // Unselect first
1047        let erecentBlock = document.getElementById("reift-recent");
1048        let count = erecentBlock.children.length;
1049
1050        for (let i = 0 ; i < count ; i++) {
1051            let erecentItem = erecentBlock.children[i];
1052            
1053            erecentItem.classList.remove("s-category-list-category-block-selected");
1054            erecentItem.children[0].classList.remove("s-category-list-category-name-selected");
1055            erecentItem.setAttribute("_active", "0");
1056        }
1057        
1058        
1059        if (dayCount == 0) {
1060            if (etitleBlock) {
1061                etitleBlock.children[1].children[0].innerHTML = "--";
1062                etitleBlock.children[1].children[1].style.display = "none";
1063            }
1064            
1065            if (etitle) {
1066                etitle.classList.remove("category-title-tiny");
1067                etitle.classList.add("category-title");
1068            }
1069        }
1070        else {
1071            recentItemElement.setAttribute("_active", "1");
1072            recentItemElement.classList.add("s-category-list-category-block-selected");
1073            recentItemElement.children[0].classList.add("s-category-list-category-name-selected");
1074            
1075            if (etitleBlock) {
1076                etitleBlock.children[1].children[0].innerHTML = recentItemElement.children[0].innerHTML;
1077                etitleBlock.children[1].children[1].style.display = "";
1078            }
1079            
1080            if (etitle) {
1081                etitle.classList.remove("category-title");
1082                etitle.classList.add("category-title-tiny");
1083            }
1084        }
1085
1086        ReiftShop.toggleCategory(ecategoryBlock, true);
1087
1088        if (search) {
1089            ReiftShop.search(false, 0);
1090            //ReiftShop.bootiq.fetchItemList(0, true); TWO
1091        }
1092    },
1093
1094    
1095
1096
1097    /**
1098     * Unselects all the categories of div
1099     */
1100    unselectAllCategoryInDiv: function(categoryIndex) {
1101        ReiftShop.bootiq.unselectAllCategoryInDiv(categoryIndex, true);
1102    },
1103
1104    
1105
1106    /**
1107     * Unselects the category
1108     */
1109    unselectCategory: function(categoryIndex,
1110                               categoryId) {
1111        ReiftShop.bootiq.unselectCategoryInDiv(categoryIndex,
1112                                               categoryId,
1113                                               true);
1114    },
1115
1116
1117    /**
1118     * A categeory has been selected
1119     */
1120    categorySelectCallback: function(categoryIndex,
1121                                     categoryId,
1122                                     categoryName) {
1123        // Check if not already selected
1124        let block = document.getElementById("selected-category-" + categoryId);
1125
1126        if (block != null)
1127            return;
1128
1129        // Add into list
1130        let eselectedCategoryBlock = document.getElementById("selected-category-list-" + categoryIndex);
1131
1132        if (eselectedCategoryBlock == null)
1133            return;
1134
1135        eselectedCategoryBlock.style.display = "";
1136
1137        block = document.createElement("div");
1138        block.id = "selected-category-" + categoryId;
1139        block.setAttribute("data-category-index", categoryIndex);
1140        block.setAttribute("data-category-id", categoryId);
1141        block.classList.add("selected-category");
1142
1143        let e = document.createElement("div");
1144        e.classList.add("selected-category-remove");
1145        e.classList.add("fa-solid");
1146        e.classList.add("fa-times");
1147        e.addEventListener("click",
1148                           function() {
1149                               ReiftShop.bootiq.unselectCategoryInDiv(this.parentNode.getAttribute("data-category-index"), this.parentNode.getAttribute("data-category-id"), true);
1150                           });
1151        block.appendChild(e);
1152
1153        e = document.createElement("div");
1154        e.classList.add("selected-category-name");
1155        e.innerHTML = categoryName;
1156        block.appendChild(e);
1157
1158        eselectedCategoryBlock.appendChild(block);
1159
1160        // Set count
1161        let ecategoryBlock = null;
1162        let ecount = null;
1163        let eremove = null;
1164
1165        if (ReiftShop.shopType == REIFT_SHOP_TYPE_BOOK
1166            || ReiftShop.shopType == REIFT_SHOP_TYPE_TOPSALES) {
1167            if (categoryIndex == 0) {
1168                ecategoryBlock = document.getElementById("category-formation-block");
1169                ecount = document.getElementById("category-formation-count");
1170                eremove = document.getElementById("category-formation-remove");
1171            }
1172            else if (categoryIndex == 1) {
1173                ecategoryBlock = document.getElementById("category-instrument-block");
1174                ecount = document.getElementById("category-instrument-count");
1175                eremove = document.getElementById("category-instrument-remove");
1176            }
1177            else if (categoryIndex == 2) {
1178                ecategoryBlock = document.getElementById("category-accompaniment-block");
1179                ecount = document.getElementById("category-accompaniment-count");
1180                eremove = document.getElementById("category-accompaniment-remove");
1181            }
1182            else if (categoryIndex == 3) {
1183                ecategoryBlock = document.getElementById("category-collection-block");
1184                ecount = document.getElementById("category-collection-count");
1185                eremove = document.getElementById("category-collection-remove");
1186            }
1187            else if (categoryIndex == 4) {
1188                ecategoryBlock = document.getElementById("category-style-block");
1189                ecount = document.getElementById("category-style-count");
1190                eremove = document.getElementById("category-style-remove");
1191            }
1192            else if (categoryIndex == 5) {
1193                ecategoryBlock = document.getElementById("category-top-sales-block");
1194                ecount = document.getElementById("category-top-sales-count");
1195                eremove = document.getElementById("category-top-salse-remove");
1196            }
1197        }
1198        else if (ReiftShop.shopType == REIFT_SHOP_TYPE_CD) {
1199            if (categoryIndex == 0) {
1200                ecategoryBlock = document.getElementById("category-formation-block");
1201                ecount = document.getElementById("category-formation-count");
1202                eremove = document.getElementById("category-formation-remove");
1203            }
1204            else if (categoryIndex == 1) {
1205                ecategoryBlock = document.getElementById("category-instrument-block");
1206                ecount = document.getElementById("category-instrument-count");
1207                eremove = document.getElementById("category-instrument-remove");
1208            }
1209            else if (categoryIndex == 2) {
1210                ecategoryBlock = document.getElementById("category-style-block");
1211                ecount = document.getElementById("category-style-count");
1212                eremove = document.getElementById("category-style-remove");
1213            }
1214            else if (categoryIndex == 3) {
1215                ecategoryBlock = document.getElementById("category-artist-block");
1216                ecount = document.getElementById("category-artist-count");
1217                eremove = document.getElementById("category-artist-remove");
1218            }
1219        }
1220        
1221        //if (ecategoryBlock != null)
1222        //    ReiftShop.toggleCategory(ecategoryBlock, true);
1223        
1224        if (ecount != null) {
1225            let count = 0;
1226            
1227            if (ecount.hasAttribute("data-count"))
1228                count = Number(ecount.getAttribute("data-count"));
1229            else
1230                count = 0;
1231            
1232            count++;
1233            
1234            ecount.setAttribute("data-count", count);
1235            
1236            ecount.innerHTML = count;
1237
1238            if (eremove != null)
1239                eremove.style.display = "";
1240        }
1241
1242        return;
1243    },
1244
1245
1246
1247    /**
1248     * A categeory has been deselected
1249     */
1250    categoryUnselectCallback: function(categoryIndex,
1251                                       categoryId) {
1252        // Remove from list
1253        let e = document.getElementById("selected-category-" + categoryId);
1254
1255        if (e == null)
1256            return;
1257        
1258        let parent = e.parentNode;
1259        
1260        e.remove();
1261
1262        if (parent.children.length == 0)
1263            parent.style.display = "none";
1264
1265        // Count
1266        let ecount = null;
1267
1268        if (ReiftShop.shopType == REIFT_SHOP_TYPE_BOOK
1269            || ReiftShop.shopType == REIFT_SHOP_TYPE_TOPSALES) {
1270            if (categoryIndex == 0) {
1271                ecount = document.getElementById("category-formation-count");
1272                eremove = document.getElementById("category-formation-remove");
1273            }
1274            else if (categoryIndex == 1) {
1275                ecount = document.getElementById("category-instrument-count");
1276                eremove = document.getElementById("category-instrument-remove");
1277            }
1278            else if (categoryIndex == 2) {
1279                ecount = document.getElementById("category-accompaniment-count");
1280                eremove = document.getElementById("category-accompaniment-remove");
1281            }
1282            else if (categoryIndex == 3) {
1283                ecount = document.getElementById("category-collection-count");
1284                eremove = document.getElementById("category-collection-remove");
1285            }
1286            else if (categoryIndex == 4) {
1287                ecount = document.getElementById("category-style-count");
1288                eremove = document.getElementById("category-style-remove");
1289            } 
1290            else if (categoryIndex == 5) {
1291                ecount = document.getElementById("category-top-sales-count");
1292                eremove = document.getElementById("category-top-sales-remove");
1293            }
1294        }
1295        if (ReiftShop.shopType == REIFT_SHOP_TYPE_CD) {
1296            if (categoryIndex == 0) {
1297                ecount = document.getElementById("category-formation-count");
1298                eremove = document.getElementById("category-formation-remove");
1299            }
1300            else if (categoryIndex == 1) {
1301                ecount = document.getElementById("category-instrument-count");
1302                eremove = document.getElementById("category-instrument-remove");
1303            }
1304            else if (categoryIndex == 2) {
1305                ecount = document.getElementById("category-style-count");
1306                eremove = document.getElementById("category-style-remove");
1307            }
1308            else if (categoryIndex == 3) {
1309                ecount = document.getElementById("category-artist-count");
1310                eremove = document.getElementById("category-artist-remove");
1311            }
1312        }
1313        
1314        if (ecount != null) {
1315            if (ecount.hasAttribute("data-count"))
1316                count = Number(ecount.getAttribute("data-count"));
1317            else
1318                count = 0;
1319
1320            if (count > 0)
1321                count--;
1322               
1323            ecount.setAttribute("data-count", count);
1324
1325            if (count == 0) {
1326                ecount.innerHTML = "--";
1327
1328                if (eremove)
1329                    eremove.style.display = "none";
1330            }
1331            else
1332                ecount.innerHTML = count;
1333        }
1334        return;
1335    },
1336
1337    
1338
1339
1340    /**
1341     * Sets the login information
1342     */
1343    setRegistrationInformation: function(registration) {
1344        ReiftCart.registration = registration;	// For saving cart
1345
1346        let login = document.getElementById("reift-menu-login");
1347        let user = document.getElementById("reift-menu-user");
1348
1349        if (registration == null) {
1350            if (login != null) 
1351                login.style.display = "";
1352            
1353            if (user != null) {
1354                user.style.display = "none";
1355                user.children[0].innerHTML = "";
1356            }
1357
1358            // Hide comment on detail
1359            let e = document.getElementById("item-add-comment-block");
1360
1361            if (e != null)
1362                e.style.display = "none";
1363
1364            e = document.getElementById("item-add-comment-block-unlogged");
1365
1366            if (e != null)
1367                e.style.display = "";
1368        }
1369        else {
1370            if (login != null) 
1371                login.style.display = "none";
1372            
1373            if (user != null) {
1374                user.children[0].innerHTML = registration.firstName;
1375                user.style.display = "";
1376            }
1377
1378            // Show comment on detail
1379            let e = document.getElementById("item-add-comment-block-unlogged");
1380
1381            if (e != null)
1382                e.style.display = "none";
1383            
1384            e = document.getElementById("item-add-comment-block");
1385
1386            if (e != null)
1387                e.style.display = "";
1388        }
1389    },
1390
1391
1392
1393    /**
1394     * Logged in
1395     */
1396    loggedIn: function(registration) {
1397        // If language changed, call the right page
1398        let e = document.getElementById("current-language");
1399
1400        if (e != null)
1401            if (e.value != registration.language.code) {
1402                ReiftCommon.changeLanguage(e.value,
1403                                           registration.language.code,
1404                                           false,
1405                                           null,
1406                                           null);
1407                return;	// New page called
1408            }
1409
1410        ReiftShop.setRegistrationInformation(registration);
1411        ReiftCommon.closeModal("login-modal");
1412
1413        // Update the discounts
1414        ReiftShop.getDiscountList();
1415
1416        // Update cart and search again to adapt prices to currency
1417        ReiftShop.bootiq.fetchCart(0,
1418                                   false,
1419                                   function(cart) {
1420                                       //ReiftShop.bootiq.fetchItemList(0, true);
1421                                       ReiftShop.search(false, 0);// TWO
1422                                   },
1423                                   null);
1424    },
1425
1426
1427    /**
1428     * Logged out
1429     */
1430    loggedOut: function() {
1431        ReiftShop.setRegistrationInformation(null);
1432
1433        // Update the discounts
1434        ReiftShop.getDiscountList();
1435
1436        // Update cart and search again to adapt prices to currency
1437        ReiftShop.bootiq.fetchCart(0,
1438                                   false,
1439                                   function(cart) {
1440                                       //ReiftShop.bootiq.fetchItemList(0, true);
1441                                       ReiftShop.search(false, 0);// TWO
1442
1443                                   },
1444                                  null);
1445    },
1446
1447
1448
1449    /**
1450     * Opens menu category in header
1451     */
1452    openHeaderMenuCategory: function() {
1453        let e = document.getElementById("reift-top-category-block");
1454
1455        if (e != null) {
1456            e.style.display = "inline-block";
1457        }
1458    },
1459
1460
1461
1462    /**
1463     * Closes the detail
1464     */
1465    closeDetail: function(modalId) {
1466        ReiftShop.pauseAllAudio(null)
1467        BootiqModal.closeModal(modalId);
1468    },
1469
1470
1471
1472
1473    /**
1474     * Categories were fetched
1475     */
1476    categoryListFetchedCallback: function(list,
1477                                          categoryIndex) {
1478        let params = new URLSearchParams(window.location.search);
1479        let categoryId = params.get("categoryId");
1480
1481        if (categoryId != null)
1482            ReiftShop.bootiq.setSelectedCategoryListForIndex(categoryIndex,
1483                                                             [ categoryId ],
1484                                                             false);
1485        else {
1486            let categoryList = params.get("categoryList");
1487            
1488            if (categoryList != null) {
1489                let clist = JSON.parse(categoryList);
1490
1491                ReiftShop.bootiq.setSelectedCategoryList(categoryIndex,
1492                                                         clist,
1493                                                         false);
1494            }
1495        }
1496        
1497        ReiftShop.fetchedCategory[categoryIndex] = true;
1498
1499        let search = true;
1500        let count = ReiftShop.rootCategoryId.length;
1501
1502        for (let i = 0 ; i < count ; i++ )
1503            search &= ReiftShop.fetchedCategory[i];
1504
1505        if (search)
1506            ReiftShop.allCategoryFetched = true;
1507        
1508        if (ReiftShop.allCategoryFetched && ReiftShop.searchParamSet)
1509            ReiftShop.search(false, 0);
1510    },
1511
1512
1513
1514    /**
1515     * A search was run 
1516     * Unused, use itemListFilledCallback instead
1517     */
1518    searchCallback: function(criteria,
1519                             exact) {
1520        //ReiftShop.showResultMessage("");
1521
1522        //ReiftShop.toggleSearchResultSection(true);
1523    },
1524
1525
1526
1527    /**
1528     * Item list has been filled
1529     */
1530    itemCategoryClickCallback: function(categoryId) {
1531        window.location.href = ReiftShop.generateCategoryUrl(categoryId,
1532                                                             ReiftShop.shopType);
1533    },
1534
1535
1536    /**
1537     * Item list starts te be filled
1538     */
1539    itemListFillingCallback: function(count) {
1540        if (count == 0) {
1541            ReiftShop.showResultMessage(ReiftShop.text.message.noMatch);
1542            ReiftShop.toggleSearchResultSection(false);
1543        }
1544        else {
1545            ReiftShop.showResultMessage("");
1546            ReiftShop.toggleSearchResultSection(true);
1547        }
1548    },
1549
1550
1551    /**
1552     * Sticker url callbak
1553     */
1554    stickerUrlCallback: function(item) {
1555        let file = item.code.replace(" ", "") + ".jpg";
1556
1557        return "https://files.reift.ch/files/covers/" + file;
1558    },
1559
1560
1561    /**
1562     * Missing picture callback
1563     */
1564    missingPictureCallback: function(item,
1565                                     element,
1566                                     inList) {
1567        
1568        element.src = this.server + "/bootiqItemStickerDownloader?profileId=" + this.profileId + "&code=" + item.id;
1569
1570        element.onerror = function() {
1571            element.onerror = null;
1572            element.src = "../resources/images/reift-missing-cover.png";
1573        };
1574    },
1575    
1576
1577    /**
1578     * Item list has been filled
1579     */
1580    itemListFilledCallback: function(count) {
1581        // If url is an action, don't do it
1582        /*
1583          let pathList = window.location.pathname.split("/");
1584          
1585          if (pathList.length >= 2) {
1586          let action = pathList[2];
1587          
1588          if (action == "contributor"
1589          || action == "emr"
1590          || action == "title") {
1591          return "";
1592          }
1593          }*/
1594        if (ReiftShop.firstSearch) {
1595            ReiftShop.firstSearch = false;
1596        }
1597        else {
1598            if (! ReiftShop.poppedUrl) {
1599                let pathList = window.location.pathname.split("/");
1600                let url = window.location.protocol + "//" + window.location.hostname + "/" + pathList[1] + "/";
1601                let searchUrl = "";
1602
1603                // Url on code
1604                let e = document.getElementById("reift-search-code");
1605                
1606                if (e != null && e.value != "") {
1607                    if (ReiftShop.shopType == REIFT_SHOP_TYPE_CD)
1608                        url += "cd/" + e.value.replace("CD ", "");
1609                    else if (ReiftShop.shopType == REIFT_SHOP_TYPE_CATALOG)
1610                        url += "catalog/" + e.value.replace("EMRC ", "");	// TODO: CHECK
1611                    else if (ReiftShop.shopType == REIFT_SHOP_TYPE_VOUCHER)
1612                        url += "gift/" + e.value.replace("GIFT ", "");
1613                    else if (ReiftShop.shopType == REIFT_SHOP_TYPE_PLAYALONG)
1614                        url += "playalong/" + e.value;
1615                    else
1616                        ///url += "emr/" + e.value.replace("EMR ", "");
1617                        url += "emr/" + e.value;
1618                }
1619                else {
1620                    searchUrl = ReiftShop.generateSearchUrl();
1621                    
1622                    if (ReiftShop.shopType == REIFT_SHOP_TYPE_CD)
1623                        url += "shopCd.html";
1624                    else if (ReiftShop.shopType == REIFT_SHOP_TYPE_CATALOG)
1625                        url += "shopCatalog.html";
1626                    else if (ReiftShop.shopType == REIFT_SHOP_TYPE_VOUCHER)
1627                        url += "voucher.html";
1628                    else if (ReiftShop.shopType == REIFT_SHOP_TYPE_PLAYALONG)
1629                        url += "playalong.html";
1630                else if (ReiftShop.shopType == REIFT_SHOP_TYPE_TOPSALES)
1631                    url += "topSales.html";
1632			
1633                    else
1634                        url += "shop.html";
1635                }
1636                            
1637                window.history.pushState(
1638                    {
1639                        "searchUrl": searchUrl,
1640                    },
1641                    "Editions Marc Reift",
1642                    url + searchUrl);
1643            }
1644            else
1645                ReiftShop.poppedUrl = false;
1646        }
1647    },
1648
1649
1650
1651    /**
1652     * Item has been drawn
1653     */
1654    itemDrawnCallback: function(item,
1655                                container) {
1656        // Show quantity if min quantity is > 1
1657        if (item.minOrderQuantity > 1) {
1658            let el = container.getElementsByClassName("s-item-list-item-quantity-block");
1659
1660            if (el.length > 0)
1661                el[0].style.display = "flex";
1662        }
1663
1664        // Clear and hide comment
1665        ReiftShop.toggleDetailComment(true, true);
1666
1667        // Sets the item-id to comment
1668        let e = document.getElementById("item-add-comment");
1669
1670        if (e != null)
1671            e.setAttribute("data-item-id",
1672                           item.id);
1673            
1674
1675        // Direct print - not since 2025-08-01
1676        //ReiftShop.checkDpmInDetail(item.code,
1677        //                           ReiftShop.shopType);
1678
1679        // Rentable
1680        e = document.getElementById("item-rentable");
1681
1682        if (e)
1683            e.style.display = (item.rentable ? "" : "none");
1684
1685
1686        // Generate links on http for comment
1687        if (item.comment != "") {
1688            let el = container.getElementsByClassName("d-item-comment");
1689            
1690            if (el.length > 0) {
1691                let expr = /(https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*))/gi;
1692                let regexp = new RegExp(expr);
1693                el[0].innerHTML = el[0].innerHTML.replace(regexp, "<a href='$1' target='_blank'>$1</a>");
1694            }
1695        }
1696
1697
1698        // Copy link
1699        e = document.getElementById("item-copy-link");
1700            
1701        if (e != null)
1702            e.setAttribute("itemCode", item.code);
1703
1704        // Relations
1705        if (ReiftShop.shopType == REIFT_SHOP_TYPE_BOOK
1706            || ReiftShop.shopType == REIFT_SHOP_TYPE_TOPSALES)
1707            ReiftShop.fetchItemReference(item, false);
1708        else if (ReiftShop.shopType == REIFT_SHOP_TYPE_CD) {
1709            // Reset length
1710            let etotal = document.getElementById("item-duration");
1711            
1712            if (etotal != null)
1713                etotal.innerHTML = "";
1714
1715            // Get compositions
1716            ReiftShop.fetchItemComposition(item);
1717        }
1718        else if (ReiftShop.shopType == REIFT_SHOP_TYPE_CATALOG) {
1719            // Get compositions
1720            ReiftShop.fetchItemComposition(item);
1721        }
1722        
1723        if (ReiftShop.shopType == REIFT_SHOP_TYPE_BOOK
1724            || ReiftShop.shopType == REIFT_SHOP_TYPE_TOPSALES) {
1725            // Mp3
1726            let audioContainer = document.getElementById("item-audio-container");
1727            
1728            if (audioContainer != null) {
1729                // Clear first
1730                let children = audioContainer.children;
1731                
1732                while (children.length > 0)
1733                    children[children.length - 1].remove();
1734                
1735                if (audioContainer.children.length > 0)
1736                    audioContainer.removeChild[0];
1737                
1738                try {
1739                    let fileName = item.code.replace(" ", "");
1740                    let mp3Url = "https://files.reift.ch/files/mp3/" + fileName + ".mp3";
1741                    
1742                    fetch(mp3Url, {method: "HEAD"}).then(function(response) {
1743                        let e = document.createElement("audio");
1744
1745                        e.oncontextmenu = function() {
1746                            return false;
1747                        };
1748                        
1749                        e.addEventListener("play", 
1750                                           function(event) {
1751                                               ReiftShop.pauseAllAudio(event.target);
1752                                           }, 
1753                                           true);
1754                        
1755                        e.className = "item-audio";
1756                        e.controls = "controls";
1757                        e.controlsList = "nodownload";
1758                        e.innerHTML = "";
1759                        e.src = mp3Url;
1760                        e.type = "audio/mpeg";
1761                        audioContainer.appendChild(e);
1762                    }).catch(function(error) {
1763                        
1764                    });
1765                }
1766                catch(error) {
1767                }
1768            }
1769            
1770            // Score
1771            let scoreContainer = document.getElementById("item-score-container");
1772            
1773            if (scoreContainer != null) {
1774                // Clear first
1775                let children = scoreContainer.children;
1776                
1777                while (children.length > 0)
1778                    children[children.length - 1].remove();
1779
1780                try {
1781                    if (scoreContainer.children.length > 0)
1782                        scoreContainer.removeChild[0];
1783                    
1784                    let fileName = item.code.replace(" ", "");
1785                    let pdfUrl = "https://files.reift.ch/files/scores/" + fileName + ".pdf";
1786                    
1787                    fetch(pdfUrl, {method: "HEAD"}).then(function(response) {
1788                        let e = document.createElement("a");
1789                        
1790                        e.oncontextmenu = function() {
1791                            return false;
1792                        };
1793                        
1794                        e.className = "fa-duotone fa-file-music reift-item-score";
1795                        e.target = "_blank";
1796                        e.href = pdfUrl;
1797                        scoreContainer.appendChild(e);
1798                    }).catch(function(error) {
1799                        console.log(error);
1800                    });
1801                }
1802                catch(error) {
1803                }
1804            }
1805        }
1806
1807
1808        // Itunes, amazon, youtube and spotify link
1809        if (ReiftShop.shopType != REIFT_SHOP_TYPE_VOUCHER) {
1810            let linkContainer = document.getElementById("item-link-container");
1811            
1812            if (linkContainer != null) {
1813                // Clear first
1814                let children = linkContainer.children;
1815                
1816                while (children.length > 0)
1817                    children[children.length - 1].remove();
1818                
1819                let detailList = item.details;
1820                let count = detailList.length;
1821                
1822                for (let i = 0 ; i < count ; i++) {
1823                    let detail = detailList[i];
1824
1825                    if (detail.value == "")
1826                        continue;
1827
1828                    if (detail.field.code == "itunes") {
1829                        let e = document.createElement("a");
1830                        
1831                        e.oncontextmenu = function() {
1832                            return false;
1833                        };
1834                        
1835                        e.className = "fa-brands fa-itunes itunes-icon reift-item-itunes";
1836                        e.target = "_blank";
1837                        e.href = "https://music.apple.com/" + detail.value;
1838                        linkContainer.appendChild(e);
1839                    }
1840                    else if (detail.field.code == "amazon") {
1841                        let e = document.createElement("a");
1842                        
1843                        e.oncontextmenu = function() {
1844                            return false;
1845                        };
1846                        
1847                        e.className = "fa-brands fa-amazon amazon-icon reift-item-amazon";
1848                        e.target = "_blank";
1849                        e.href = "https://amazon.de/" + detail.value;
1850                        linkContainer.appendChild(e);
1851                    }
1852                    else if (detail.field.code == "youtube") {
1853                        let e = document.createElement("a");
1854                        
1855                        e.oncontextmenu = function() {
1856                            return false;
1857                        };
1858                        
1859                        e.className = "fa-brands fa-youtube youtube-icon reift-item-youtube";
1860                        e.target = "_blank";
1861                        e.href = "https://youtube.com/watch?v=" + detail.value;
1862                        linkContainer.appendChild(e);
1863                    }
1864                    else if (detail.field.code == "spotify") {
1865                        let e = document.createElement("a");
1866                        
1867                        e.oncontextmenu = function() {
1868                            return false;
1869                        };
1870                        
1871                        e.className = "fa-brands fa-spotify spotify-icon reift-item-spotify";
1872                        e.target = "_blank";
1873                        e.href = "https://open.spotify.com/intl-fr/album/" + detail.value;
1874                        linkContainer.appendChild(e);
1875                    }
1876                }
1877            }
1878        }        
1879    },
1880    
1881
1882    /**
1883     * Item in list has been drawn
1884     */
1885    itemDrawnInListCallback: function(item,
1886                                      container) {
1887        // Show quantity if min quantity is > 1
1888        if (item.minOrderQuantity > 1) {
1889            let el = container.getElementsByClassName("s-item-list-item-quantity-block");
1890
1891            if (el.length > 0)
1892                el[0].style.display = "flex";
1893        }
1894
1895        // Replace spcifity by complement if any
1896        if (item.complement != "") {
1897            let el = container.getElementsByClassName("s-item-list-item-sub-name");
1898
1899            if (el.length > 0)
1900                el[0].innerHTML = item.complement;
1901        }
1902            
1903        // Download
1904        if (ReiftShop.shopType == REIFT_SHOP_TYPE_PLAYALONG) {
1905            let cdListUrl = "https://files.reift.ch/getScoreCdList.php?bookCode=" + item.code;
1906            let el = document.createElement("div");
1907            el.classList.add("playalong-download-button-list");
1908
1909            fetch(cdListUrl, {method: "GET"}).then((response) => {
1910                console.log(response);
1911                
1912                if (response.ok)
1913                    return response.text();
1914            }).then((data) => {
1915                console.log(data);
1916                if (data == "Code not found") {
1917                    let label = "No CD";
1918                    let emsg = document.getElementById("playalong-message-nocd");
1919
1920                    if (emsg)
1921                        label = emsg.innerHTML;
1922                    
1923                    let e = document.createElement("div");
1924                    e.classList.add("playalong-nocd-button");
1925                    e.innerHTML = label;
1926                    el.appendChild(e);
1927                }
1928                else {
1929                    
1930                    let cdList = data.split(";");
1931                    let count = cdList.length;
1932                    let itemCode = item.code.replaceAll(" ", "");
1933                    let label = ReiftShop.text.bootiq.item.downloadCd;
1934
1935                    if (count > 1)
1936                        label = ReiftShop.text.bootiq.item.downloadCdN;
1937
1938                    for (let i = 0 ; i < count ; i++) {
1939                        let e = document.createElement("a");
1940                        e.href = "https://files.reift.ch/files/full-scores-cd/" + itemCode + "/" + cdList[i];
1941                        e.classList.add("playalong-download-button");
1942                        e.innerHTML = label.replace("{CD}", (i + 1));
1943                        el.appendChild(e);
1944                    }
1945                }
1946                
1947            }).catch(function(error) {
1948                console.error(error);
1949            });
1950
1951            container.appendChild(el);
1952        }
1953        
1954        if (ReiftShop.shopType != REIFT_SHOP_TYPE_CATALOG
1955            && ReiftShop.shopType != REIFT_SHOP_TYPE_PLAYALONG) {
1956            let linkContainer = document.createElement("div");
1957            linkContainer.classList.add("reift-item-list-link-container");
1958            
1959            // Copy link
1960            let e = document.createElement("div");
1961            e.classList.add("fas");
1962            e.classList.add("fa-link");
1963            e.classList.add("reift-item-list-copy-link");
1964            
1965            e.addEventListener("click",
1966                               function() {
1967                                   ReiftShop.generateItemUrl(item.code,
1968                                                             ReiftShop.shopType,
1969                                                             true);
1970                               });
1971            
1972            linkContainer.appendChild(e);
1973
1974            if (ReiftShop.shopType == REIFT_SHOP_TYPE_BOOK
1975                || ReiftShop.shopType == REIFT_SHOP_TYPE_TOPSALES) {
1976                // Mp3
1977                try {
1978                    let fileName = item.code.replace(" ", "");
1979                    let mp3Url = "https://files.reift.ch/files/mp3/" + fileName + ".mp3";
1980                    
1981                    fetch(mp3Url, {method: "HEAD"}).then(function(response) {
1982                        let e = document.createElement("audio");
1983
1984                        e.oncontextmenu = function() {
1985                            return false;
1986                        };
1987
1988                        e.addEventListener("play", 
1989                                           function(event) {
1990                                               let audioList = document.getElementsByTagName("audio");
1991                                               let count = audioList.length;
1992                                               
1993                                               for (let i = 0 ; i < count ; i++)
1994                                                   if (audioList[i] != event.target)
1995                                                       audioList[i].pause();
1996                                           }, 
1997                                           true);
1998                        
1999                        e.className = "reift-item-list-audio";
2000                        e.controls = "controls";
2001                        e.controlsList = "nodownload";
2002                        e.src = mp3Url;
2003                        e.type = "audio/mpeg";
2004                        container.appendChild(e);	// Not in link container
2005                    }).catch(function(error) {
2006                        
2007                    });
2008
2009                    // Pdf
2010                    let pdfUrl = "https://files.reift.ch/files/scores/" + fileName + ".pdf";
2011
2012                    fetch(pdfUrl, {method: "HEAD"}).then(function(response) {
2013                        let epdf = document.createElement("a");
2014
2015                        epdf.oncontextmenu = function() {
2016                            return false;
2017                        };
2018
2019                        epdf.className = "fa-duotone fa-file-music reift-item-list-score";
2020                        epdf.target = "_blank";
2021                        epdf.href = pdfUrl;
2022                        linkContainer.appendChild(epdf);
2023                        
2024                    }).catch(function(error) {
2025                        
2026                    });
2027                }
2028                catch(error) {
2029                }
2030
2031                // Check if available for download
2032                // Not since 2025-08-01
2033                //ReiftShop.checkDpmInList(container,
2034                //                         item.code);
2035            }
2036            //else if (ReiftShop.shopType == REIFT_SHOP_TYPE_CD) {
2037                // Check if available for download
2038                //ReiftShop.checkCdInList(container,
2039                //                        item.code);
2040            //}
2041
2042            // Itunes, amazon, youtube and spotify link
2043            if (ReiftShop.shopType != REIFT_SHOP_TYPE_VOUCHER
2044               && ReiftShop.shopType != REIFT_SHOP_TYPE_CATALOG) {
2045                let detailList = item.details;
2046                let count = detailList.length;
2047                
2048                for (let i = 0 ; i < count ; i++) {
2049                    let detail = detailList[i];
2050                    
2051                    if (detail.value == "")
2052                        continue;
2053                    
2054                    if (detail.field.code == "itunes") {
2055                        let e = document.createElement("a");
2056                        
2057                        e.oncontextmenu = function() {
2058                            return false;
2059                        };
2060                        
2061                        e.className = "fa-brands fa-itunes itunes-icon reift-item-list-itunes";
2062                        e.target = "_blank";
2063                        e.href = "https://music.apple.com/" + detail.value;
2064                        linkContainer.appendChild(e);
2065                    }
2066                    else if (detail.field.code == "amazon") {
2067                        let e = document.createElement("a");
2068                        
2069                        e.oncontextmenu = function() {
2070                            return false;
2071                        };
2072                        
2073                        e.className = "fa-brands fa-amazon amazon-icon reift-item-list-amazon";
2074                        e.target = "_blank";
2075                        e.href = "https://amazon.de/" + detail.value;
2076                        linkContainer.appendChild(e);
2077                    }
2078                    else if (detail.field.code == "youtube") {
2079                        let e = document.createElement("a");
2080                        
2081                        e.oncontextmenu = function() {
2082                            return false;
2083                        };
2084                        
2085                        e.className = "fa-brands fa-youtube youtube-icon reift-item-list-youtube";
2086                        e.target = "_blank";
2087                        e.href = "https://youtube.com/watch?v=" + detail.value;
2088                        linkContainer.appendChild(e);
2089                    }
2090                    else if (detail.field.code == "spotify") {
2091                        let e = document.createElement("a");
2092                        
2093                        e.oncontextmenu = function() {
2094                            return false;
2095                        };
2096                        
2097                        e.className = "fa-brands fa-spotify spotify-icon reift-item-list-spotify";
2098                        e.target = "_blank";
2099                        e.href = "https://open.spotify.com/intl-fr/album/" + detail.value;
2100                        linkContainer.appendChild(e);
2101                    }
2102                }
2103
2104                container.appendChild(linkContainer);
2105            }
2106        }
2107            
2108    },
2109
2110
2111    /**
2112     * Item has been selected
2113     */
2114    itemSelectedCallback: function(item) {
2115        let parent = document.getElementById("detail-content");
2116
2117        if (parent == null)
2118            return;
2119
2120        ReiftShop.bootiq.drawItemUserMode(item,
2121                                          "d-");
2122
2123        BootiqModal.openModal("detail-modal", "");
2124
2125        if (item.name != "") 
2126            document.title = item.name;
2127
2128        if (item.subName != "")
2129            document.title += " " + item.subName;
2130            
2131        let meta = document.getElementsByTagName("meta")  
2132        //meta.keywords.content = "";
2133
2134        if (item.description != "")
2135            meta.description.content = item.description.substr(0, 250);
2136        
2137    },
2138
2139
2140    /**
2141     * Page has been selected
2142     */
2143    pageSelectedCallback: function(configId,
2144                                   page) {
2145        if (configId == "bottom")
2146            window.scrollTo({ top: 0, behavior: "smooth" });
2147    },
2148
2149
2150
2151    /**
2152     * Shows/Hides search result section
2153     */
2154    toggleSearchResultSection: function(show) {
2155        let e = document.getElementById("reift-item-list-section");
2156
2157        if (e != null) {
2158            if (show)
2159                e.style.display = "";
2160            else
2161                e.style.display = "none";
2162        }
2163    },
2164
2165
2166
2167
2168    /**
2169     * Search
2170     */
2171    search: function(resetCategory,
2172                     page) {
2173        ReiftShop.bootiq.clearContributorCriteriaList();
2174        ReiftShop.bootiq.setItemNameCriteria("");
2175
2176        if (ReiftShop.shopType == REIFT_SHOP_TYPE_BOOK
2177            || ReiftShop.shopType == REIFT_SHOP_TYPE_TOPSALES) 
2178            ReiftShop.bootiq.resetSelectedExternalCategoryList(REIFT_BOOK_EXTERNAL_CATEGORY_COUNT);
2179                
2180        
2181        ReiftShop.bootiq.setSearchInCode(true);
2182
2183        ReiftShop.toggleSearchResultSection(false);
2184
2185        
2186        // Text
2187        let e = document.getElementById("reift-search-text");
2188
2189        if (e != null)
2190            ReiftShop.bootiq.setSearchCriteria(e.value);
2191
2192        // Advanced - name (TODO)
2193        e = document.getElementById("reift-search-advanced-name");
2194        let chk = document.getElementById("reift-search-advanced-name-exact");
2195
2196        if (e != null && e.value != "") {
2197            ReiftShop.bootiq.setItemNameCriteria(e.value);
2198            ReiftShop.bootiq.setSearchInCode(false);
2199        }
2200
2201        if (chk != null)
2202            ReiftShop.bootiq.setSearchExact(chk.checked);
2203
2204        
2205        // Advanced - composer
2206        e = document.getElementById("reift-search-advanced-composer");
2207
2208        if (e != null && e.value != "")
2209            ReiftShop.bootiq.addContributorCriteria(e.value,
2210                                                    [ "composer", "composer-arr" ]);
2211
2212        // Advanced - arranger
2213        e = document.getElementById("reift-search-advanced-arranger");
2214
2215        if (e != null && e.value != "")
2216            ReiftShop.bootiq.addContributorCriteria(e.value,
2217                                                    [ "arranger", "adapter" ]);
2218
2219        // External categories (difficulty, edition, sale/rent, catalog)
2220        let clist = [];
2221
2222        // External categories - difficulty
2223        let elist = document.getElementsByClassName("reift-search-extra-difficulty");
2224        let count = elist.length;
2225
2226        if (count > 0) {
2227            for (let i = 0 ; i < count ; i++) {
2228                e = elist[i];
2229                
2230                if (BootiqCheckbox.isChecked(e))
2231                    clist.push(e.getAttribute("cid"));
2232            }
2233        }
2234
2235        if (clist.length > 0)
2236            ReiftShop.bootiq.setSelectedExternalCategoryList(REIFT_BOOK_EXTERNAL_CATEGORY_DIFFICULTY,
2237                                                             clist);
2238
2239        // External categories - edition
2240        clist = [];
2241        elist = document.getElementsByClassName("reift-search-extra-edition");
2242        count = elist.length;
2243
2244        if (count > 0) {
2245            for (let i = 0 ; i < count ; i++) {
2246                e = elist[i];
2247                
2248                if (BootiqCheckbox.isChecked(e))
2249                    clist.push(e.getAttribute("cid"));
2250            }
2251        }
2252
2253        if (clist.length > 0)
2254            ReiftShop.bootiq.setSelectedExternalCategoryList(REIFT_BOOK_EXTERNAL_CATEGORY_EDITION,
2255                                                             clist);
2256        
2257            
2258
2259        // Sale/rent
2260        let sale = document.getElementById("reift-search-extra-saleRent-sale");
2261        let rent = document.getElementById("reift-search-extra-saleRent-rent");
2262
2263        if (sale)
2264            ReiftShop.bootiq.setNoRentableItemOnly(BootiqCheckbox.isChecked(sale));
2265        else
2266            ReiftShop.bootiq.setNoRentableItemOnly(false);
2267
2268        if (rent)
2269            ReiftShop.bootiq.setRentableItemOnly(BootiqCheckbox.isChecked(rent));
2270        else
2271            ReiftShop.bootiq.setRentableItemOnly(false);
2272
2273        // Recent
2274        let ecategoryBlock = document.getElementById("reift-recent-block");
2275
2276        if (ecategoryBlock != null) {
2277            let children = ecategoryBlock.children[1].children;
2278            let count = children.length;
2279            let found = false;
2280            
2281            for (let i = 0 ; i < count ; i++) {
2282                let e = children[i];
2283                
2284                if (e.getAttribute("_active") == "1") {
2285                    ReiftShop.bootiq.setNewerThan(e.children[0].getAttribute("day"));
2286                    found = true;
2287                    break;
2288                }
2289            }
2290
2291            if (! found)
2292                ReiftShop.bootiq.setNewerThan(0);
2293        }
2294
2295        if (resetCategory)
2296            ReiftShop.bootiq.unselectAllCategory(false);
2297
2298        if (page > 1)
2299            ReiftShop.bootiq.fetchItemList(page - 1, true);
2300        else
2301            ReiftShop.bootiq.fetchItemList(0, true);
2302    },
2303
2304
2305    /**
2306     * Search by code
2307     */
2308    searchByCode: function(code,
2309                           tryNumber) {
2310        code = code.trim();
2311
2312        if (code == "")
2313            return;
2314
2315        // Try...
2316        if (tryNumber != 0) {
2317            let emrcode = ""
2318            
2319            if (tryNumber == 1)
2320                emrcode = "EMR " + code;
2321            else if (tryNumber == 2)
2322                emrcode = "BIM " + code;
2323            else if (tryNumber == 3)
2324                emrcode = "BrP " + code;
2325
2326            if (emrcode == "")
2327                return;
2328
2329            ReiftShop.bootiq.fetchItemListByCode(
2330                emrcode,
2331                true,
2332                function() {
2333                    if (tryNumber >= 3) {
2334                        ReiftShop.toggleSearchResultSection(false);
2335                        ReiftShop.showResultMessage(code + " - " + ReiftShop.text.message.itemNotFound);
2336                        return;
2337                    }
2338
2339                    ReiftShop.searchByCode(code,
2340                                           tryNumber + 1);
2341                });
2342
2343            return;
2344        }
2345
2346        let emr = code.substr(0, 5);
2347        let emrcode = code;
2348
2349        if (ReiftShop.shopType == REIFT_SHOP_TYPE_BOOK
2350            || ReiftShop.shopType == REIFT_SHOP_TYPE_TOPSALES) {
2351            if (emr.substr(0, 3).toUpperCase() != "EMR"
2352                && emr.substr(0, 3).toUpperCase() != "BIM"
2353                && emr.substr(0, 3).toUpperCase() != "BRP") {
2354
2355                ReiftShop.searchByCode(code,
2356                                       1);
2357                
2358                return;
2359            }
2360
2361            if (emrcode.charAt(3) != " ")
2362                emrcode = emrcode.substr(0, 3) + " " + emrcode.substr(3);
2363        }
2364        else if (ReiftShop.shopType == REIFT_SHOP_TYPE_CD) {
2365            if (emr.substr(0, 2).toUpperCase() != "CD")
2366                emrcode = "CD " + emrcode;
2367            else
2368                if (emrcode.charAt(2) != " ")
2369                    emrcode = "CD " + emrcode.substr(2);
2370        }
2371        else if (ReiftShop.shopType == REIFT_SHOP_TYPE_CATALOG) {
2372            if (emr.substr(0, 4).toUpperCase() != "EMRC")
2373                emrcode = "EMRC " + emrcode;
2374            else
2375                if (emrcode.charAt(4) != " ")
2376                    emrcode = "EMRC " + emrcode.substr(4);
2377        }
2378        else if (ReiftShop.shopType == REIFT_SHOP_TYPE_PLAYALONG) {
2379            if (emr.substr(0, 3).toUpperCase() != "EMR"
2380                && emr.substr(0, 3).toUpperCase() != "BIM"
2381                && emr.substr(0, 3).toUpperCase() != "BRP") {
2382
2383                ReiftShop.searchByCode(code,
2384                                       1);
2385                
2386                return;
2387            }
2388
2389            if (emrcode.charAt(3) != " ")
2390                emrcode = emrcode.substr(0, 3) + " " + emrcode.substr(3);
2391        }
2392        
2393        ReiftShop.bootiq.fetchItemListByCode(
2394            emrcode,
2395            true,
2396            function() {
2397                ReiftShop.toggleSearchResultSection(false);
2398                ReiftShop.showResultMessage(code + " - " + ReiftShop.text.message.itemNotFound);
2399            });
2400    },
2401
2402
2403
2404    /**
2405     * Generates the search url
2406     */
2407    generateSearchUrl: function() {
2408        /*
2409          if (! navigator.clipboard) {
2410          ReiftCommon.showMessage(ReiftShop.text.message.noClipboard,
2411          true,
2412          2);
2413          //return;
2414          }
2415        */
2416
2417        
2418        let crit = "";
2419
2420        // Search
2421        if (ReiftShop.bootiq.getSearchCriteria() != "")
2422            crit += "&search=" + encodeURIComponent(ReiftShop.bootiq.getSearchCriteria());
2423
2424        // Item code
2425        /*
2426          too complicated here
2427          let e = document.getElementById("reift-search-code");
2428
2429          if (e != null && e.value != "")
2430          return ReiftShop.generateItemUrl(e.value, ReiftShop.shopType, false);
2431        */
2432        
2433        // Item name
2434        let name = ReiftShop.bootiq.itemNameCriteria;
2435
2436        if (name != "")
2437            crit += "&name=" + encodeURIComponent(name);
2438
2439        // Recent
2440        let recent = ReiftShop.bootiq.getNewerThan();
2441
2442        if (recent != 0)
2443            crit += "&recent=" + encodeURIComponent(recent);
2444
2445        // Categories
2446        let categoryList = ReiftShop.bootiq.getSelectedCategoryList();
2447        let count = categoryList.length;
2448        let categoryArray = [];
2449
2450        for (let i = 0 ; i < count ; i++) {
2451            let clist = categoryList[i];
2452            let ccount = clist.length;
2453
2454            for (let j = 0 ; j < ccount ; j++)
2455                categoryArray.push(Number(clist[j]));
2456        }
2457
2458        if (categoryList != null) {
2459            let count = categoryList.length;
2460            let categoryCount = 0;
2461
2462            for (let i = 0 ; i < count ; i++)
2463                categoryCount += categoryList[i].length;
2464
2465            if (categoryCount > 0)
2466                crit += "&categoryList=" + encodeURIComponent(JSON.stringify(categoryList));
2467        }
2468        
2469        // Contributors
2470        let contributorList = ReiftShop.bootiq.contributorCriteriaList;
2471
2472        if (contributorList != null) {
2473            let count = contributorList.length;
2474
2475            if (count != 0) {
2476                for (let i = 0 ; i < count ; i++) {
2477                    let contributor = contributorList[i];
2478                    let roleList = "";
2479
2480                    for (let j = 0 ; j < contributor.roleList.length ; j++)
2481                        roleList += ", " + contributor.roleList[j];
2482
2483                    crit += "&searchContributorName[]=" + encodeURIComponent(contributor.name) +
2484                        "&searchContributorRole[]=" + encodeURIComponent(roleList.substring(2));
2485                }
2486            }
2487        }
2488
2489        // Difficulties
2490        let elist = document.getElementsByClassName("reift-search-extra-difficulty");
2491        count = elist.length;
2492
2493        if (count > 0) {
2494            let diff = "";
2495            
2496            for (let i = 0 ; i < count ; i++) {
2497                let e = elist[i];
2498                
2499                if (BootiqCheckbox.isChecked(e))
2500                    diff += "," + (i + 1);
2501            }
2502
2503            if (diff != "")
2504                crit += "&searchDifficulty=" + encodeURIComponent(diff.substring(1));
2505        }
2506
2507        // Editions
2508        elist = document.getElementsByClassName("reift-search-extra-edition");
2509        count = elist.length;
2510
2511        if (count > 0) {
2512            let diff = "";
2513            
2514            for (let i = 0 ; i < count ; i++) {
2515                let e = elist[i];
2516                
2517                if (BootiqCheckbox.isChecked(e))
2518                    diff += "," + (i + 1);
2519            }
2520
2521            if (diff != "")
2522                crit += "&searchEdition=" + encodeURIComponent(diff.substring(1));
2523        }
2524
2525        // SaleRents
2526        elist = document.getElementsByClassName("reift-search-extra-saleRent");
2527        count = elist.length;
2528
2529        if (count > 0) {
2530            let diff = "";
2531            
2532            for (let i = 0 ; i < count ; i++) {
2533                let e = elist[i];
2534                
2535                if (BootiqCheckbox.isChecked(e))
2536                    diff += "," + (i + 1);
2537            }
2538
2539            if (diff != "")
2540                crit += "&searchSaleRent=" + encodeURIComponent(diff.substring(1));
2541        }
2542
2543        // Page
2544        if (ReiftShop.bootiq.currentPage > 0)
2545            crit += "&page=" + (ReiftShop.bootiq.currentPage + 1);
2546        
2547        if (crit != "")
2548            crit = "?" + crit.substr(1);
2549
2550
2551        /*
2552          if (navigator.clipboard) {
2553          navigator.clipboard.writeText(window.location.protocol + "//" + window.location.hostname + window.location.pathname + crit);
2554          ReiftCommon.showMessage(ReiftShop.text.message.urlCopied,
2555          false,
2556          3);
2557          }
2558          else
2559          console.info(url);
2560        */
2561
2562        return crit;
2563
2564    },
2565
2566
2567
2568
2569    /**
2570     * Generates the item url
2571     */
2572    generateItemUrl: function(code,
2573                              type,
2574                              copy) {
2575        if (copy && ! navigator.clipboard) {
2576            ReiftCommon.showMessage(ReiftShop.text.message.noClipboard,
2577                                    true,
2578                                    2);
2579            //return;
2580        }
2581
2582        //let url = window.location.protocol + "//" + window.location.hostname +
2583        //    "/" + (ReiftShop.shopType == REIFT_SHOP_TYPE_CD ? "cd" : "emr") + "/" + code;
2584        
2585        let pathList = window.location.pathname.split("/");
2586
2587        let param = "";
2588
2589        if (type == REIFT_SHOP_TYPE_CD)
2590            param = "cd/" + encodeURIComponent(code.replace("CD ", ""));
2591        else if (type == REIFT_SHOP_TYPE_CATALOG)
2592            param = "catalog/" + encodeURIComponent(code.replace("EMRC ", ""));
2593        else if (type == REIFT_SHOP_TYPE_VOUCHER)
2594            param = "gift/" + encodeURIComponent(code.replace("GIFT ", ""));
2595        else if (type == REIFT_SHOP_TYPE_PLAYALONG)
2596            param = "playalong/" + encodeURIComponent(code);
2597        else
2598            //param = "emr/" + code.replace("EMR ", "");
2599            param = "emr/" + encodeURIComponent(code);
2600            
2601
2602        let url = window.location.protocol + "//" + window.location.hostname + "/" + pathList[1] + "/" + param;
2603
2604        if (copy) {
2605            if (navigator.clipboard) {
2606                navigator.clipboard.writeText(url);
2607                ReiftCommon.showMessage(ReiftShop.text.message.urlCopied,
2608                                        false,
2609                                        3);
2610            }
2611            else
2612                console.info(url);
2613
2614        }
2615
2616        return url;
2617    },
2618
2619
2620
2621    /**
2622     * Generates the category url
2623     */
2624    generateCategoryUrl: function(id,
2625                                  type) {
2626        let pathList = window.location.pathname.split("/");
2627
2628        let page = "";
2629
2630        if (type == REIFT_SHOP_TYPE_CD)
2631            page = "shopCd.html";
2632        else if (type == REIFT_SHOP_TYPE_CATALOG)
2633            page = "shopCatalog.html";
2634        else if (type == REIFT_SHOP_TYPE_VOUCHER)
2635            page = "voucher.html";
2636        else if (type == REIFT_SHOP_TYPE_PLAYALONG)
2637            page = "playalong.html";
2638        else if (type == REIFT_SHOP_TYPE_TOPSALES)
2639            page = "topSales.html";
2640
2641        else
2642            page = "shop.html";
2643
2644        return window.location.protocol + "//" + window.location.hostname + "/" + pathList[1] + "/" + page + "?categoryId=" + id;
2645    },
2646
2647
2648    /** 
2649     * Shows the result message
2650     */
2651    showResultMessage: function(message) {
2652        let e = document.getElementById("result-message-block");
2653
2654        if (e == null)
2655            return;
2656
2657        if (message == "")
2658            e.style.display = "none";
2659        else
2660            e.style.display = "";
2661
2662        e = e.children[0];
2663
2664        if (e == null)
2665            return;
2666
2667        e.innerHTML = message;
2668    },
2669
2670
2671
2672    
2673
2674    /**
2675     * Toggles categories section
2676     */
2677    toggleCategorySection: function(show) {
2678        let e = document.getElementById("category-section");
2679
2680        if (e == null)
2681            return;
2682
2683        if (e.style.display == "none" || e.style.display == "")
2684            e.style.display = "block";
2685        else
2686            e.style.display = "none";
2687    },
2688
2689
2690
2691    /**
2692     * A difficulty was clicked
2693     */
2694    difficultyClicked: function(element,
2695                                checked) {
2696        ReiftShop.search(false, 0);
2697    },
2698
2699
2700
2701    /**
2702     * A edition was clicked
2703     */
2704    editionClicked: function(element,
2705                             checked) {
2706        ReiftShop.search(false, 0);
2707    },
2708
2709
2710
2711    /**
2712     * A saleRent was clicked
2713     */
2714    saleRentClicked: function(element,
2715                              checked) {
2716        ReiftShop.search(false, 0);
2717    },
2718
2719
2720
2721    /**
2722     * Fetches and draws the item reference
2723     */
2724    fetchItemReference: function(item,
2725                                 withReverse) {
2726        let e = document.getElementById("d-item-reference-section");
2727        let e1 = document.getElementById("d-item-reference-section-1");
2728        let es = document.getElementById("d-item-similar-section");
2729
2730        if (e == null && e1 == null)
2731            return;
2732
2733        if (e != null) {
2734            let children = e.children;
2735            
2736            while (children.length > 0)
2737                children[children.length - 1].remove();
2738        }
2739
2740        if (e1 != null) {
2741            children = e1.children;
2742            
2743            while (children.length > 0)
2744                children[children.length - 1].remove();
2745        }
2746
2747        if (es != null) {
2748            children = es.children;
2749            
2750            while (children.length > 0)
2751                children[children.length - 1].remove();
2752        }
2753
2754        ReiftShop.bootiq.fetchItemRelationList(item,
2755                                               withReverse,
2756                                               true,
2757                                               true,
2758                                               true,
2759                                               false,
2760                                               null,
2761                                               false,
2762                                               function(relationList) {
2763                                                   if (e != null)
2764                                                       ReiftShop.drawItemReference(item,
2765                                                                                   relationList,
2766                                                                                   e);
2767                                                   
2768                                                   if (e1 != null)
2769                                                       ReiftShop.drawItemReference(item,
2770                                                                                   relationList,
2771                                                                                   e1);
2772                                                   
2773                                                   if (es != null)
2774                                                       ReiftShop.drawItemSimilar(item,
2775                                                                                 relationList,
2776                                                                                 es);
2777                                               },
2778                                               function(errorList) {
2779                                                   console.error(errorList);
2780                                               });
2781    },
2782
2783
2784
2785    /**
2786     * Draws the item reference
2787     */
2788    drawItemReference: function(item,
2789                                relationList,
2790                                container) {
2791        let refersToList = relationList.refersTo;
2792        let count = refersToList.length;
2793
2794        let cdCount = 0;
2795
2796        // Cound Cds
2797        for (let i = 0 ; i < count ; i++)
2798            if (refersToList[i].item.type.code == "cd")
2799                cdCount++;
2800
2801        if (cdCount > 0) {
2802            let e = document.createElement("div");
2803            e.classList.add("d-item-reference-title");
2804            e.innerHTML = ReiftShop.text.bootiq.relation.availableOnCD;
2805            container.appendChild(e);
2806
2807            let cdList = document.createElement("div");
2808            cdList.classList.add("d-item-reference");
2809            
2810            for (let i = 0 ; i < count ; i++) {
2811                let refersTo = refersToList[i];
2812                let refersItem = refersTo.item;
2813
2814                if (refersItem.type.code != "cd")
2815                    co
2815ntinue;
2816
2817                let block = document.createElement("a");
2818                block.classList.add("d-item-reference-block");
2819                block.href = ReiftShop.generateItemUrl(refersItem.code,
2820                                                       REIFT_SHOP_TYPE_CD,
2821                                                       false);
2822                // Cover
2823                let server = ReiftCommon.server;
2824                let profileId = ReiftCommon.profileId;
2825
2826                let e = document.createElement("img");
2827                e.classList.add("d-item-reference-item-cover");
2828                e.src = this.stickerUrlCallback(refersItem);
2829                e.alt = "";
2830                block.appendChild(e);
2831
2832                let detailBlock = document.createElement("div");
2833                detailBlock.classList.add("d-item-reference-item-detail");
2834                
2835                // Code
2836                e = document.createElement("div");
2837                e.classList.add("d-item-reference-item-code");
2838                e.innerHTML = refersItem.code;
2839                detailBlock.appendChild(e);
2840
2841                // Name
2842                e = document.createElement("div");
2843                e.classList.add("d-item-reference-item-name");
2844                e.innerHTML = refersItem.name;
2845                detailBlock.appendChild(e);
2846
2847                // Subname
2848                e = document.createElement("div");
2849                e.classList.add("d-item-reference-item-more-reference-item-sub-name");
2850                e.innerHTML = refersItem.subName;
2851                detailBlock.appendChild(e);
2852
2853                block.appendChild(detailBlock);
2854
2855                cdList.appendChild(block);
2856            }
2857
2858            container.appendChild(cdList);
2859        }
2860        
2861    },
2862
2863
2864
2865    /**
2866     * Draws the item similar
2867     */
2868    drawItemSimilar: function(item,
2869                              relationList,
2870                              container) {
2871        let similarToList = relationList.similarTo;
2872        let count = similarToList.length;
2873
2874        let bookCount = 0;
2875
2876        // Cound books
2877        for (let i = 0 ; i < count ; i++)
2878            if (similarToList[i].item.type.code == "book")
2879                bookCount++;
2880
2881        if (bookCount > 0) {
2882            let e = document.createElement("div");
2883            e.classList.add("d-item-reference-title");
2884            e.innerHTML = ReiftShop.text.bootiq.relation.similar;
2885            container.appendChild(e);
2886
2887            let bookList = document.createElement("div");
2888            bookList.classList.add("d-item-reference");
2889            
2890            for (let i = 0 ; i < count ; i++) {
2891                let similarTo = similarToList[i];
2892                let similarItem = similarTo.item;
2893
2894                if (similarItem.type.code != "book")
2895                    continue;
2896
2897                let block = document.createElement("a");
2898                block.classList.add("d-item-reference-block");
2899                block.href = ReiftShop.generateItemUrl(similarItem.code,
2900                                                       REIFT_SHOP_TYPE_BOOK,
2901                                                       false);
2902                // Cover
2903                let server = ReiftCommon.server;
2904                let profileId = ReiftCommon.profileId;
2905
2906                let e = document.createElement("img");
2907                e.classList.add("d-item-reference-item-cover");
2908                e.src = this.stickerUrlCallback(similarItem);
2909                e.alt = "";
2910                block.appendChild(e);
2911
2912                let detailBlock = document.createElement("div");
2913                detailBlock.classList.add("d-item-reference-item-detail");
2914                
2915                // Code
2916                e = document.createElement("div");
2917                e.classList.add("d-item-reference-item-code");
2918                e.innerHTML = similarItem.code;
2919                detailBlock.appendChild(e);
2920
2921                // Name
2922                e = document.createElement("div");
2923                e.classList.add("d-item-reference-item-name");
2924                e.innerHTML = similarItem.name;
2925                detailBlock.appendChild(e);
2926
2927                // Subname
2928                e = document.createElement("div");
2929                e.classList.add("d-item-reference-item-more-reference-item-sub-name");
2930                e.innerHTML = similarItem.subName;
2931                detailBlock.appendChild(e);
2932
2933                block.appendChild(detailBlock);
2934
2935                bookList.appendChild(block);
2936            }
2937
2938            container.appendChild(bookList);
2939        }
2940        
2941    },
2942
2943
2944
2945    /**
2946     * Fetches and draws the item composition
2947     */
2948    fetchItemComposition: function(item) {
2949        let e = document.getElementById("d-item-composition-section");
2950
2951        if (e == null)
2952            return;
2953        
2954        let children = e.children;
2955        
2956        while (children.length > 0)
2957            children[children.length - 1].remove();
2958
2959        // Fetch relations, with categories if shop is catalog
2960        let withCategoryList = false;
2961        let ancestorCategoryList = null;
2962
2963        if (ReiftShop.shopType == REIFT_SHOP_TYPE_CATALOG) {
2964            withCategoryList = true;
2965            
2966            let count = item.categories.length;
2967
2968            for (i = 0 ; i < count ; i++) {
2969                let category = item.categories[i];
2970
2971                if (category.parent.id == ReiftShop.catalogCategoryId) {
2972                    ancestorCategoryList = [ item.categories[i].id ];
2973                    break;
2974                }
2975            }
2976        }
2977
2978        ReiftShop.bootiq.fetchItemRelationList(item,
2979                                               true,
2980                                               true,
2981                                               true,
2982                                               true,
2983                                               withCategoryList,
2984                                               ancestorCategoryList,
2985                                               false,
2986                                               function(relationList) {
2987                                                   if (e == null)
2988                                                       return;
2989                                                   
2990                                                   let totalLength = ReiftShop.drawItemComposition(item,
2991                                                                                                   relationList,
2992                                                                                                   e);
2993
2994                                                   if (totalLength != 0) {
2995                                                       let etotal = document.getElementById("item-duration");
2996                                                       
2997                                                       if (etotal == null)
2998                                                           return;
2999                                                       
3000                                                       etotal.innerHTML = ReiftShop.formatDuration(totalLength, "'");
3001                                                   }
3002                                               },
3003                                               function(errorList) {
3004                                                   console.error(errorList);
3005                                               });
3006    },
3007
3008
3009
3010    /**
3011     * Draws the item composition
3012     */
3013    drawItemComposition: function(item,
3014                                  relationList,
3015                                  container) {
3016        let composedByList = relationList.composedBy;
3017        let count = composedByList.length;
3018        let totalLength = 0;
3019        let categoryList = [];
3020
3021        if (ReiftShop.shopType == REIFT_SHOP_TYPE_CATALOG) {
3022            ReiftShop.drawItemCompositionHeaderBook(container);
3023
3024            // Build the list of categories
3025            for (let i = 0 ; i < count ; i++) {
3026                let composedItem = composedByList[i].item;
3027                let itemCategoryList = composedItem.categories;
3028
3029                let categoryId = 0;
3030                let categoryName = "";
3031                let found = false;
3032                
3033                if (itemCategoryList.length > 0) {
3034                    categoryId = itemCategoryList[0].id;
3035                    categoryName = itemCategoryList[0].name;
3036                }
3037
3038                // Check if exists
3039                let categoryCount = categoryList.length;
3040
3041                for (let j = 0 ; j < categoryCount ; j++) {
3042                    let category = categoryList[j];
3043                    
3044                    if (category.id == categoryId) {
3045                        found = true;
3046                        break;
3047                    }
3048                }
3049
3050                if (! found)
3051                    categoryList.push({ id: categoryId,
3052                                        name: categoryName,
3053                                        container: null });
3054            }
3055
3056            let categoryCount = categoryList.length;
3057            
3058            for (let i = 0 ; i < categoryCount ; i++) {
3059                let category = categoryList[i];
3060                let e = ReiftShop.drawItemCompositionCategory(container,
3061                                                              category.id,
3062                                                              category.name,
3063                                                              i + 1)
3064                category.container = e;
3065            }
3066        }
3067        
3068        let categoryCount = categoryList.length;
3069        
3070        for (let i = 0 ; i < count ; i++) {
3071            let composedBy = composedByList[i];
3072            let composedItem = composedBy.item;
3073            
3074            if (composedItem.type.code == "cd")
3075                totalLength = ReiftShop.drawItemCompositionCd(composedItem,
3076                                                              container);
3077            else if (composedItem.type.code == "book") {
3078                let itemCategoryList = composedItem.categories;
3079                let categoryId = (itemCategoryList.length > 0 ? itemCategoryList[0].id : 0);
3080                let sequence = 1;
3081
3082                let categoryContainer = container;
3083
3084                for (let j = 0 ; j < categoryCount ; j++) {
3085                    let category = categoryList[j];
3086                    
3087                    if (category.id == categoryId) {
3088                        categoryContainer = category.container;
3089                        sequence = categoryContainer.children.length + 1;
3090                        break;
3091                    }
3092                }
3093
3094                totalLength = ReiftShop.drawItemCompositionBook(composedItem,
3095                                                                categoryContainer,
3096                                                                sequence);
3097            }
3098            else if (composedItem.type.code == "mp3")
3099                totalLength = ReiftShop.drawItemCompositionMp3(composedItem,
3100                                                               container,
3101                                                               i + 1);
3102        }
3103
3104        return totalLength;
3105    },
3106
3107
3108    /**
3109     * Draws the item composition for CD
3110    */
3111    drawItemCompositionCd: function(composedItem,
3112                                    container) {
3113        let totalLength = 0;
3114
3115        // Child CD line
3116        let line = document.createElement("div");
3117        line.classList.add("d-item-composition-cd");
3118        
3119        let eblock = document.createElement("div");
3120        eblock.classList.add("d-item-composition-cd-title-block");
3121            
3122            
3123        let e = document.createElement("div");
3124        e.classList.add("d-item-composition-cd-title");
3125        e.innerHTML = composedItem.name;
3126        //e.innerHTML = composedItem.description;
3127        e.setAttribute("data-read", "0");
3128        e.setAttribute("data-open", "0");
3129        e.addEventListener(
3130            "click",
3131            function() {
3132                let me = this.parentNode.parentNode;
3133                
3134                if (this.getAttribute("data-read") == "0") {
3135                    this.setAttribute("data-read", "1");
3136                    
3137                    ReiftShop.bootiq.fetchItemRelationList(
3138                        composedItem,
3139                        true,
3140                        true,
3141                        true,
3142                        true,
3143                        false,
3144                        null,
3145                        true,
3146                        function(relationList) {
3147                            let totalLength = ReiftShop.drawItemComposition(composedItem,
3148                                                                            relationList,
3149                                                                            me.children[1]);
3150                            
3151                            if (totalLength != 0)
3152                                me.children[0].children[0].innerHTML += " (" + ReiftShop.formatDuration(totalLength, "'") + ")";
3153                        },
3154                        function(errorList) {
3155                            console.error(errorList);
3156                        });
3157                }
3158                if (this.getAttribute("data-open") == "0") {
3159                    me.children[1].style.display = "";
3160                    this.setAttribute("data-open", "1");
3161                }
3162                else {
3163                    me.children[1].style.display = "none";
3164                    this.setAttribute("data-open", "0");
3165                }
3166            });
3167        
3168        eblock.appendChild(e);
3169        
3170        // Link on CD if it is an e-bootiq one
3171        if (composedItem.eBootiq == 1) {
3172            e = document.createElement("a");
3173            e.classList.add("fa-light", "fa-compact-disc", "d-item-composition-cd-link");
3174            e.href = ReiftShop.generateItemUrl(composedItem.code,
3175                                               ReiftShop.shopType,
3176                                               false);
3177            eblock.appendChild(e);
3178        }
3179        
3180        line.appendChild(eblock);
3181        
3182        e = document.createElement("div");
3183        e.classList.add("d-item-composition-cd-detail");
3184        line.appendChild(e);
3185        
3186        container.appendChild(line);
3187
3188        return totalLength;
3189    },
3190
3191
3192    /**
3193     * Draws the item composition header for Book
3194     */
3195    drawItemCompositionHeaderBook: function(container) {
3196        let compositionBlock = document.createElement("div");
3197        compositionBlock.classList.add("d-item-composition-block");
3198
3199        // First line
3200        let efirstLine = document.createElement("div");
3201        efirstLine.classList.add("d-item-composition-main");
3202
3203        // Sequence
3204        e = document.createElement("div");
3205        e.classList.add("d-item-composition-sequence");
3206        efirstLine.appendChild(e);
3207
3208        let emain = document.createElement("div");
3209        emain.classList.add("d-item-composition-item");
3210
3211        // Code
3212        let block = document.createElement("div");
3213        block.classList.add("d-item-composition-item-block");
3214                            
3215        e = document.createElement("div");
3216        e.classList.add("d-item-composition-code");
3217        e.innerHTML = ReiftShop.text.bootiq.relation.bookHeader.code;
3218        block.appendChild(e);
3219
3220        // Name
3221        e = document.createElement("div");
3222        e.classList.add("d-item-composition-name");
3223        e.innerHTML = ReiftShop.text.bootiq.relation.bookHeader.name;
3224        block.appendChild(e);
3225
3226        // Contributors
3227        let contributorBlock = document.createElement("div");
3228        contributorBlock.classList.add("d-item-composition-contributor-block");
3229        contributorBlock.innerHTML = ReiftShop.text.bootiq.relation.bookHeader.contributor;
3230        block.appendChild(contributorBlock);
3231
3232        emain.appendChild(block);
3233
3234        
3235        block = document.createElement("div");
3236        block.classList.add("d-item-composition-item-detail-block");
3237
3238
3239        // Difficulty
3240        e = document.createElement("div");
3241        e.classList.add("d-item-composition-difficulty");
3242        e.innerHTML = ReiftShop.text.bootiq.relation.bookHeader.difficulty;
3243        block.appendChild(e);
3244
3245
3246        // Length
3247        e = document.createElement("div");
3248        e.classList.add("d-item-composition-length");
3249        e.innerHTML = ReiftShop.text.bootiq.relation.bookHeader.length;
3250        block.appendChild(e);
3251
3252
3253        // PDF 
3254        e = document.createElement("div");
3255        e.classList.add("d-item-composition-score-header");
3256        e.classList.add("fa-light");
3257        e.classList.add("fa-file-music");
3258        block.appendChild(e);
3259
3260        // Audio
3261        e = document.createElement("div");
3262        e.classList.add("d-item-composition-audio-toggle");
3263        e.classList.add("fa-light");
3264        e.classList.add("fa-music");
3265        block.appendChild(e);
3266        emain.appendChild(block);
3267        
3268        efirstLine.appendChild(emain);
3269        compositionBlock.appendChild(efirstLine);
3270        container.appendChild(compositionBlock);
3271    },
3272
3273
3274    /**
3275     * Draws the item composition category
3276     */
3277    drawItemCompositionCategory: function(container,
3278                                          categoryId,
3279                                          categoryName,
3280                                          sequence) {
3281        let block = document.createElement("div");
3282        block.classList.add("d-item-composition-category-block");
3283
3284        let e = document.createElement("div");
3285        e.classList.add("d-item-composition-category-title");
3286        e.classList.add("d-item-composition-category-title-" + sequence);
3287        e.innerHTML = categoryName;
3288        block.appendChild(e);
3289
3290        e = document.createElement("div");
3291        e.classList.add("d-item-composition-category-content");
3292        block.appendChild(e);
3293
3294        container.appendChild(block);
3295
3296        return e;
3297    },
3298
3299
3300    /**
3301     * Draws the item composition for Book
3302     */
3303    drawItemCompositionBook: function(composedItem,
3304                                      container,
3305                                      sequence) {
3306        let totalLength = 0;
3307    
3308        let compositionBlock = document.createElement("div");
3309        compositionBlock.classList.add("d-item-composition-block");
3310
3311        // First line
3312        let efirstLine = document.createElement("div");
3313        efirstLine.classList.add("d-item-composition-main");
3314
3315        // Link
3316        let link = ReiftShop.generateItemUrl(composedItem.code,
3317                                             REIFT_SHOP_TYPE_BOOK,
3318                                             false);
3319
3320        // Sequence
3321        e = document.createElement("div");
3322        e.classList.add("d-item-composition-sequence");
3323        e.innerHTML = sequence + ".";
3324        efirstLine.appendChild(e);
3325
3326        let emain = document.createElement("div");
3327        emain.classList.add("d-item-composition-item");
3328
3329        
3330        let block = document.createElement("div");
3331        block.classList.add("d-item-composition-item-block");
3332
3333        // Code
3334        e = document.createElement("a");
3335        e.href = link;
3336        e.classList.add("d-item-composition-code");
3337        e.innerHTML = composedItem.code;
3338        block.appendChild(e);
3339
3340        // Name
3341        e = document.createElement("a");
3342        e.href = link;
3343        e.classList.add("d-item-composition-name");
3344        e.innerHTML = composedItem.name;
3345        block.appendChild(e);
3346                            
3347        // Contributors
3348        let contributorBlock = document.createElement("div");
3349        contributorBlock.classList.add("d-item-composition-contributor-block");
3350        let arrangerCount = 0;
3351
3352        /* Contributor (only composer) */
3353        let composerBlock = document.createElement("div");
3354        composerBlock.classList.add("d-item-composition-composer-block");
3355
3356        if (composedItem.hasOwnProperty("contributors")) {
3357            let contributorList = composedItem.contributors;
3358            let contributorCount = contributorList.length;
3359
3360            for (let j = 0 ; j < contributorCount ; j++) {
3361                let contributor = contributorList[j];
3362                
3363                if (contributor.role.code != "composer"
3364                    && contributor.role.code != "composer-arr") {
3365                    arrangerCount++;
3366                    continue;
3367                }
3368
3369                let e = document.createElement("div");
3370                e.classList.add("d-item-composition-composer");
3371
3372                if (contributor.role.code == "composer-arr")
3373                    e.classList.add("d-item-composition-composer-arr");
3374                
3375                if (contributor.companyName != "")
3376                    e.innerHTML = contributor.companyName;
3377                else {
3378                    if (contributor.firstName != "")
3379                        e.innerHTML = contributor.firstName + " ";
3380
3381                    if (contributor.lastName != "")
3382                        e.innerHTML += contributor.lastName;
3383                }
3384
3385                composerBlock.appendChild(e);
3386            }
3387        }
3388
3389        contributorBlock.appendChild(composerBlock);
3390        
3391        /* Contributor (only arranger) */
3392        if (arrangerCount > 0) {
3393            let arrangerBlock = document.createElement("div");
3394            arrangerBlock.classList.add("d-item-composition-arranger-block");
3395
3396            let contributorList = composedItem.contributors;
3397            let contributorCount = contributorList.length;
3398
3399            for (let j = 0 ; j < contributorCount ; j++) {
3400                let contributor = contributorList[j];
3401                
3402                if (contributor.role.code != "arranger"
3403                    && contributor.role.code != "adapter")
3404                    continue;
3405
3406                let e = document.createElement("div");
3407                e.classList.add("d-item-composition-arranger");
3408
3409                if (contributor.role.code == "adapter")
3410                    e.classList.add("d-item-composition-adapter");
3411                
3412                if (contributor.companyName != "")
3413                    e.innerHTML = contributor.companyName;
3414                else {
3415                    if (contributor.firstName != "")
3416                        e.innerHTML = contributor.firstName + " ";
3417
3418                    if (contributor.lastName != "")
3419                        e.innerHTML += contributor.lastName;
3420                }
3421
3422                arrangerBlock.appendChild(e);
3423            }
3424
3425            contributorBlock.appendChild(arrangerBlock);
3426        }
3427
3428        block.appendChild(contributorBlock);
3429
3430        emain.appendChild(block);
3431
3432
3433        block = document.createElement("div");
3434        block.classList.add("d-item-composition-item-detail-block");
3435
3436        // Difficulty
3437        e = document.createElement("div");
3438        e.classList.add("d-item-composition-difficulty");
3439
3440        if (composedItem.hasOwnProperty("details")) {
3441            let detailList = composedItem.details;
3442            let detailCount = detailList.length;
3443
3444            for (let j = 0 ; j < detailCount ; j++) {
3445                let detail = detailList[j];
3446                let field = detail.field;
3447
3448                if (field.code != "difficulty")
3449                    continue;
3450                
3451                e.innerHTML = detail.value;
3452
3453                break;
3454            }
3455        }
3456        
3457        block.appendChild(e);
3458
3459
3460        // Length
3461        e = document.createElement("div");
3462        e.classList.add("d-item-composition-length");
3463
3464        if (composedItem.hasOwnProperty("details")) {
3465            let detailList = composedItem.details;
3466            let detailCount = detailList.length;
3467
3468            for (let j = 0 ; j < detailCount ; j++) {
3469                let detail = detailList[j];
3470                let field = detail.field;
3471
3472                if (field.code != "length")
3473                    continue;
3474                
3475                e.innerHTML = detail.value;
3476
3477                totalLength += ReiftShop.convertDuration(detail.value);
3478
3479                break;
3480            }
3481        }
3482
3483        block.appendChild(e);
3484
3485        // Pdf
3486        let epdf = document.createElement("a");
3487        epdf.classList.add("d-item-composition-score");
3488                        
3489        let fileName = composedItem.code.replace(" ", "");
3490        let pdfUrl = "https://files.reift.ch/files/scores/" + fileName + ".pdf";
3491        
3492        fetch(pdfUrl, {method: "HEAD"}).then(function(response) {
3493            epdf.oncontextmenu = function() {
3494                return false;
3495            };
3496
3497            epdf.classList.add("fa-duotone");
3498            epdf.classList.add("fa-file-music");
3499            epdf.target = "_blank";
3500            epdf.href = pdfUrl;
3501            console.log(pdfUrl);            
3502        }).catch(function(error) {
3503            console.log(error);
3504            console.error(pdfUrl);
3505        });
3506
3507        block.appendChild(epdf);
3508
3509
3510        // Audio
3511        e = document.createElement("div");
3512        e.classList.add("fa-solid", "fa-music", "d-item-composition-audio-toggle");
3513        e.innerHTML = "";
3514        e.addEventListener("click",
3515                           function() {
3516                               ReiftShop.pauseAllAudio(null)
3517                               ReiftShop.closeAllItemAudio(this.parentNode.parentNode.parentNode.parentNode);
3518                               ReiftShop.toggleItemAudioPlayer(this.parentNode.parentNode.parentNode.parentNode, this);
3519                               event.stopPropagation();
3520                           });
3521        block.appendChild(e);
3522
3523        emain.appendChild(block);
3524        
3525        efirstLine.appendChild(emain);
3526        compositionBlock.appendChild(efirstLine);
3527
3528        
3529        // Audio player (with label)
3530        eblock = document.createElement("div");
3531        eblock.classList.add("d-item-composition-audio-container");
3532        eblock.style.display = "none";
3533        efirstLine.appendChild(eblock);
3534
3535        e = document.createElement("div");
3536        e.classList.add("d-item-composition-audio-label");
3537        e.innerHTML = "Demo audio";
3538        e.addEventListener("click",
3539                           function() {
3540                               let audio = this.parentNode.children[1];
3541
3542                               if (audio.paused)
3543                                   audio.play();
3544                               else
3545                                   audio.pause();
3546                           });
3547        eblock.appendChild(e);
3548
3549        ReiftShop.drawBookCompositionAudio({ code: composedItem.code },
3550                                           eblock);
3551        
3552        compositionBlock.appendChild(eblock);
3553        container.appendChild(compositionBlock);
3554
3555        return totalLength;
3556    },
3557
3558
3559
3560    /**
3561     * Draws the item composition for Mp3
3562     */
3563    drawItemCompositionMp3: function(composedItem,
3564                                     container,
3565                                     sequence) {
3566        let totalLength = 0;
3567
3568        let compositionBlock = document.createElement("div");
3569        compositionBlock.classList.add("d-item-composition-block");
3570
3571        // First line
3572        let efirstLine = document.createElement("div");
3573        efirstLine.classList.add("d-item-composition-main");
3574
3575        // Sequence
3576        let e = document.createElement("div");
3577        e.classList.add("d-item-composition-sequence");
3578        e.innerHTML = sequence + ".";
3579        efirstLine.appendChild(e);
3580
3581        // Show more
3582        e = document.createElement("div");
3583        e.classList.add("d-item-composition-show-more");
3584        e.innerHTML = "";
3585
3586        if (composedItem.relations.refersTo.length > 0) {
3587            e.classList.add("fa-solid");
3588            e.classList.add("fa-caret-down");
3589            e.classList.add("d-item-composition-show-more-active");
3590
3591            e.addEventListener("click",
3592                               function() {
3593                                   ReiftShop.toggleItemCompositionMore(this.parentNode.parentNode);
3594                               });
3595        }
3596        
3597        efirstLine.appendChild(e);
3598
3599        let emain = document.createElement("div");
3600        emain.classList.add("d-item-composition-item");
3601
3602        // Name
3603        e = document.createElement("div");
3604        e.classList.add("d-item-composition-name");
3605        e.innerHTML = composedItem.name;
3606        emain.appendChild(e);
3607
3608        // Contributors
3609        let contributorBlock = document.createElement("div");
3610        contributorBlock.classList.add("d-item-composition-contributor-block");
3611        let arrangerCount = 0;
3612
3613        /* Contributor (only composer) */
3614        let composerBlock = document.createElement("div");
3615        composerBlock.classList.add("d-item-composition-composer-block");
3616
3617        if (composedItem.hasOwnProperty("contributors")) {
3618            let contributorList = composedItem.contributors;
3619            let contributorCount = contributorList.length;
3620
3621            for (let j = 0 ; j < contributorCount ; j++) {
3622                let contributor = contributorList[j];
3623                
3624                if (contributor.role.code != "composer"
3625                    && contributor.role.code != "composer-arr") {
3626                    arrangerCount++;
3627                    continue;
3628                }
3629
3630                let e = document.createElement("div");
3631                e.classList.add("d-item-composition-composer");
3632
3633                if (contributor.role.code == "composer-arr")
3634                    e.classList.add("d-item-composition-composer-arr");
3635                
3636                if (contributor.companyName != "")
3637                    e.innerHTML = contributor.companyName;
3638                else {
3639                    if (contributor.firstName != "")
3640                        e.innerHTML = contributor.firstName + " ";
3641
3642                    if (contributor.lastName != "")
3643                        e.innerHTML += contributor.lastName;
3644                }
3645
3646                composerBlock.appendChild(e);
3647            }
3648        }
3649
3650        contributorBlock.appendChild(composerBlock);
3651        
3652        /* Contributor (only arranger) */
3653        if (arrangerCount > 0) {
3654            let arrangerBlock = document.createElement("div");
3655            arrangerBlock.classList.add("d-item-composition-arranger-block");
3656
3657            let contributorList = composedItem.contributors;
3658            let contributorCount = contributorList.length;
3659
3660            for (let j = 0 ; j < contributorCount ; j++) {
3661                let contributor = contributorList[j];
3662                
3663                if (contributor.role.code != "arranger"
3664                    && contributor.role.code != "adapter")
3665                    continue;
3666
3667                let e = document.createElement("div");
3668                e.classList.add("d-item-composition-arranger");
3669
3670                if (contributor.role.code == "adapter")
3671                    e.classList.add("d-item-composition-adapter");
3672                
3673                if (contributor.companyName != "")
3674                    e.innerHTML = contributor.companyName;
3675                else {
3676                    if (contributor.firstName != "")
3677                        e.innerHTML = contributor.firstName + " ";
3678
3679                    if (contributor.lastName != "")
3680                        e.innerHTML += contributor.lastName;
3681                }
3682
3683                arrangerBlock.appendChild(e);
3684            }
3685
3686            contributorBlock.appendChild(arrangerBlock);
3687        }
3688
3689        emain.appendChild(contributorBlock);
3690
3691
3692        // Length
3693        e = document.createElement("div");
3694        e.classList.add("d-item-composition-length");
3695
3696        if (composedItem.hasOwnProperty("details")) {
3697            let detailList = composedItem.details;
3698            let detailCount = detailList.length;
3699
3700            for (let j = 0 ; j < detailCount ; j++) {
3701                let detail = detailList[j];
3702                let field = detail.field;
3703
3704                if (field.code != "length")
3705                    continue;
3706                
3707                e.innerHTML = detail.value;
3708
3709                totalLength += ReiftShop.convertDuration(detail.value);
3710
3711                break;
3712            }
3713        }
3714
3715        emain.appendChild(e);
3716
3717
3718        // Audio
3719        e = document.createElement("div");
3720        e.classList.add("fa-solid", "fa-music", "d-item-composition-audio-toggle");
3721        e.innerHTML = "";
3722        e.addEventListener("click",
3723                           function() {
3724                               ReiftShop.pauseAllAudio(null)
3725                               ReiftShop.closeAllItemAudio(this.parentNode.parentNode.parentNode);
3726                               ReiftShop.toggleItemAudioPlayer(this.parentNode.parentNode.parentNode, this);
3727                               event.stopPropagation();
3728                           });
3729        emain.appendChild(e);
3730        
3731        efirstLine.appendChild(emain);
3732        compositionBlock.appendChild(efirstLine);
3733
3734        
3735        // Audio player (with label)
3736        eblock = document.createElement("div");
3737        eblock.classList.add("d-item-composition-audio-container");
3738        eblock.style.display = "none";
3739        efirstLine.appendChild(eblock);
3740
3741        e = document.createElement("div");
3742        e.classList.add("d-item-composition-audio-label");
3743        e.innerHTML = "80% audio";
3744        e.addEventListener("click",
3745                           function() {
3746                               let audio = this.parentNode.children[1];
3747
3748                               if (audio.paused)
3749                                   audio.play();
3750                               else
3751                                   audio.pause();
3752                           });
3753        eblock.appendChild(e);
3754
3755        ReiftShop.drawCdCompositionAudio({ code: composedItem.code },
3756                                         eblock);
3757
3758        compositionBlock.appendChild(eblock);
3759
3760
3761        // More
3762        let emoreBlock = document.createElement("div");
3763        emoreBlock.style.display = "none";
3764        emoreBlock.classList.add("d-item-composition-item-more");
3765
3766        // Own relations
3767        if (composedItem.hasOwnProperty("relations")) {
3768            let moreRefersToList = composedItem.relations.refersTo;
3769            let moreRefersToCount = moreRefersToList.length;
3770
3771            let block = document.createElement("div");
3772            block.classList.add("d-item-composition-item-more-reference-block");
3773
3774            let server = ReiftCommon.server;
3775            let profileId = ReiftCommon.profileId;
3776
3777            for (let j = 0 ; j < moreRefersToCount ; j++) {
3778                let moreRefersTo = moreRefersToList[j];
3779                let moreComposedItem = moreRefersTo.item;
3780
3781                let line = document.createElement("a");
3782                line.href = ReiftShop.generateItemUrl(moreComposedItem.code,
3783                                                      (moreComposedItem.type.code == "cd" ? REIFT_SHOP_TYPE_CD : REIFT_SHOP_TYPE_BOOK),
3784                                                      false);
3785                line.classList.add("d-item-composition-item-more-reference-item");
3786                
3787                // Cover
3788                let e = document.createElement("img");
3789                e.classList.add("d-item-composition-item-more-reference-item-cover");
3790                e.src = this.stickerUrlCallback(moreComposedItem);
3791                e.alt = "";
3792                line.appendChild(e);
3793
3794                let moreItemDetail = document.createElement("div");
3795                moreItemDetail.classList.add("d-item-composition-item-more-reference-item-detail");
3796                
3797                // Code
3798                e = document.createElement("div");
3799                e.classList.add("d-item-composition-item-more-reference-item-code");
3800                e.innerHTML = moreComposedItem.code;
3801                moreItemDetail.appendChild(e);
3802                
3803                // Name
3804                e = document.createElement("div");
3805                e.classList.add("d-item-composition-item-more-reference-item-name");
3806                e.innerHTML = moreComposedItem.name;
3807                moreItemDetail.appendChild(e);
3808                
3809                // Subname
3810                e = document.createElement("div");
3811                e.classList.add("d-item-composition-item-more-reference-item-sub-name");
3812                e.innerHTML = moreComposedItem.subName;
3813                moreItemDetail.appendChild(e);
3814
3815                line.appendChild(moreItemDetail);
3816                
3817                // Miniscore 
3818                let fileName = moreComposedItem.code.replace(" ", "");
3819                let pdfUrl = "https://files.reift.ch/files/scores/" + fileName + ".pdf";
3820                
3821                fetch(pdfUrl, {method: "HEAD"}).then(function(response) {
3822                    let e = document.createElement("a");
3823                    
3824                    e.oncontextmenu = function() {
3825                        return false;
3826                    };
3827                    
3828                    e.className = "fa-duotone fa-file-music d-item-composition-item-more-reference-item-score";
3829                    e.target = "_blank";
3830                    e.href = pdfUrl;
3831                    line.appendChild(e);
3832                }).catch(function(error) {
3833                    console.log(error);
3834                    
3835                });
3836
3837                block.appendChild(line);
3838            }
3839
3840            emoreBlock.appendChild(block);
3841        }
3842
3843        compositionBlock.appendChild(emoreBlock);
3844        container.appendChild(compositionBlock);
3845
3846        return totalLength;
3847    },
3848
3849
3850
3851    /**
3852     * Toggles the composition audio for book
3853     */
3854    drawBookCompositionAudio: function(item,
3855                                       container) {
3856        let index = item.code.lastIndexOf(".");
3857        let cd = item.code.substr(4, index - 4);
3858        let track = item.code.substr(index + 1);
3859        
3860        let fileName = item.code.replace(" ", "");
3861        let mp3Url = "https://files.reift.ch/files/mp3/" + fileName + ".mp3";
3862
3863        fetch(mp3Url, {method: "HEAD"}).then(function(response) {
3864            let e = document.createElement("audio");
3865
3866            e.oncontextmenu = function() {
3867                return false;
3868            };
3869            
3870            e.addEventListener("play", 
3871                               function(event) {
3872                                   ReiftShop.pauseAllAudio(event.target);
3873                               }, 
3874                               true);
3875            
3876            e.className = "item-audio";
3877            e.controls = "controls";
3878            e.controlsList = "nodownload";
3879            e.innerHTML = "";
3880            e.src = mp3Url;
3881            e.type = "audio/mpeg";
3882            container.appendChild(e);
3883        }).catch(function(error) {
3884            console.log(error);
3885            container.style.backgroundColor = "red";
3886        });
3887    },
3888
3889
3890
3891    /**
3892     * Toggles the composition audio for CD
3893     */
3894    drawCdCompositionAudio: function(item,
3895                                     container) {
3896        let index = item.code.lastIndexOf(".");
3897        let cd = item.code.substr(4, index - 4);
3898        let track = item.code.substr(index + 1);
3899
3900        let trackNameUrl = "https://files.reift.ch/getCdTrack.php?cd=" + cd + "&track=" + track;
3901        
3902        fetch(trackNameUrl, {
3903            method: "GET"
3904        }).then((response) => {
3905            return response.text();
3906        }).then((data) => {
3907            if (data == "")
3908                return;
3909            
3910            let trackUrl = "https://files.reift.ch/" + data;
3911            
3912            let e = document.createElement("audio");
3913            
3914            e.oncontextmenu = function() {
3915                return false;
3916            };
3917            
3918            e.addEventListener("play", 
3919                               function(event) {
3920                                   let audioList = document.getElementsByTagName("audio");
3921                                   let count = audioList.length;
3922                                   
3923                                   for (let i = 0 ; i < count ; i++)
3924                                       if (audioList[i] != event.target)
3925                                           audioList[i].pause();
3926                               }, 
3927                               true);
3928                
3929            e.className = "d-item-composition-audio";
3930            e.controls = "controls";
3931            e.controlsList = "nodownload";
3932            e.src = trackUrl;
3933            e.type = "audio/mpeg";
3934            container.appendChild(e);
3935
3936            container.style.display = "none";
3937        });/*.catch(function(error) {
3938            
3939        });*/
3940    },
3941
3942
3943
3944    /**
3945     * Pauses all audios except given one
3946     */
3947    closeAllItemAudio: function(container) {
3948        let e = null;
3949        
3950        if (container != null)
3951            e = container.children[1];
3952        
3953        let audioList = document.getElementsByClassName("d-item-composition-audio-container");
3954        let count = audioList.length;
3955
3956        for (let i = 0 ; i < count ; i++)
3957            if (e == null || audioList[i] !== e)
3958                audioList[i].style.display = "none";
3959    },
3960
3961    
3962    
3963    /**
3964     * Toggles the composition audio player
3965     */
3966    toggleItemAudioPlayer: function(container, button) {
3967        let e = container.children[1];
3968
3969        if (e.style.display == "none") {
3970            e.style.display = "";
3971            e.children[1].play();
3972
3973            button.classList.remove("fa-music");
3974            button.classList.add("fa-xmark");
3975        }
3976        else {
3977            e.style.display = "none";
3978            e.children[1].pause();
3979
3980            button.classList.remove("fa-xmark");
3981            button.classList.add("fa-music");
3982        }
3983    },
3984
3985
3986
3987    /**
3988     * Pauses all audios
3989     */
3990    pauseAllAudio: function(currentAudio) {
3991        let audioList = document.getElementsByTagName("audio");
3992        let count = audioList.length;
3993
3994        for (let i = 0 ; i < count ; i++)
3995            if (currentAudio == null || audioList[i] !== currentAudio)
3996                audioList[i].pause();
3997
3998        let buttonList = document.getElementsByClassName("d-item-composition-audio-toggle");
3999
4000        if (buttonList.length > 0)	// Audios on mp3
4001            for (let i = 0 ; i < count ; i++)
4002                if (currentAudio == null || audioList[i] !== currentAudio) {
4003                    buttonList[i].classList.remove("fa-xmark"); 
4004                    buttonList[i].classList.add("fa-music");
4005                }
4006
4007    },
4008
4009    
4010    
4011    /**
4012     * Toggles the more part of composition detail
4013     */
4014    toggleItemCompositionMore: function(container) {
4015        let e = container.children[2];
4016
4017        if (e.style.display == "none")
4018            e.style.display = "";
4019        else
4020            e.style.display = "none";
4021    },
4022
4023
4024    /**
4025     * Converts a duration from m's to seconds
4026     */
4027    convertDuration: function(value) {
4028        let duration = ReiftShop._convertDuration(value,
4029                                                  "'");
4030
4031        if (duration == -1)
4032            duration = ReiftShop._convertDuration(value,
4033                                                  ":");
4034
4035        if (duration == -1)
4036            duration = ReiftShop._convertDuration(value,
4037                                                  "’");
4038
4039
4040        if (duration == -1)
4041            return 0;
4042
4043        return duration;
4044    },
4045        
4046
4047    /**
4048     * Converts a duration from m's to seconds using separator
4049     */
4050    _convertDuration: function(value,
4051                               separator) {
4052        let idx = value.indexOf(separator);
4053        
4054        if (idx == -1)
4055            return -1;
4056
4057        let duration = 0;
4058
4059        try {
4060            duration = parseInt(value.substring(0, idx)) * 60 + parseInt(value.substring(idx + 1));
4061        }
4062        catch(e) {
4063            console.error(e.message);
4064            return 0;
4065        }
4066
4067        return duration;
4068    },
4069        
4070
4071    /**
4072     * Formats a duration from seconds m's using separator
4073     */
4074    formatDuration: function(duration,
4075                             separator) {
4076        return Math.floor(duration / 60).toString() + separator + ("00" + (duration % 60)).slice(-2);
4077    },
4078
4079
4080
4081    /**
4082     * Checks DPM
4083     */
4084    checkDpmInList: function(container,
4085                             itemCode) {
4086   	    let url = ReiftCommon.server + "/reiftShopService";
4087        let formData = new FormData();
4088        formData.append("x", "dpmExists");
4089        formData.append("profileId", ReiftCommon.profileId);
4090        formData.append("code", itemCode);
4091                     
4092        fetch(url, {
4093            method: "POST",
4094            credentials: "include",
4095            body: formData
4096        }).then((response) => {
4097            return response.json();
4098        }).then((data) => {
4099            if (data.hasOwnProperty("errors"))
4100                return;
4101
4102            e = document.createElement("div");
4103
4104            if (data.success.exists == "1") {
4105                e.classList.add("reift-item-list-available");
4106                e.innerHTML = ReiftShop.text.bootiq.item.readyForDownload;
4107                container.appendChild(e);
4108            }
4109
4110        });/*.catch(function(error) {
4111             Debug.add("ERROR Customer Login : " + error);
4112             });*/
4113
4114    },   
4115
4116
4117
4118    /**
4119     * Checks CD
4120     */
4121    checkCdInList: function(container,
4122                            itemCode) {
4123   	    let url = ReiftCommon.server + "/reiftShopService";
4124        let formData = new FormData();
4125        formData.append("x", "cdExists");
4126        formData.append("profileId", ReiftCommon.profileId);
4127        formData.append("code", itemCode);
4128                     
4129        fetch(url, {
4130            method: "POST",
4131            credentials: "include",
4132            body: formData
4133        }).then((response) => {
4134            return response.json();
4135        }).then((data) => {
4136            if (data.hasOwnProperty("errors"))
4137                return;
4138
4139            e = document.createElement("div");
4140
4141            if (data.success.exists == "1") {
4142                e.classList.add("reift-item-list-available");
4143                e.innerHTML = ReiftShop.text.bootiq.item.readyForDownload;
4144                container.appendChild(e);
4145            }
4146
4147        });/*.catch(function(error) {
4148             Debug.add("ERROR Customer Login : " + error);
4149             });*/
4150
4151    },   
4152
4153
4154
4155    /**
4156     * Checks DPM
4157     */
4158    checkDpmInDetail: function(itemCode,
4159                               shopType) {
4160        // TODO: TEMPORARY ?
4161        return;
4162        
4163        let availableContainer = document.getElementById("item-dpm-available");
4164        let notAvailableContainer = document.getElementById("item-dpm-not-available");
4165
4166        if (availableContainer == null
4167            && notAvailableContainer == null)
4168            return;
4169        
4170   	    let url = ReiftCommon.server + "/reiftShopService";
4171        let formData = new FormData();
4172
4173        if (shopType == REIFT_SHOP_TYPE_CD)
4174            formData.append("x", "cdExists");
4175        else if (shopType == REIFT_SHOP_TYPE_CATALOG)
4176            formData.append("x", "catalogExists");
4177        else
4178            formData.append("x", "dpmExists");
4179        
4180        formData.append("profileId", ReiftCommon.profileId);
4181        formData.append("code", itemCode);
4182
4183        fetch(url, {
4184            method: "POST",
4185            credentials: "include",
4186            body: formData
4187        }).then((response) => {
4188            return response.json();
4189        }).then((data) => {
4190            if (data.hasOwnProperty("errors"))
4191                return;
4192
4193            if (data.success.exists == "1") {
4194                if (notAvailableContainer != null)
4195                    notAvailableContainer.style.display = "none";
4196
4197                if (availableContainer != null)
4198                    availableContainer.style.display = "";
4199            }
4200            else {
4201                if (availableContainer != null)
4202                    availableContainer.style.display = "none";
4203                
4204                if (notAvailableContainer != null)
4205                    notAvailableContainer.style.display = "";
4206            }
4207            
4208        });/*.catch(function(error) {
4209             Debug.add("ERROR Customer Login : " + error);
4210             });*/
4211
4212    },
4213
4214
4215    /**
4216     * Toggles the detail comment
4217     */
4218    toggleDetailComment: function(forceClose,
4219                                  reset) {
4220        let block = document.getElementById("item-add-comment-block");
4221
4222        if (block == null)
4223            return;
4224
4225        toggle = block.children[0].children[1];
4226        body = block.children[1];
4227
4228        if (reset) {
4229            body.children[0].value = "";
4230            ReiftShop.commentLength(body.children[0],
4231                                    body.children[1].children[1]);
4232        }
4233
4234        if (forceClose || toggle.getAttribute("data-open") == "1") {
4235            toggle.setAttribute("data-open", "0");
4236            toggle.classList.remove("fa-caret-down");
4237            toggle.classList.add("fa-caret-up");
4238
4239            body.classList.remove("item-add-comment-body-open");
4240            body.classList.add("item-add-comment-body-closed");
4241        }
4242        else {
4243            toggle.setAttribute("data-open", "1");
4244            toggle.classList.remove("fa-caret-up");
4245            toggle.classList.add("fa-caret-down");
4246
4247            body.classList.remove("item-add-comment-body-closed");
4248            body.classList.add("item-add-comment-body-open");
4249        }
4250
4251        
4252    },
4253
4254
4255    /**
4256     * Toggles the detail comment
4257     */
4258    commentLength: function(edit,
4259                            ecount) {
4260        ecount.innerHTML = edit.value.length + " / " + edit.maxLength;
4261    },
4262
4263
4264
4265    /*
4266     * Submits the comment
4267     */
4268    submitComment: function(edit) {
4269        if (edit.value == "")
4270            return;
4271        
4272        let itemId = edit.getAttribute("data-item-id");
4273
4274        ReiftShop.bootiq.addCommentOnItem(itemId,
4275                                          edit.value,
4276                                          function() {
4277                                              ReiftShop.toggleDetailComment(true, true);
4278                                              ReiftCommon.showMessage(ReiftShop.text.message.commentSent,
4279                                                                      false,
4280                                                                      2);
4281                                          },
4282                                          function() {
4283                                              ReiftCommon.showMessage(ReiftShop.text.message.commentNotSent,
4284                                                                      true,
4285                                                                      2);
4286                                          });
4287    },
4288
4289
4290    /** 
4291     * Gets discounts
4292     */
4293    getDiscountList: function() {
4294        let block = document.getElementById("discount-block");
4295
4296        if (block == null)
4297            return;
4298
4299        ReiftShop.bootiq.fetchDiscountList(function(discountList) {
4300                                               ReiftShop.drawDiscountList(block,
4301                                                                          discountList);
4302                                           },
4303                                           function(errorList) {
4304                                               console.error(errorList);
4305                                           });
4306    },
4307
4308
4309    /** 
4310     * Draws given discounts
4311     */
4312    drawDiscountList: function(parent,
4313                               discountList) {
4314        // Clear first
4315        while (parent.children.length > 0)
4316            parent.children[parent.children.length - 1].remove();
4317                            
4318        let count = discountList.length;
4319        let found = false;
4320        
4321        if (count == 0)
4322            return;
4323
4324
4325        for (let i = 0 ; i < count ; i++) {
4326            let description = discountList[i].description;
4327
4328            if (description == "")
4329                continue;
4330
4331            found = true;
4332            let e = document.createElement("div");
4333
4334            e.classList.add("discount");
4335
4336            let icon = document.createElement("div");
4337            icon.classList.add("fa-solid");
4338            icon.classList.add("fa-badge-percent");
4339            icon.classList.add("discount-icon");
4340            e.appendChild(icon);
4341            
4342
4343            let edes = document.createElement("div");
4344            edes.classList.add("discount-description");
4345            edes.innerHTML = description;
4346            e.appendChild(edes);
4347
4348            icon = document.createElement("div");
4349            icon.classList.add("fa-solid");
4350            icon.classList.add("fa-badge-percent");
4351            icon.classList.add("discount-icon");
4352            e.appendChild(icon);
4353            
4354            parent.appendChild(e);
4355        }
4356
4357        if (found)
4358            parent.style.display = "";
4359    },
4360
4361    
4362}

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.