PageSourceSearch

http://siwego.net/kosci/core/quiz3.js

js siwego.net collected 2026-10-04 08:57:32 UTC 143,473 bytes, 3,591 lines download raw bytes

1//* kosci engine author: s1w_ => siwego.net *//* CC BY-NC 4.0 *//
2var d=document;
3
4const ALLOW_DEBG = 1; //zezwalaj na debugowanie
5const DETAILSETS = 1; //czy uzywac zbiorczych detali w trybie przegladania
6const CLEARTYPES = 0; //czy restartowac typy kosci przy nowym tescie
7const BIGLETTERS = 1; //wielkie litery?
8const LAT_ITALIC = 0; //czy łacina w kursywie?
9const SWITCH_MEM = 1; //pamietaj ustawienia switchy
10const BLEDY = 2;
11
12var bones = [], kosci = [], detale = [], all_sets = [], setbag = [], grupa = [], podgr = [], iconz = [], bonetypes = [], DEBUG_MODE = 0; //tryb pozycjonowania
13var /*bonetyp = "",*/ qarea, quiztxt, descbox, inputy, buttony, wyniki, statsy, support, gbook, gback, gclick, slider, slider2, sliding, darr, doff, slided, box_on, losowanie, menuitem, lastitem = [], menubtn, loosetag = "", loosebone = false, quizpicbox, pic, rect, lat = true, eng = true, snd = true;
14var /*newBone = 1,*/ eh = 0, index = 0, detail_main = [], detail_en = [], detail_la = [], detail_wrap = [], detail_side = [], detail_sufx = [], detail_x = [], detail_y = [], detail_nr = [], fu, ee, ok, bt, sl, waitdetail, scoretimer, showtimer = [], blockInterval = [], alerttimer, rarrtimer, licznik, autolos = true, tabbing = false;
15var poprawnych = 0, zlych = 0, zestaw = 0, tmpb, resolved = DEBUG_MODE, hiding = false, lastBone, lastDetail, lastDetidx, lastPic, lastSet, lastMods = [], langSwitch = false, debugSwitch = false, debModSwitch = false, setModSwitch = false, revoked = false, reduced = false, prepared = false;
16
17var langs = ['pl','en'], current_lang = langs[1], c_en, c_la, _ = 0, mobile = false, module, bonetypwidth, wynikwidth;
18var bone_bone, bone_bones, bone_type = [], button_roll, lang_english, lang_latin, prev_detail, next_detail, boneset_choose, bonetype_choose, name_detail, wrong_answer, result_stat, good_answer, bad_answer, modal_box = [], thank_programmer;
19var all_bones, mod_menu = [], turn_on, turn_off, confirm_exit_mode, confirm_run, confirm_run_all, confirm_resolve, resolve_warning, confirm_bone_done, roll_next, confirm_all_done, ask_coffee;
20
21// Opera 8.0+
22var isOpera = (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
23// Firefox 1.0+
24var isFirefox = typeof InstallTrigger !== 'undefined';
25// Safari 3.0+ "[object HTMLElementConstructor]" 
26//var isSafari = /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || (typeof safari !== 'undefined' && safari.pushNotification));
27// Internet Explorer 6-11
28//var isIE = /*@cc_on!@*/false || !!document.documentMode;
29// Edge 20+
30//var isEdge = !isIE && !!window.StyleMedia;
31// Chrome 1 - 71
32var isChrome = !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime);
33// Blink engine detection
34//var isBlink = (isChrome || isOpera) && !!window.CSS;
35
36
37//pic scroll odpala pozno //active? czy inne gowno?
38//zmniejszanie - czcionka tez
39//menu clicks nie dzialaja pozniej, modal alerts
40//controls clicks  //dzwieki?
41//na start pelny quiz podswietlony, pozniej aktywna kosc (//zanaczony aktywny quiz, all na start)
42//jezeli menu zwiniete, ponowne rozsuniecie sidebar rozwija na aktywnej (moze juz po zwinieciu sidebar)
43
44//menu zamiast >>
45//jasniejszy border i ciemniejsze przyciski w chrome //tlo szare  https://siwego.net/ratmed/
46//jasniejszy border przyciskow ff
47
48//module --> zamiast kosci
49
50//wciecie bloczkowe zmienia side, przy odkrywaniu set podczas debug czcionka size nie zaskakuje do pierwszego
51// podczas dragg debug zmiana side przewala coords [przez shortcut]
52// spr off'y (1 pixel odchyłu gdzieniegdzie)
53
54//pc:
55//debug... tryb zestawu... wiesza sie
56//debug... tryb przegladania.. w lewo... full wyl... full wl - gubi poz napisow
57
58//zamienic showup hide na transition
59
60//rozdzielic debug switch od detailswitch dla dzwiekow
61//przy otwieraniu menu dzwiek leci dla kazdej pozycji nalozony
62//dzwieki switchy
63//od czego lag przy zmianie setu? spr wczesniej
64//lvl2 znizac max 2, lvl3 dorownac max lvl2, zmierzyc czy nie wychodzi poza ekran
65
66//responseText na responseXML
67
68//kiedys:
69//dojebac async i await przy ladowaniu, informowac w console.logu
70//konwersja na indexedDB ~!! z JSON https://pl.wikipedia.org/wiki/JSON
71//kazda kosc swoja ikone
72//przystosowac do innych modułów
73// przerobic guestbook date lokalizowac z uniwersalnego zapisu
74//z prawej wylaniajacy sie caly szkieletor do selekcji kosci
75//statystyki wchodzen stat4u?
76//sprawdzic wydajnosc, passive eventlisteners, usecapture
77
78
79
80//https://online.seterra.com/en-an/vgp/3800?c=JDEYT
81//drag pionowe w boatbrowser jest nie do wywalenia
82
83
84/* C:\Chrome.exe --disable-web-security
85
86var newLayer = new ol.layer.Tile({
87source: new ol.source.OSM({
88    url: 'E:/Maperitive/Tiles/vychod/{z}/{x}/{y}.png',
89    crossOrigin: null
90    })
91});
92
93<?xml version="1.0" encoding="UTF-8"?>
94<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
95    <CORSRule>
96        <AllowedOrigin>*</AllowedOrigin>
97        <AllowedMethod>GET</AllowedMethod>
98        <AllowedHeader>*</AllowedHeader>
99        <ExposeHeader>Accept-Ranges</ExposeHeader>
100        <ExposeHeader>Content-Range</ExposeHeader>
101        <ExposeHeader>Content-Encoding</ExposeHeader>
102        <ExposeHeader>Content-Length</ExposeHeader>
103    </CORSRule>
104</CORSConfiguration>
105
106<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
107    <CORSRule>
108        <AllowedOrigin><!-- insert your origin here --></AllowedOrigin>
109        <AllowedMethod>GET</AllowedMethod>
110        <AllowedHeader>Range</AllowedHeader>
111        <MaxAgeSeconds>3000</MaxAgeSeconds>
112        <ExposeHeader>Accept-Ranges</ExposeHeader>
113        <ExposeHeader>Content-Range</ExposeHeader>
114        <ExposeHeader>Content-Encoding</ExposeHeader>
115        <ExposeHeader>Content-Length</ExposeHeader>
116        <AllowedHeader>Authorization</AllowedHeader>
117    </CORSRule>
118</CORSConfiguration>
119 */
120
121
122function setLang(lng, init = false) {
123  console.log("---------------------------");
124  console.log("set lang > "+lng);
125  if (!init) au_play(2); //bt[2].play();
126  var flaga = d.getElementById("flag");
127  module = "kosci";
128  switch (lng) {
129    case 'pl':
130      d.title   = "ANATOMIC Quiz Z Kości";
131      flaga.src = "grf/polish.png";
132      bone_bone =         "kość";
133      bone_bones =        "kości";
134      bone_type[1] =      "długa";
135      bone_type[2] =      "krótka";
136      bone_type[3] =      "płaska";
137      bone_type[4] =      "różnokształtna";
138      bone_type[5] =      "pneumatyczna";
139      button_roll =       "LOSUJ";
140      lang_english =      "angielski";
141      lang_latin =        "łacina";
142      lang_english_m =    "nazwy angielskie";
143      lang_latin_m =      "nazwy łacińskie";      
144      set_sound =         "dźwięk";
145      section_options =   "OPCJE";
146      prev_detail =       "poprzedni detal";
147      next_detail =       "następny detal";
148      boneset_choose =    "wybierz kość";
149      bonetype_choose =   "wskaż rodzaj kości";
150      name_detail =       "nazwij obszar";
151      wrong_answer =      "błędna odpowiedź";      
152      result_stat =       "poprawność";
153      good_answer =       "POPRAWNIE!";
154      bad_answer =        "BŁĄD!";
155      thank_programmer =  "Podziękuj programiście! - wspomóż rozwój projektu";
156      all_bones =         "Pełny quiz";
157      mod_menu[0] =       "tryb przeglądania";  
158      mod_menu[1] =       "debug mode";
159      set_view =          "tryb zestawu";
160      turn_on =           "włącz";
161      turn_off =          "wyłącz";
162      lng_on =            "wł";
163      lng_off =           "wył";      
164      snd_toggle =        "przełącz dźwięki";
165      confirm_exit_mode = "Wyjść z trybu przeglądania?";
166      confirm_run =       "Uruchamiam QUIZ";
167      confirm_run_all =   "Uruchamiam QUIZ dla wszystkich kości";
168      confirm_resolve   = "Odsłonić wszystkie detale?";
169      resolve_warning   = "to działanie przerwie quiz";
170      confirm_bone_done = "Kość w pełni opisana";
171      roll_next =         "losować następną?";
172      confirm_all_done  = "Quiz rozwiązany! - wszystkie kości zostały opisane.";
173      ask_coffee        = "czy postawisz autorowi kawę? ;)  (rozwój programu wymaga znacznego nakładu pracy)";
174      modal_box[0]      = "Program został przystosowany do działania w pełnym ekranie.";
175      modal_box[1]      = "Wciśnij przycisk by przejść teraz...";
176      modal_box[2]      = "WŁĄCZ PEŁNY EKRAN";
177      modal_box[3]      = "Nie pytaj ponownie";
178      pageviews         = "Liczba odsłon";
179      pageviews_today   = "Odsłon dzisiaj";
180      visits            = "Liczba wejść";
181      visits_today      = "Wizyty dzisiaj";
182      people_online     = "Osób online";    
183    break;
184    case 'en':
185    default:
186      d.title   = "ANATOMIC Bone Quiz";
187      flaga.src = "grf/english.png";
188      bone_bone =         "bone";
189      bone_bones =        "bones";
190      bone_type[1] =      "long";
191      bone_type[2] =      "short";
192      bone_type[3] =      "flat";
193      bone_type[4] =      "irregular";
194      bone_type[5] =      "sesamoid";
195      button_roll =       "ROLL";
196      lang_english =      "english";
197      lang_latin =        "latin";
198      lang_english_m =    "english names";
199      lang_latin_m =      "latin names";      
200      set_sound =         "sounds";
201      section_options =   "OPTIONS";
202      prev_detail =       "previous detail";       
203      next_detail =       "next detail";
204      boneset_choose =    "choose bone set";
205      bonetype_choose =   "mark bone type";
206      name_detail =       "describe detail";
207      wrong_answer =      "wrong answer";
208      result_stat =       "correctness"; //score
209      good_answer =       "CORRECT!";
210      bad_answer =        "WRONG!";
211      thank_programmer =  "Thank the programmer!";
212      all_bones =         "All bones";
213      mod_menu[0] =       "overview mode";
214      mod_menu[1] =       "debugging mode";
215      set_view =          "full set view";
216      turn_on =           "turn on";
217      turn_off =          "turn off";      
218      lng_on =            "on";
219      lng_off =           "off";
220      snd_toggle =        "toggle sounds";
221      confirm_exit_mode = "Exit overview mode?";
222      confirm_run       = "Run QUIZ";
223      confirm_run_all   = "Run QUIZ for all bones";
224      confirm_resolve   = "Resolve all details?";
225      resolve_warning   = "this action will break the quiz";
226      confirm_bone_done = "Bone fully described";
227      roll_next =         "roll next?";
228      confirm_all_done  = "Quiz resolved! - all bones are described.";
229      ask_coffee        = "will you buy the coffee for author? ;)  (creating this program required a significant amount of work)";
230      modal_box[0]      = "The program was adapted to run in full screen.";
231      modal_box[1]      = "Press the button to go now...";
232      modal_box[2]      = "GO FULL SCREEN";
233      modal_box[3]      = "Don't ask again";      
234      pageviews         = "Page views";
235      pageviews_today   = "Views today";
236      visits            = "Visits";
237      visits_today      = "Visits today";
238      people_online     = "Online";
239    break;
240  }
241  langs.forEach(lng_ => {         
242    if (lng_ == lng) {
243      d.getElementById("poprawnie").addClass(lng_);
244      d.getElementById("blad").addClass(lng_);       
245    }
246    else {
247      d.getElementById("poprawnie").removeClass(lng_);
248      d.getElementById("blad").removeClass(lng_);  
249    }
250  });  
251
252  d.getElementById("wyniktxt").innerHTML = result_stat+"&nbsp;&nbsp;";
253  d.getElementById("stacktxt").innerHTML = bone_bones+"&nbsp;&nbsp;";
254  d.getElementById("dotuj").src = "grf/btn_donate_"+lng+".png";  
255  d.getElementById("poprawnie").innerHTML = good_answer;
256  d.getElementById("blad").innerHTML = bad_answer;  
257  d.getElementById("prev").title = prev_detail;  
258  d.getElementById("next").title = next_detail;  
259  buttony.title = bonetype_choose;  
260  
261  if (mobile) {
262    applyLang(lng, init);
263    return;
264  }
265  /******* not mobile ********/
266  d.getElementById("inputtext").innerHTML = name_detail+"&nbsp;";
267  d.getElementById("losuj").value = button_roll;
268  buttony.getElementsByTagName("input")[0].value = bone_type[1];
269  buttony.getElementsByTagName("input")[1].value = bone_type[2];
270  buttony.getElementsByTagName("input")[2].value = bone_type[3];
271  buttony.getElementsByTagName("input")[3].value = bone_type[4];
272  buttony.getElementsByTagName("input")[4].value = bone_type[5];
273  var langswitch1 = switche.getElementsByTagName('label')[0]; //getElementById("en").
274  var langswitch2 = switche.getElementsByTagName('label')[1]; //getElementById("en").
275  if (lng == "en") {
276    langswitch1.style.display = 'none';
277    langswitch2.innerHTML = langswitch2.innerHTML.replace(/^\S+/,"<br>"+lang_latin);
278    //d.getElementById("angielski").checked = false;
279    if (!init) uncheckLang("en");    
280  }
281  else {
282    langswitch1.innerHTML = langswitch1.innerHTML.replace(/^\S+/,lang_english);
283    langswitch1.style.display = '';
284    langswitch2.innerHTML = langswitch2.innerHTML.replace(/^\S+/,lang_latin);
285    //d.getElementById("angielski").checked = true;
286    if (!init) checkLang("en");
287  }
288  //d.getElementById("lacina").checked = true;
289  if (!init) checkLang("la");
290  if (!init) applyLangs(0);
291
292  d.getElementById("menu").title = boneset_choose;  
293  d.getElementById("speaker").title = snd_toggle;
294    
295  //console.log(switche.getElementById("la").innerHTML);
296  var mod = d.getElementsByClassName("addon");
297  mod[0].innerHTML = mod[0].innerHTML.replace(/^[^:]+/,DEBUG_MODE ? set_view : mod_menu[0]);  
298  mod[1].innerHTML = mod[1].innerHTML.replace(/^[^:]+/,mod_menu[1]);  
299  current_lang = lng;
300  
301  var stats = d.getElementsByClassName("counters");
302  if (stats.length) {
303    stats[0].getElementsByClassName("pageviews")[0].innerHTML = pageviews+": ";
304    stats[0].getElementsByClassName("pageviews_today")[0].innerHTML = pageviews_today+": ";
305    stats[0].getElementsByClassName("visits")[0].innerHTML = visits+": ";
306    stats[0].getElementsByClassName("visits_today")[0].innerHTML = visits_today+": ";
307    stats[0].getElementsByClassName("people")[0].innerHTML = people_online+": ";
308  }
309  
310  if (!init) {
311    setCookie('lang',lng,730);
312    switchMode();
313    //newBone = 1;
314    showBone(0, langSwitch = true);
315    langSwitch = false;
316    createMenu(lng);
317    lastSet = currentBone("menu");
318    initMenu(3);
319  }
320  initGuestBox(lng);
321  
322  if (!mobile) d.getElementById("inpucik").focus();     
323}
324
325
326
327
328HTMLElement.prototype.checkBone = function() {
329  if (buttony.hasClass("hiding")) return;
330  console.log("f checkbone");
331  
332  if (this.hasClass('valid')) {
333    score(1, mobile ? 100 : 75, this);
334    buttonsHide(this.id, eh == 0 ? true : false); //.value
335    quiztxt.innerHTML += "&nbsp;&nbsp;&nbsp;&nbsp;<span id='bonetyp' class='subtype' style='color:#"+(eh == 0 ? "8a8" : "a88")+"'>"+bone_bone+" "+(mobile ? this.innerHTML : this.value);
336    eh = 0;
337  }
338  else {
339    score(0, mobile ? 73 : 69, this);
340    if (eh == -1) {
341      var vbtn = buttony.getElementsByClassName("valid")[0];
342      buttonsHide(vbtn.id, false); //.value
343      quiztxt.innerHTML += "&nbsp;&nbsp;&nbsp;&nbsp;<span id='bonetyp' class='subtype' style='color:#a88'>"+bone_bone+" "+(mobile ? vbtn.innerHTML : vbtn.value);
344      eh = 0;
345    }
346    else if (mobile) {
347        /* showup(buttony, -0.2, 10, 0, true); */
348        //buttony.style.opacity = "0.9";
349    }
350  }
351  /* if (mobile)  */fitTxt();
351 //resizing();
352  /* else relocate(1); */
353  if (!mobile) relocate(1);
354}
355
356function buttonsHide(answer, hit) {
357  //console.log("f buttonshide");
358  
359  if (!mobile) buttony.style.display = "none";
360  else buttony.addClass("hiding");
361  
362  showup(buttony, -0.0, 35);
363
364  if (mobile) {
365    inputy.style.display = "flex"; //"list-item"; 
366    makeChoices();
367    col2.addClass("dimmed");
368    showup(inputy, 0.9, 30, 10);
369  }
370  else {
371    inputy.style.display = "inline-block"; 
372  }
373  
374  if (!bonetypes[currentBone("base")]) {  //currentBone("type")
375    //console.log(">>"+currentBone("base")+" => ["+[ answer, hit ]+"]");
376     bonetypes[currentBone("base")] = [ answer, hit ];  
377  }
378  
379  if (!mobile)
380    d.getElementById("inpucik").focus();
381  else {
382    setTimeout(function() {  
383      buttony.removeClass("hiding");
384    }, 1500);     
385  }
386}
387
388function inputsHide() {
389  console.log("f inputshide");
390  // if (mobile)
391    inputy.style.display = "none"; 
392    if (mobile) { 
393      inputy.style.opacity = "0.0";
394      return;
395    }
396   else {
397    // inputy.style.visibility = "hidden"; 
398    d.getElementById("inpucik").disabled = false;
399    d.getElementById("inputtext").style.color = "#555";
400    d.getElementById("inputtext").innerHTML = name_detail+"&nbsp;";
401    d.getElementById("inpucik").value = '';
402  }
403}
404
405/*async*/ function inputsOff(del, delay /* = true/*, time = 0*/) {
406  //console.log("f inputsOff "+hit+"   autolos "+autolos);
407  //await sleep(time * 1000);
408  var currPic = lastPic;
409  
410  if (del)
411  {
412    if (currentBone("details") == 1)  //TRAFIONY - OSTATNI DETAL
413    {
414      reduce();
415      if (kosci.length == 0) {
416        
417        setTimeout(function() { confirmEnd(); }, delay);
418      }
419      else
420        if (autolos) { console.log("::0");
421          //autolos = true; //czy to z licznika pieprzy
422          //autolos = true;
423          //disrupted = false;
424          //prepareNext(false);
425          setTimeout(function() { losowanie.start(true, currPic); }, delay);
426          //losowanie.start(true);
427        }  //true - krotkie
428        else 
429          setTimeout(function() { endBone(); }, delay);
430
431      
432      return;
433    }
434    else  //TRAFIONY - WIECEJ DETALI
435    {
436      console.log("::2");
437      //disrupted = false;
438      prepareNext(true); //true - remove
439      if (autolos) setTimeout(function() { losowanie.start(true, currPic); }, delay); //losowanie.start(true); //true - krotkie
440    }
441  }
442  else {  //PUDŁO
443    console.log("::3");
444    //if (!reduced) { disrupted = false; prepareNext(false); }  //na chuj mi bylo reduced
445    //disrupted = false;
446    
447    //new 2020.03 gdzie to jest potrzebne? debug? resolved?
448////////////////////////    prepareNext(false); //false - nie usuwaj (dlaczego? na przyszlosc opisywac, teraz to musze usunac a nie wiem do czego to bylo potrzebne w tym miejscu) //przez to preparuje sie przed wylosowaniem (uniemozliwia przerwanie)
449    if (autolos) setTimeout(function() { losowanie.start(false, currPic); }, delay); //losowanie.start(false); //false - dlugie
450  }
451  
452
453  //if (autolos) { console.log("::2   hit "+hit);
454  //  if (!reduced) { autolos = true; disrupted = false; prepareNext(hit); }
455  //  losowanie.start(hit); }
456    //else { console.log("::3");  //TO BEDZIE POTRZEBNE? potrzebne gdy detali > 1, szkodzi w niektorych przypadkach
457    //prepareNext(hit); }
458}
459
460function endBone() {
461  if (au_play(4) && confirm(confirm_bone_done+"\n > "+roll_next)) {
462    /*console.log("::1");*/ losuj(/*false*/);    }
463  else { revokeDetail(false); revoked = true; }
464}
465
466/*
467function restart(msg = null) {
468  if (!!bt[17].play().catch(function() { }) && confirm(msg ? msg : "Powrócić to quizu?"))
469   { prestart(); window.location.reload(); }
470}
471*/
472function confirmEnd() {
473  var set_name;
474  au_play(5);
475  if (lastSet)
476    set_name = lastSet.getElementsByTagName('div')[0].textContent.replace('⊳', '').trim();
477  if (confirm(confirm_all_done+"\n\n"+(lastSet ? set_name+": " : "")+result_stat+": "+d.getElementById("procenty").innerHTML+"\n\n > "+ask_coffee))
478   { prestart(); d.forms['dotacja'].submit(); inputsHide(); return false; }
479  else { /*switchMode(1);*/ resolveBones(); reduced = false; /*prestart(); window.location.reload();*/ return true; }
480}
481    
482function prestart() {
483  shutIt(); wyniki.style.display = 'none'; pic.preload();
484}
485
486function reset() {
487  //console.log(">>czyszcze odpowiedzi");
488  if (CLEARTYPES) bonetypes = [];  //new 06.11 nie czysc typow kosci przy nowym tescie
489  for (var key in bones)
490    for (var num in bones[key]) {
491      bones[key][num][0] = false;
492      bones[key][num][1] = false;
493    }
494/*  //ten myk nie przejdzie ;>
495    bones.forEach(bone => {
496    bone.forEach(detail => {
497      detail[0] = false;
498      detail[1] = false;
499    });
500  });
501*/ 
502}
503
504/*
505function sleep(ms) {
506  return new Promise(resolve => setTimeout(resolve, ms));
507}
508*/
509
510function checkBoneDetal(detal) { //SPRAWDZ POPRAWNOSC DETALU NA KOSCI
511  //console.log("f checkbonedetal");
512  if (!detal) return;
513  
514  var description, hit = false;
515  var BreakException = {};
516
517  try {
518  [detail_main[0], detail_en[0], detail_la[0]].forEach(lang => { //dla pierwszego detalu (gdy nie odkryte jest tylko jeden)
519    detailloop: 
520    if (lang) {
521      for (var i = 0; i < lang.length; i++) {  //dla wszystkich wariantów
522      /**/console.log("checking ::: "+lang[i][0]);
523        if (equalsIgnoreCase(detal, lang[i][0])) { hit = true; throw BreakException; /*break detailloop;*/ }
524        else if (mobile) { throw BreakException; }
525        for (var k = 0; lang[0][2] && k < lang[0][2].length; k++) { //dla koncowych suffiksow (zapisane w tablicy pierwszego wariantu)
526      /**/console.log("checking ::: "+lang[i][0]+" "+lang[0][2][k]);
527          if (equalsIgnoreCase(detal, lang[i][0]+" "+lang[0][2][k])) { hit = true; throw BreakException; /*break detailloop;*/ }
528        }      
529        for (var j = 0; lang[i][1] && j < lang[i][1].length; j++) { //dla opcjonalnych suffiksow
530      /**/console.log("checking ::: "+lang[i][0]+" "+lang[i][1][j]);
531          if (equalsIgnoreCase(detal, lang[i][0]+" "+lang[i][1][j])) { hit = true; throw BreakException; /*break detailloop;*/ }
532          for (var k = 0; lang[0][2] && k < lang[0][2].length; k++) { //dla koncowych suffiksow (zapisane w tablicy pierwszego wariantu)
533        /**/console.log("checking ::: "+lang[i][0]+" "+lang[i][1][j]+" "+lang[0][2][k]);
534            if (equalsIgnoreCase(detal, lang[i][0]+" "+lang[i][1][j]+" "+lang[0][2][k])) { hit = true; throw BreakException; /*break detailloop;*/ }
535          }
536        }
537      }
538    }
539  });
540  } catch (e) { if (e !== BreakException) throw e; } //breaking
541  
542  /*
543  if (equalsIgnoreCase(detal, detail_main[0]) ||                                   //DETAL OK --usun 
544     (btail_pl && (equalsIgnoreCase(detal, detail_main[0]+" "+btail_pl) || equalsIgnoreCase(detal, detail_main+" kości "+btail_pl))) ||   //jezeli dodatkowe
545     (detail_en && equalsIgnoreCase(detal, detail_en)) ||
546     (detail_la && equalsIgnoreCase(detal, detail_la))) {  */
547     
548  if (hit) {
549
550      score(1, mobile ? 100 : 79);
551      if (currentBone("detailbad"))
552        loosetag = "<span style='color:#a88'>";
553      
554      updDetail(); //<-- param: init, temporary
555      if (!mobile) inputsHide();
556      currentBone("detail", true);
557      eh = 0;
558      showup(descbox);  //---------------- czy przy autolos ostatni check spelnia swoja f?
559
560      inputsOff(true, 800);
561      //setTimeout(function() { inputsOff(true) }, 800);   //hit i usun
562      //inputsOff(true); //<-- tam prepareNext(hit) usuwa ze zbioru;
563      return;
564     
565  }
566  else {
567  
568    score(0, mobile ? 84 : 69, null);
569    currentBone("detailbad", true);
570
571    if (eh == -1) { //force wrong answer                   //DETAL ZLY i WYMUSZENIE --usun ze zbioru
572      currentBone("detail", true);
573      loosetag = "<span style='color:#a88'>";
574      updDetail();
575      
576      if (!mobile) wrongInput();
577      
578      //inputsHide();
579
580      loosetag = "<span style='color:#a88'>";
581      showup(descbox);
582
583      inputsOff(true, 700);
584      //setTimeout(function() { inputsOff(true) }, 700);  
585      //inputsOff(true);
586    }
587    else {  //zwykly blad, nie usuwaj ze zbioru            //DETAL ZLY -błąd zwykły --jeszcze nie usuwaj
588      loosetag = "<span style='color:#aaa'>";
589      updDetail(true); //<-- tymczasowy hint
590
591      if (currentBone("details") == 1)
592        if (!autolos || kosci.length == 1) {                //OSTATNIA KOŚĆ -raz błąd i w drugim usuń
593          console.log("ostatni detal");
594          autolos = false;
595          //currentBone("detail", true);
596          //currentBone("detailbad", true);
597          showup(descbox, -0.0, 130);
598          return;
599        }
600      
601      if (!mobile) wrongInput();   
602      //inputsHide();
603      //showup(descbox, 120);
604      hint(descbox);
605      //inputsHide();
606      inputsOff(false);
607    }
608    return;
609  }
610}
611
612function wrongInput() {
613  d.getElementById("inpucik").disabled = true;
614  d.getElementById("inputtext").style.color = "#a88";
615  d.getElementById("inputtext").innerHTML = wrong_answer;
616}
617
618function updDetail(temporary = false, txt = "") {  //init juz niepotrzebne?
619  //console.log("f upddetail:"+txt);
620  //var BreakException = {};
621  //throw BreakException
622  var set = currentBone("set") ? 1 : 0, idx; // = set && !once? 0 : lastDetidx;
623  if (currentBone("detailbad")) loosetag = "<span style='color:#a88'>";  //new 10.10
624  var all_details = descbox.getElementsByClassName("detal");
625  //for (var i = once && set ? lastDetidx : 0; i < all_details.length || once; i++, idx = set ? i : lastDetidx) {  //jedna linia mozliwa tylko dla prawych detali
626  var i = 0;
627  do {
628    idx = set ? i : lastDetidx;
629    //var i = currentBone("set") ? idx : lastDetidx; //new 29.11
630    if (DEBUG_MODE) { /*console.log("setting drag "+all_details[i].id+"  idx "+idx);*/ draggable(all_details[i], idx); all_details[i].style.cursor = "move"; }
631    
632    //console.log("updating ---- "+idx+"  "+detail_nr[idx]+"="+all_details[i].id);
633    if (detail_side[set][idx] == "l") {
634      if (!(all_details[i].classList.contains("left"))) all_details[i].classList.add("left");
635    }
636    else if (all_details[i].classList.contains("left")) all_details[i].classList.remove("left");
637    all_details[i].innerHTML = (set ? "" : loosetag)+(BIGLETTERS ? detail_main[idx][0][0].toUpperCase() : detail_main[idx][0][0].charAt(0).toUpperCase()+detail_main[idx][0][0].slice(1))+(!set && detail_main[idx][0][1] ? " "+(BIGLETTERS ? detail_main[idx][0][1][0].toUpperCase() : detail_main[idx][0][1][0]) : "")+(!set && detail_sufx[idx] && detail_main[idx][0][2] ? " "+(BIGLETTERS ? detail_main[idx][0][2][0].toUpperCase() : detail_main[idx][0][2][0]) : "")+(detail_wrap[idx] != "0" || detail_side[set][idx] == "l" || set ? "<br>" : "&nbsp;");
638    if (!temporary) {
639      if (set && (detail_main[idx][0][1] || detail_sufx[idx] && detail_main[idx][0][2])) all_details[i].title = " "+detail_main[idx][0][0]+(detail_main[idx][0][1] ? " "+detail_main[idx][0][1][0] : "")+(detail_sufx[idx] && detail_main[idx][0][2] ? " "+detail_main[idx][0][2][0] : "")+" ";
640      if (detail_en.length && detail_en[idx][0][0]) { if (eng) all_details[i].innerHTML += '&nbsp;<span class="subdescr'+(set ? ' res' : '')+'">'+detail_en[idx][0][0]+(detail_en[idx][0][1] ? " "+detail_en[idx][0][1][0] : "")+(detail_sufx[idx] && detail_en[idx][0][2] ? " "+detail_en[idx][0][2][0] : "")+(!set && lat ? "" : "&nbsp;")+(set ? "<br>" : ""); }
641      if (detail_la.length && detail_la[idx][0][0]) { if (lat) { var msg = "";
641 if (set) { detail_la[idx].forEach(latin => { if (msg) msg += " ~ "; msg += latin[0]; }) } else msg = detail_la[idx][0][0];
642        all_details[i].innerHTML += '&nbsp;<span class="subdescr'+(eng ? ' lat' : '')+(set ? ' res' : '')+'">'+(LAT_ITALIC ? '<i>' : '')+(detail_en.length ? '<idx>' : '')+(set || !eng || !detail_en.length ? '' : '(')+msg+(set || !eng || !detail_en.length ? '' : ')')+'&nbsp;';  //detail_la[idx][0][0]+(detail_la[idx][0][1].length ? " "+detail_la[idx][0][1][0] : "")
643      } }
644    }                                 //  ^  ^  ^  ^  detal, wariant odp, odp, suffixy
645    //if (once) break;
646    if (++i >= all_details.length) break;
647  } while (set);
648  relocate(1);
649  if (!resolved) wyniki.style.display = ""; 
650  descbox.style.display = "block"; 
651  //setTimeout(function() { 
652  //  if (init == 1) { descbox.style.display = "block";  }
653  //}, 500);   
654  debugSwitch = false;
655}
656
657function relocate(force = 0) {
658  if (mobile) { relocate_m(); return; }
659  //console.log("f relocate");
660  if (!resolved && window.innerWidth < 570) {
661    if (!switche.hasClass("hide")) switche.addClass("hide");
662  }
663  else if (switche.hasClass("hide"))
664    switche.removeClass("hide");
665    
666  if (force || descbox.style.display == "block") {
667    var all_details = descbox.getElementsByClassName("detal");
668    var set = currentBone("set") ? 1 : 0;
669    var idx;// = set && !once? 0 : lastDetidx;
670    var lefts = [], l = 0, detail_rect;
671    //for (var det = once && set ? lastDetidx : 0; det < all_details.length || once; det++, idx = set ? det : lastDetidx) {
672    var det = 0;
673    rect = /* (coords ? */ pic.getBoundingClientRect() /* : quiztxt.getBoundingClientRect()) */; //moved 06.05.2021
674    do {
675      idx = set ? det : lastDetidx;    
676      var coords = (typeof detail_x[set][idx] == 'number' && typeof detail_y[set][idx] == 'number');  //to juz raczej zbedne
677      
678      var coords_offset = (rect.x+(coords ? detail_x[set][idx] : 350 + vw(5)))
679      all_details[det].style.left = ""+coords_offset+"px";
680      all_details[det].style.top = ""+(rect.y+(coords ? detail_y[set][idx] : 3))+"px";
681      
682      if (coords && detail_side[set][idx] == "l") {
683        lefts[l] = []
684        lefts[l][0] = all_details[det];
685        lefts[l++][1] = coords_offset;
686      }
687      //if (once) break;
688      if (++det >= all_details.length) break;
689    } while (set);
690    if (descbox.style.display != "block") {
691      descbox.style.opacity = "0.0"; descbox.style.display = "block";     
692    }
693    for (var det = 0; det < lefts.length; det++) {
694      detail_rect = lefts[det][0].getBoundingClientRect();
695      lefts[det][0].style.left = ""+(lefts[det][1]-detail_rect.width)+"px";
696    }
697    if (resolved) {
698      descbox.style.opacity = "0.95";
699    }
700  }
701  if (DEBUG_MODE) debugLocation(rect);
702
703  /* if (force || wyniki.style.display == "") { */
704    rect = qarea.getBoundingClientRect(); 
705    wyniki.style.right = ""+(window.innerWidth/2-rect.width/2)+"px";
706    wyniki.style.top = ""+(rect.top+(isFirefox ? 28 : 26))+"px";
707  /* } */
708  
709  try {
710    var gbody = gbook.document.getElementsByTagName('body')[0];  
711    if (!scrollbarVisible(gbody)) {
712      if (window.innerWidth > 650)
713        gbody.style.marginRight = "18px";
714      else
715        gbody.style.marginRight = "0";
716    }
717  } catch(e) { /* console.error(e); */ }
718  keepSupportPos();
719  fitTxt();
720}
721
722
723fitTxt = function() {
724  /* console.log("f fitTxt"); */
725  /* check quiztxt length */
726  var typ = d.getElementById("bonetyp");
727  var stackset = d.getElementById("stackset");
728  var rect = quiztxt.getBoundingClientRect();
729
730  if (!stackset.hasClass("hide"))
731    wynikwidth = wynik.getBoundingClientRect().width;
732    
733  if (!mobile) {
734    if (window.innerWidth <= rect.width + 220) 
735      stackset.addClass("hide");
736    else
737      stackset.removeClass("hide");
738  }
739  else {
740    if (window.innerWidth > wynikwidth + 100 && stackset.hasClass("hide"))
741      stackset.removeClass("hide");
742    else if (window.innerWidth < wynikwidth + 100 && !stackset.hasClass("hide"))
743      stackset.addClass("hide");
744  }
745  
746  if (!typ) return;
747  var w = wynikwidth + 40;
748  
749  if (!typ.hasClass("hide"))
750    bonetypwidth = typ.getBoundingClientRect().width;
751  
752  if (window.innerWidth <= rect.width + (mobile ? 10 : w) && !typ.hasClass("hide")) 
753    typ.addClass("hide");
754  if (window.innerWidth >= rect.width + bonetypwidth + (mobile ? 10 : w) && typ.hasClass("hide")) 
755    typ.removeClass("hide");
756}
757
758
759function vw(value) {
760  var w = window,
761    d = document,
762    e = d.documentElement,
763    g = d.getElementsByTagName('body')[0],
764    x = w.innerWidth || e.clientWidth || g.clientWidth,
765    y = w.innerHeight|| e.clientHeight|| g.clientHeight;
766
767  var result = (x*value)/100;
768  return result;
769}
770
771
772function showBone(newBone = 1, switchOnly = (tabbing || langSwitch || debugSwitch || debModSwitch)) {
773  console.log("f showbone "+currentBone("base")+"   lastBone "+lastBone); //  (newbone "+newBone+"  switchonly "+switchOnly+")");
774  var xml = readTextFile(currentBone("xml"));
775  if (!xml) return;
776  parser = new DOMParser();
777  xmlElements = parser.parseFromString(xml,"text/xml");
778
779  var name = [], main, en = [], la;
780  name = xmlElements.getElementsByTagName("nazwa");
781  try {
782    main = name[0].getElementsByTagName(current_lang)[0].innerHTML.toLowerCase().trim().replace(/\s\s+/g, ' ').split("<s>"); //.textContent;
783    if (current_lang != "en")
784      en = name[0].getElementsByTagName("en")[0].innerHTML.toLowerCase().trim().replace(/\s\s+/g, ' ').split("<s>"); //.textContent;
785    la = name[0].getElementsByTagName("la")[0].innerHTML.toLowerCase().trim().replace(/\s\s+/g, ' ').split("<s>"); //.textContent;
786  } catch(e) { console.error(e); }
787  quiztxt.innerHTML = main[0].toUpperCase()+"&nbsp;&nbsp;";   //.childNodes[1]
788  if (en.length) { if (eng) { quiztxt.innerHTML += "&nbsp;<span class='subtype'>"+en[0]; if (!SWITCH_MEM || c_en) checkLang("en", false); } }
789  else uncheckLang("en", false);
790  if (la.length) { if (lat) { quiztxt.innerHTML += "&nbsp;&nbsp;<span class='subtype'><i>"+(eng && en.length ? "(" : "")+la[0]+(eng && en.length ? ")" : " "); if (!SWITCH_MEM || c_la) checkLang("la", false); } }
791  else uncheckLang("la", false);
792  //if (currentBone("type")) {
793  //  bonetyp = xmlElements.getElementsByTagName("typ")[0].innerHTML.toLowerCase().trim().replace(/\s\s+/g, ' ');
794  //  if (currentBone("typebad")) loosebone = true;
795  //}
796
797  var typ = xmlElements.getElementsByTagName("typ");
798  try {
799    var validBone = typ[0].getElementsByTagName(current_lang)[0].innerHTML.toLowerCase().trim().replace(/\s\s+/g, ' '); //10.10
800  } catch(e) { console.error(e); }
801  if (resolved /* == 1 */ && validBone && (!DEBUG_MODE || DEBUG_MODE && currentBone("set"))/* debModSwitch */ && !currentBone("type")) bonetypes[currentBone("base")] = [ bone_type.indexOf(validBone), null ]; //new 10.10 przegladaj tez typy kosci  
802  if (currentBone("type")) quiztxt.innerHTML += "<span id='bonetyp' class='subtype' style='color:#"+(currentBone("typehit") ? "8a8" : (currentBone("typehit") === null ? "555" : "a88"))+"'>&nbsp;&nbsp;&nbsp;&nbsp;"+bone_bone+" "+currentBone("type");
803  /* if (mobile)  */fitTxt();
804  
805  if (!newBone && !switchOnly) return;
806  
807  //if (newBone || switchOnly) {
808    if (newBone && !debModSwitch) {
809      if (resolved)
810        console.log("showing details > "+currentBone("base"));
811      else {
812        console.log("new bone > "+currentBone("name"));
813        console.log(detale[kosci[0]]);
814      }
815      //if (currentBone("set") ? 1 : 0)
816      //  lastBone = kosci[index]; //NEW 2020 ---- BO NIE ZMIENIALO pRZY SECIE currentBone("set") ? 1 : 0; //jednak nie pomoglo
817    }
818
819    //if (DEBUG_MODE && !switchOnly) debugbox.style.display = "none";
820    //console.log(kosci);
821
822    //////////////////////////////////////////////////////////////bone type///////
823    /*bonetyp = "", loosebone = false;*/ loosetag = "";
824    //var validBone = xmlElements.getElementsByTagName("typ")[0].innerHTML.toLowerCase().trim().replace(/\s\s+/g, ' ');
825    if (resolved || debModSwitch && DEBUG_MODE) {
826      buttony.style.display = "none";
827      //inputy.style.visibility = "hidden";
828      if (!mobile) inputsHide();
829    } else if (validBone && !currentBone("type")) {  //rodzaj nie byl zgadywany dla tej kosci
830
831      // if (mobile)
832        inputy.style.display = "none"; 
833        if (mobile) inputy.style.opacity = "0.0";
834      // else
835        // inputy.style.visibility = "hidden";
836      buttony.style.opacity = (!mobile ? "1.0" : "0.0");
837      buttony.style.display = (!mobile ? "" : "flex");
838      //showup(buttony);
839      d.activeElement.blur();
840      //d.getElementsByTagName("body")[0].focus();
841      //(d.getElementById("prev")).style.disabled = true;
842      //(d.getElementById("next")).style.disabled = true;
843      for (var btn, i = 1; btn = d.getElementById(""+i), i<6; i++) {
844        if (equalsIgnoreCase(mobile ? btn.textContent : btn.value, validBone)) {
845          btn.addClass("valid"); 
846          break;
847        }
848      }
849    }
850    else {
851      buttony.style.display = "none";
852      if (!currentBone()) {  //detal nie byl jeszcze odpowiedziany
853      // if (mobile)
854        /////// TO SIE KIEDY DZIEJE?? PRZECIEZ JEST SHOWUP(INPUTY,..)
855      if (mobile) {
856       /*  inputy.style.display = "flex"; //"list-item"; 
857        showup(inputy, 0.9);
858        posChoices(); */
859      }
860      else
861        inputy.style.display = "inline-block"; 
862      // else
863        // inputy.style.visibility = "";
864      if (!mobile) d.getElementById("inpucik").focus();
865      }
866      else {
867        // if (mobile)
868          inputy.style.display = "none"; 
869          if (mobile) inputy.style.opacity = "0.0";
870        // else
871          // inputy.style.visibility = "hidden";
872      }
873    }     
874    //////////////////////////////////////////////////////////////////////////////
875    var dscbox = [], detnum = [], side;
876    var n = 0, detnr = currentBone("nr"); //dla wszystkich detali w descboxie
877    var bone = currentBone("base"), detail, fontsize;
878    var set = currentBone("set") ? 1 : 0;
879    descbox.innerHTML = "";
880    
881    if (!langSwitch && !DEBUG_MODE && !debugSwitch && !debModSwitch)
882      pic.style.opacity = "0.05";
883    
884    if (newBone) {
885      detail_wrap = []; detail_side = []; detail_sufx = []; detail_x = []; detail_y = []; detail_nr = [];
886    }
887    
888    /*  
889    else
890    {
891      var tmpdetail = Object.keys(bones[bone]);
892      for (var i = 0; i < tmpdetail.length; i++) {
893        dscbox[i] = tmpdetail[i]
894      }
895    }
896    */          //czy detale tagi trzeba szuflowac? chyba detale[index] poszuflowane wystarczy
897    //detnum = DEBUG_MODE ? Object.keys(bones[bone]).sort(function(a, b){return a-b}) : shuffle(Object.keys(bones[bone]));
898    detnum = Object.keys(bones[bone]).sort(function(a, b){return a-b});
899
900    
901    if (!set) {  //NEW 06.05.2021
902      //detnr = currentBone("nr");
903      dscbox[n = lastDetidx = !DEBUG_MODE || resolved == 2 ? 0 : detnum.indexOf(detnr)] = xmlElements.getElementsByTagName("detal"); //dla sekcji detalu z xml'a (jezyki, koordynaty, wariacje)
904      //console.log("lastDetidx <-- "+lastDetidx);
905      //if (lastDetidx == null) lastDetidx = n;
906    }
907    else if (newBone) { lastDetidx = DEBUG_MODE ? 0 : detnum.indexOf(detnr); /*console.log("lastDetidx <-- "+lastDetidx);*/ } 
908    
909    if (!detail_side[0]) detail_side[0] = [];
910    if (!detail_side[1]) detail_side[1] = [];
911    if (!detail_x[set]) detail_x[set] = [];
912    if (!detail_y[set]) detail_y[set] = [];
913          
914    detail_main = [], detail_en = [], detail_la = []; //, detail_nr = []; --bledy przy indexOf
915    do {
916      if (set) {  //detale zaczac od 0 przy grupowym odslonieciu
917        if (!detnum[n]) break;
918        xml = readTextFile(currentBone("xml", detnum[n]));
919        // console.log("reading xml "+currentBone("xml", detnum[n]));
920        xmlElements = parser.parseFromString(xml,"text/xml");  
921        dscbox[n] = xmlElements.getElementsByTagName("detal");
922        detnr = detnum[n];
923      }
924
925      var p0 = 0, e0 = 0, l0 = 0, sub_lang = [];
926      try {
927        //if ((detail_x[1-set] && detail_y[1-set]) && (detail_x[1-set][n] && detail_y[1-set][n])) {
928          //console.log(" detail_x["+(1-set)+"]["+n+"] "+detail_x[1-set][n])
929          //console.log(" detail_y["+(1-set)+"]["+n+"] "+detail_y[1-set][n])
930        //}
931        if (newBone || (!(detail_x[set][n] && detail_y[set][n]) && (!(detail_x[1-set] && detail_y[1-set]) || !(detail_x[1-set][n] && detail_y[1-set][n])))) { //switchOnly  !debugSwitch
932          //console.log("upd side|wrap|sufx");
933          side = dscbox[n][0].getAttribute('side');
934          detail_side[1][n] = side.charAt(0);
935          detail_side[0][n] = side.charAt(side.length-1);
936          //console.log("detail_side[0,1]["+n+"] <-- "+detail_side[0][n]+","+detail_side[1][n]);
937          detail_wrap[n] = dscbox[n][0].getAttribute('wrap');
938          detail_sufx[n] = dscbox[n][0].getAttribute('sufx') == 1 ? 1 : 0;
939          fontsize = dscbox[n][0].getAttribute('size');
940        } 
941        /*
942        else if (DEBUG_MODE && debugSwitch) {
943          if (!set) //dla detalu
944          {
945            detail_side[n] = detail_side[lastDetidx];
946            detail_wrap[n] = detail_wrap[lastDetidx];
947          }
948          else if (!n) //dla setu -tylko raz
949          {
950            detail_side[lastDetidx] = detail_side[n];
951            detail_wrap[lastDetidx] = detail_wrap[n];
952          }
953        }
954        */
955        if (current_lang != "en")                  // _zawsze bedzie 0, bo jedna sekcja detalu w xml
956          detail_main[n] = [].slice.call(dscbox[n][0].getElementsByTagName(current_lang)).map(answer => { //.products  parsuj warianty odpowiedzi
957            var detail = answer.innerHTML.toLowerCase().trim().replace(/\s\s+/g, ' ').split("<o>");
958            var options = detail.length > 1 ? [].slice.call(answer.getElementsByTagName("o")).map(opt => { return opt.innerHTML.toLowerCase(); }) : null;
959            var suffx = !p0++ && main.length > 1 ? [ /* (detail_sufx[n] == "1" ? "kości " : "")+ */ name[0].getElementsByTagName(current_lang)[0].getElementsByTagName("s")[0].innerHTML.toLowerCase() ] : null;
960            return [detail[0], options, suffx];      //NEW 02.12 przeniesione do xml
961          });
962        sub_lang = [].slice.call(dscbox[n][0].getElementsByTagName("en")).map(answer => { //.products
963          var detail = answer.innerHTML.toLowerCase().trim().replace(/\s\s+/g, ' ').split("<o>");
964          var options = detail.length > 1 ? [].slice.call(answer.getElementsByTagName("o")).map(opt => { return opt.innerHTML.toLowerCase(); }) : null;
965          var suffx = null;
966          if (!e0++ && (current_lang == "en" && main.length > 1 || current_lang != "en" && en.length > 1)) {
967            var sfxbase = name[0].getElementsByTagName("en")[0].getElementsByTagName("s")[0].innerHTML.toLowerCase();
968            suffx = [ "of "+sfxbase, "of the "+sfxbase ];
969          }
970          return [detail[0], options, suffx];
971        });
972        if (current_lang == "en")
973          detail_main[n] = sub_lang;
974        else
975          detail_en[n] = sub_lang;
976        detail_la[n] = [].slice.call(dscbox[n][0].getElementsByTagName("la")).map(answer => { //.products
977          var detail = answer.innerHTML.toLowerCase().trim().replace(/\s\s+/g, ' ').split("<o>");
978          var options = detail.length > 1 ? [].slice.call(answer.getElementsByTagName("o")).map(opt => { return opt.innerHTML.toLowerCase(); }) : null;
979          var suffx = !l0++ && la.length > 1 ? [ name[0].getElementsByTagName("la")[0].getElementsByTagName("s")[0].innerHTML.toLowerCase() ] : null;
980          return [detail[0], options, suffx];
981        });
982
983        if (newBone || !(detail_x[set][n] && detail_y[set][n])) {
984          detail_x[set][n] = Number(dscbox[n][0].getElementsByTagName(set ? "setx" : "dx")[0].innerHTML);
985          detail_y[set][n] = Number(dscbox[n][0].getElementsByTagName(set ? "sety" : "dy")[0].innerHTML);
986          //console.log("detail_x["+set+"]["+n+"] <--- "+detail_x[set][n]);
987          //console.log("detail_y["+set+"]["+n+"] <--- "+detail_y[set][n]);
988        }
989        //if (DEBUG_MODE && lastDetidx == n) {
990        //  console.log("updating coords:::::::");
991        //  debug.innerHTML = "X:"+detail_x[set][n]+"  Y:"+detail_y[set][n];
992        //}
993
994        detail_nr[n] = detnr;
995        //console.log("detail_nr["+n+"] <--- "+detnr);
996        
997        descbox.innerHTML += '<span id="'+detnr+'" class="detal unselectable'+(set ? ' resolved' + (fontsize == 's' ? ' smaller' : fontsize == 'l' ? ' bigger' : '') : '')+'"></span>';
998         //all set x array ++++++++++++
999              
1000      } catch(e) { console.error(e); }
1001      
1002      n++;
1003    } while (set);
1004
1005    //console.log("lastDetail === "+lastDetail);
1006    //console.log("lastDetidx === "+lastDetidx);
1007    
1008    if (currentBone() || resolved) {
1009      if (currentBone("detailbad") /*&& !resolved*/)
1010        loosetag = "<span style='color:#a88'>";
1011        //if (!set && !debugSwitch) updDetail(); //upd jest w pic.onload
1012      //else relocate(1); NEW 28.11
1013      //descbox.style.opacity = "1.0"; console.log("b descbox.opa <--- 1");
1014    }
1015    if (resolved == 2 && !langSwitch) {    // ---------------------------------- tu nie currentBone("set") ?
1016      lastSet = currentBone("menu");
1017      //console.log(lastSet);
1018    }
1019    //newBone = 0;
1020  //}
1021  //if (switchOnly) return;            //// przy debug switch nie ma nowej kosci?
1022
1023  //var pic = d.getElementById("quizpic"); ///a powinna byc?
1024
1025  //setTimeout(function() { 
1026  //}, 3000);
1027                                                         //po co ten autolos?    //pomoglo nie zmieniac kosci przy langswitch
1028  if (!langSwitch && (!debModSwitch || autolos))  // !autolos NEW 06.03.2020  ( ) NEW 06.05.2021
1029	pic.load(currentBone("png"));           //potwierdzic czy kosc sie zmienila
1030  else /* if (!mobile) */
1031	updDetail(false,"pic");  //NEW 2020
1032  if (tabbing)  //if tab detail --mozliwe ze zrobic bezposredni boolean
1033    checkLastDetail();
1034  if (mobile) {
1035    if (langSwitch) inputChoices(true);
1036    /* else makeChoices(); */
1037  }
1038  tryDebug(); 
1039}
1040
1041function currentBone(cmd, value = null) {
1042  var bone = (detale[kosci[0]]) ? kosci[0] : lastBone;
1043  if ((tabbing || langSwitch || debModSwitch) && resolved == 2 && setbag.indexOf(bone) != -1) //debmod new
1044    bone = setbag[index];
1045
1046  var detail = (bone in detale) ? detale[bone][index] : Object.keys(bones[lastBone])[index]; //<------ tu nieposortowane??? DEBUG_MODE ? Object.keys(bones[bone]).sort(function(a, b){return a-b}) : shuffle(Object.keys(bones[bone]));
1047  //if (!detale[kosci[0]] && !cmd) console.log(cmd+": KOSC NIE MA DETALI, uzywam lastBone ("+lastBone+")");
1048  if (detail == null) return null;
1049  
1050  switch (cmd) {
1051    case 'name':
1052      //console.log(cmd+": sprawdzam dla kosci "+bone+" :: "+bone+detail);
1053      return ""+bone+detail;  //nazwa kosci z detalem
1054    case 'file':
1055    case 'png':
1056      //console.log(cmd+": sprawdzam dla kosci "+bone+" :: "+bone+detail+".png");
1057      return "kosci/"+bone+(resolved == 2 && setbag.indexOf(bone) != -1 ? "00" : detail)+".png";
1058    case 'set':
1059      //console.log(cmd+": sprawdzam dla kosci "+bone+" :: "+bone+detail+".png");
1060      return (resolved == 2 && setbag.indexOf(bone) != -1);
1061    case 'xml':
1062      //console.log(cmd+": sprawdzam dla kosci "+bone+" :: kosci/"+bone+detail+".xml");
1063      return "kosci/"+bone+(value ? value : detail)+".xml";
1064    case 'nr':
1065      //console.log(cmd+": sprawdzam dla kosci "+bone+" :: "+detail);
1066      return ""+detail;   //aktualny nr detalu
1067    case 'details':
1068      //console.log(cmd+": sprawdzam dla kosci "+bone+" :: "+((bone in detale) ? detale[bone].length : 0));
1069      if (bone in detale) return detale[bone].length;  //how many details left has current bone
1070      else return 0;
1071    case 'base':
1072      //console.log(cmd+": sprawdzam dla kosci "+bone+" :: "+bone);
1073      return ""+bone; //NEW 2020(resolved == 2 && setbag.indexOf(bone) != -1 ? setbag[index] : bone);    //kosc bez detalu ni rozszerzenia  //setbag new 29.11 - index dla resolved 2 wyjatkowo zmienia kosci -- gdzies jeszcze?
1074    case 'menu': //pozycja menu dla aktywnej kosci
1075     var grupy = Object.keys(grupa[current_lang]);
1076     for (var i = 0; i < grupy.length; i++) {
1077          for (var j = 0; j < grupa[current_lang][grupy[i]].length; j++) {
1078              for (var k = 0; k < podgr[current_lang][grupa[current_lang][grupy[i]][j]].length; k++) {
1079                  //var menu = d.getElementsByClassName('lvl3 psb'+(i+1)+' sub'+(j+1)+' it'+(k+1))[0];
1080                  var itemname = podgr[current_lang][grupa[current_lang][grupy[i]][j]][k].split(',')[0];
1081                  if (itemname == ""+bone) { //menu.textContent
1082                    return d.getElementsByClassName('lvl3 psb'+(i+1)+' sub'+(j+1)+' it'+(k+1))[0]; //menu;
1083                  }
1084              }
1085          }
1086       }
1087      return null;
1088    case 'typehit':
1089      if (value) { console.log(">>"+bone+" typehit => ["+value+"]"); if (!bonetypes[bone]) bonetypes[bone] = []; bonetypes[bone][1] = value; } //new 10.10
1090      //console.log(cmd+": sprawdzam dla kosci "+bone+" :: "+(bone in bonetypes ? bonetypes[bone][1] : false));
1091      if (bone in bonetypes) return bonetypes[bone][1];  //czy blednie zgadywany typ
1092      else return false;
1093    case 'type':
1094      if (value) { console.log(">>"+bone+" type => ["+value+"]"); if (!bonetypes[bone]) bonetypes[bone] = []; bonetypes[bone][0] = bone_type.indexOf(value); } //new 10.10
1095      //console.log(cmd+": sprawdzam dla kosci "+bone+" :: "+(bone in bonetypes ? bonetypes[bone][0] : false));
1096      if (bone in bonetypes) return bone_type[bonetypes[bone][0]];  //czy typ byl zgadywany - zwroc typ (dla kosci bazowej)
1097      else return false;
1098    case 'detailbad':
1099      if (value) console.log(">>"+bone+detail+" bad => ["+value+"]");
1100      return bones[bone][detail][1] = (value == null ? bones[bone][detail][1] : value); //czy detal blednie
1101    case 'detail':
1102    default:
1103      if (value) console.log(">>"+bone+detail+" detail => ["+value+"]");
1104      return bones[bone][detail][0] = (value == null ? bones[bone][detail][0] : value); //czy detal byl zgadywany (tablica glowna)
1105  }
1106}
1107
1108/*
1109function dnr() {
1110  return ("0" + (Number(detale[kosci[0]][0])+index)).slice(-2);
1111}
1112*/
1113
1114function showup(element, opacity_ = 1.0, steps = 30, delay = 0, withHide = false, id = "") {
1115  /* console.log("f showup"); */
1116  var lastOpac = parseFloat(element.style.opacity), currPic = lastPic;
1117  var hide = (opacity_ <= 0); if (hide) opacity_ = Math.abs(opacity_);
1118  var opac = hide && element.style.opacity ? lastOpac : withHide || (mobile && element == buttony) ? lastOpac : 0.0;
1119  //if (hide) element.style.opacity = "1.0";
1120  /* console.log("opac "+opac+" ---> "+opacity_); */
1121  clearInterval(showtimer[element.id+id]);
1122  /* console.log("setting "+element.id+id+" "+element.className); */
1123  showtimer[element.id+id] = setInterval(function(){
1124    if (delay-- <= 0) {
1125      opac += hide ? -0.1 : 0.1;
1126      element.style.opacity = ""+opac;
1127      /* console.log(element.id + " :: " +element.style.opacity); */
1128      if ((!id && DEBUG_MODE) || (hide && opac <= opacity_) || (currPic!=lastPic) || (!hide && opac >= opacity_)) {
1129        clearInterval(showtimer[element.id+id]);
1130        if (id) { element.removeClass("show"); /*hideSubList(true, true, true)*/ }
1131        else if (DEBUG_MODE)
1132          element.style.opacity = "1.0";
1133        else {
1134          element.style.opacity = (/*(hide && !id) ||*/ currPic!=lastPic && !hide) ? ""+lastOpac : ""+opacity_; // "0.0" : ""+opacity_;
1135          /* console.log(element.id + " :: " +element.style.opacity); */
1136          /* console.log("unshowed "+element.id+id); */
1137          /* console.log("------------------------------------"); */
1138          if (withHide && (currPic==lastPic)) 
1139              showup(element, lastOpac * (hide ? 1 : -1), steps, steps > 50 ? 20 : 10);
1140        }
1141        if (hide && !withHide) { /*inputsHide();*/ /* losowanie.left = ""; */ if (mobile && element == buttony) element.style.display = "none"; }  //MOBILE TYMCZASOWO
1142      }
1143    }
1144  }, steps);
1145}
1146
1147function hint(element) {
1148  showup(element, 1.0, 90, 0, !autolos);
1149}
1150
1151HTMLElement.prototype.load = function(pic) {
1152  //console.log("f load");
1153  var img = new Image();
1154  img.onload = function() {
1155    if (currentBone("set") && !debugSwitch && !debModSwitch)
1156      au_play(2);
1157    var pic = d.getElementById("quizpic");
1158    lastPic = pic.src.replace(/^.*[\\\/]/, '');
1159    //console.log("PIC LOADED :: "+lastPic);
1160    if (lastPic.split('.').pop() != "png")
1161      lastPic = null;
1162    if (!mobile)
1163      pic.style.top = "0";
1164    //pic.style.right = "0";
1165    pic.removeClass("offload");
1166    if (mobile) {
1167      quizpicbox.removeClass("offload");
1168      /* rect = pic.getBoundingClientRect();  */
1169      centerPic();
1170    }
1171    //pic.style.marginTop = "0";
1172    //pic.style.marginBottom = "0";
1173    if (!debModSwitch && !DEBUG_MODE || autolos) { // !autolos NEW 06.03.2020 {
1174      showup(pic);
1175      if (mobile && !resolved) {
1176        if (!currentBone("type"))  //if (!bonetypes[currentBone("base")]) {  //
1177          showup(buttony, 0.9);
1178        else {
1179          inputy.style.display = "flex";
1180          col2.addClass("dimmed");
1181          makeChoices();
1182          showup(inputy, 0.9, 30);
1183        }
1184      }
1185    }
1186    //pic.style.opacity = "1.0";
1187    //setTimeout(function() { if (pic.style.opacity != "1.0") pic.style.opacity = "1.0"; }, 550);   //hit i usunpic.style.opacity = "0.5";
1188    updDetail(false,"pic");  //currentBone("set") new
1189  }
1190  img.onerror = function() {
1191    console.error("blad ladowania obrazka > "+pic);
1192  }
1193  img.src = pic;
1194  this.src = img.src;
1195  /* setTimeout(function() {  */
1196    /* quizpic.removeClass("offload"); */
1197  /* }, 0);   */
1198}
1199
1200HTMLElement.prototype.preload = function() {
1201  //console.log("f preload");
1202  console.log(this.style.top);
1203  this.src = "";
1204  if (!mobile)
1205    this.style.top = "160px";
1206  else
1207  {
1208    setTranslate(0, 0, quizpic);
1209  }
1210  //this.style.right = "5px";
1211  //this.style.marginTop = "150px";
1212  //this.style.marginBottom = "110px";
1213  this.style.opacity = "0.05";
1214  this.src = "grf/loader2.gif";
1215  this.addClass("offload");
1216  if (mobile)
1217    quizpicbox.addClass("offload");
1218  
1219}
1220
1221function shutIt(detailsOnly = debModSwitch) {
1222/* if (mobile) return; */
1223  // console.log("f shutit");
1224  /*bonetyp = ""; loosebone = false;*/ loosetag = ""; eh = 0;
1225  if (!detailsOnly || mobile)
1226    inputsHide();
1227
1228  quiztxt.innerHTML = "";
1229  descbox.innerHTML = "";
1230  
1231  if (!mobile) {
1232    d.getElementById("inpucik").value = '';
1233    d.getElementById("inpucik").disabled = false;
1234  }
1235  else {
1236    unselectChoices();
1237    buttony.style.display = "none";    
1238  }
1239  
1240  if (!detailsOnly) {
1241    var trigger = d.getElementsByClassName("valid")[0];
1242    if (trigger) trigger.removeClass("valid");
1243  }
1244/*    
1245  Array.from(d.getElementsByClassName("valid")).forEach(elem => {  //or [].forEach.call(elsArray, function () {...})
1246    console.log("removing from "+elem);
1247    elem.removeClass("valid");
1248    //elem.onclick = checkBone;
1249  });
1250*/  
1251  ["detailset", "blad", "poprawnie"].forEach(tag => {  //function(tag, i, a) {  
1252    d.getElementById(tag).style.opacity = "0.0";
1253    d.getElementById(tag).style.display = "none";
1254  });
1255  
1256  if (DEBUG_MODE) {
1257    if (!detailsOnly)
1258      lastDetidx = null;
1259    debugbox.style.display = "none";
1260  }
1261}
1262
1263function equalsIgnoreCase(text, other) {
1264    return text.localeCompare(other, 'en', { sensitivity: 'base' }) === 0;
1265}
1266
1267function bgAlert(element, button, color) {
1268                             //rgb = rgb.substring(4, rgb.length-1).replace(/ /g, '').split(',');
1269  var a = mobile ? hexrgb("#f8f8f4") : hexrgb("#eeeeee"); //rgb(window.getComputedStyle(element, null).getPropertyValue("background-color"));
1270  var c = hexrgb(color);
1271  element.style.backgroundColor = color;
1272  if (button) button.style.opacity = "0.5";
1273  //score(0, 69, button);
1274  clearInterval(alerttimer);
1275  //Math.round(Math.random())
1276  var lr = c[0] < a[0], lg = c[1] < a[1], lb = c[2] < a[2];
1277  var step = 0, alerttimer = setInterval(function(){
1278      if (step++ > 10) {
1279        if (lr ? c[0] < a[0] : c[0] > a[0]) c[0] += lr ? 7 : -7;
1280        else if (button) button.style.opacity = "0.8";
1281        if (lg ? c[1] < a[1] : c[1] > a[1]) c[1] += lg ? 7 : -7;
1282        else if (button) button.style.opacity = "0.8";
1283        if (lb ? c[2] < a[2] : c[2] > a[2]) c[2] += lb ? 7 : -7;
1284        else if (button) button.style.opacity = "0.8";
1285
1286        if ((lr ? c[0] >= a[0] : c[0] <= a[0]) &&
1287            (lg ? c[1] >= a[1] : c[1] <= a[1]) &&
1288            (lb ? c[2] >= a[2] : c[2] <= a[2])) {
1289          c = a;  
1290          element.style.backgroundColor = 'rgb(' + c.toString() + ')';
1291          if (button) button.style.opacity = "1.0";
1292          clearInterval(alerttimer);
1293        }
1294        element.style.backgroundColor = 'rgb(' + c.toString() + ')';
1295      }
1296  }, mobile ? 20 : 12);
1297}
1298
1299function score(result, steps, button = false) {
1300  //console.log("---------------------------"); 
1301  console.log("\nf score : "+(result > 0 ? "HIT"+(!mobile ? " "+(button ? button.value : d.getElementById("inpucik").value) : "")+"!" : "PUDŁO!"));
1302  if (!result/*button || button == null*/)
1303    bgAlert(qarea, button, "#ab3a3a");
1304
1305  if (result) { if (snd) ok.play(); }
1306  else { eh++;
1307    if ((button && eh == BLEDY) || (!button && !autolos && currentBone("details") == 1 && eh == BLEDY)) { eh = -1; if (snd) ee.play(); }
1308    else if (snd) fu.play();
1309  }
1310    
1311  var score = d.getElementById(result ? "poprawnie" : "blad");
1312  d.getElementById(result ? "blad" : "poprawnie").style.opacity = "0.0";
1313  if (result) updScore(1); else updScore(-1);
1314/*   rect = qarea.getBoundingClientRect(); 
1315  score.style.left = ""+(window.innerWidth/2 - (result ? 127 : 52));
1316  score.style.top = ""+(rect.height/2 + rect.y); */
1317  score.style.display = "block";
1318  var opac = 1.0;
1319  clearInterval(scoretimer);
1320  score.style.opacity = "1.0";
1321  scoretimer = setInterval(function(){
1322    opac -= 0.1;
1323    score.style.opacity = ""+opac;
1324    if (opac <= 0.0) { score.style.opacity = "0.0"; score.style.display = "none"; clearInterval(scoretimer); }
1325  }, steps);
1326}
1327
1328function updScore(hit = 0) {
1329  if (resolved) return;
1330  /* console.log("f updScore"); */
1331  if (hit) {
1332    if (hit > 0) poprawnych+=hit; else zlych-=hit;
1333    var procenty = d.getElementById("procenty");
1334    var wynik = Math.floor((poprawnych/(poprawnych+zlych))*100);
1335    if (wynik < 30) procenty.style.color = "#a88";
1336    if (wynik < 30) procenty.style.color = "#a88";
1337    switch (Math.floor(wynik/10)) {
1338      case 0: procenty.style.color = "#b44"; break;
1339      case 1: procenty.style.color = "#a88"; break;
1340      case 2: procenty.style.color = "#c81"; break;
1341      case 3: 
1342      case 4: 
1343      case 5:
1344      case 6: procenty.style.color = "#aa8"; break;
1345      default:
1346        procenty.style.color = "#8a8";
1347    }  
1348    procenty.innerHTML = ""+wynik+"%";
1349  }
1350  var zestaw_ = d.getElementById("zestaw");
1351  zestaw_.innerHTML = ""+kosci.length  /* +"/"+zestaw */;
1352  
1353  if (wyniki.style.display == 'none' || wyniki.style.opacity == "0") { wyniki.style.display = "block"; showup(wyniki); }
1354}
1355
1356function applySound() {
1357  snd = d.getElementById("dzwiek").checked
1358  //console.log("f applySound " + snd);
1359  au_play(4);
1360  if (SWITCH_MEM) {
1361    setCookie('snd',snd,730);
1362  }
1363}
1364
1365function applyLangs(update = 1, tag = "angielski") {
1366  // console.log("f applyLangs");
1367  try {
1368    losowanie.stop();
1369  } catch(e) { }
1370  eng = d.getElementById("angielski").checked
1371  lat = d.getElementById("lacina").checked
1372  if (mobile) {
1373    if (tag == "angielski" && eng || tag == "lacina" && lat)
1374      au_play(4);
1375  }
1376  if (SWITCH_MEM) {
1377    c_en = eng; setCookie('en',eng,730);
1378    c_la = lat; setCookie('la',lat,730);
1379  }
1380
1381/*   console.log("f applyLangs "+c_en+" "+ c_la) */
1382  
1383  if (update) {
1384    showBone(0);
1385    updDetail();
1386    if (!mobile)
1387      tryDebug();
1388  }
1389}
1390
1391function uncheckLang(lng, cookie = SWITCH_MEM) {
1392  if (lng == "en") l = "angielski";
1393  else if (lng == "la") l = "lacina";
1394  else return;
1395  
1396  if (cookie) { 
1397    setCookie(lng,false,730);
1398    if (lng == 'en') c_en = false;
1399    if (lng == 'la') c_la = false;
1400  }
1401  
1402  d.getElementById(l).checked = false;
1403  //d.getElementById(l).disabled = true;
1404}
1405
1406function checkLang(lng, cookie = SWITCH_MEM) {
1407  if (lng == "en") l = "angielski";
1408  else if (lng == "la") l = "lacina";
1409  else return;
1410  
1411  if (cookie) {
1412    setCookie(lng,true,730);
1413    if (lng == 'en') c_en = true;
1414    if (lng == 'la') c_la = true;
1415  }
1416  
1417  //d.getElementById(l).disabled = false;
1418  d.getElementById(l).checked = true;
1419}
1420
1421function readTextFile(file)
1422{
1423    if (!file) return null;
1424    var allText;
1425    var rawFile = new XMLHttpRequest();
1426    rawFile.open("GET", file, false);
1427    rawFile.onreadystatechange = function ()
1428    {
1429        if(rawFile.readyState === 4)
1430        {
1431            if(rawFile.status === 200 || rawFile.status == 0)
1432            {
1433                allText = rawFile.responseText;
1434            }
1435        }
1436    }
1437    rawFile.send(null);
1438    return allText;
1439}
1440
1441function setCookie(name,value,days) {
1442	if (days) {
1443		var date = new Date();
1444		date.setTime(date.getTime()+(days*24*60*60*1000));
1445		var expires = "; expires="+date.toGMTString();
1446	}
1447	else var expires = "";
1448  document.cookie = name+"="+(value||"")+expires+"; path=/"; //document.cookie = name+"="+value+expires+"; path=/";
1449}
1450
1451function getCookie(name) {
1452	var nameEQ = name + "=";
1453	var ca = document.cookie.split(';');
1454	for(var i=0;i < ca.length;i++) {
1455		var c = ca[i];
1456		while (c.charAt(0)==' ') c = c.substring(1,c.length);
1457		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
1458	}
1459	return null;
1460}
1461
1462function eraseCookie(name) {
1463	setCookie(name,"",-1);
1464}
1465
1466function draggable(det, detnum) {
1467  var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0, off = 0, n = detnum, rect, set;
1468
1469  if (det.onmousedown) return;
1470  det.onmousedown = dragMouseDown;
1471  
1472  //var rect = pic.getBoundingClientRect();   //detail_side[det] == "l" detail_x[det] && detail_y[det]
1473  
1474  function dragMouseDown(e) {
1475    e = e || window.event;
1476    e.preventDefault();
1477    
1478    //console.log("clicked :: ["+n+"] --> "+detail_nr[n]);
1479    // get the mouse cursor position at startup:
1480    pos3 = e.clientX;
1481    pos4 = e.clientY;
1482    d.onmouseup = closeDragElement;
1483    d.onmousemove = elementDrag;
1484    
1485    set = currentBone("set") ? 1 : 0;
1486    rect = pic.getBoundingClientRect();
1487    //detail_x[n] = Math.round(det.offsetLeft-rect.x+off);
1488    //detail_y[n] = Math.round(det.offsetTop-rect.y);
1489
1490    detnr.innerHTML = detail_nr[n]; //resolved == 2 ? n : lastD];
1491    debug.innerHTML = "X:"+detail_x[set][n]+"  Y:"+detail_y[set][n];
1492
1493    /* console.log(detail_x[set][n] + " :: " + detail_y[set][n]); */
1494    
1495    var check = debugbox.getElementsByTagName("input");
1496    check[1].checked = (detail_side[set][n] == "l") ? true : false;
1497    
1498    //debug.className = n; 
1499    //lastDetidx = detail_nr.indexOf(lastDetail);
1500    if (set) {
1501      markDetail(det, n, rect, false);
1502      lastDetidx = n;
1503      lastDetail = det.id;
1504      console.log("lastDetail <-- "+lastDetail);
1505      //console.log("lastDetidx <-- "+lastDetidx);
1506    }
1507    
1508    if (detail_side[set][n] == "l") {
1509      off = det.getBoundingClientRect().width;
1510      //detail_x[n] = Math.round(det.offsetLeft-rect.x+off);
1511      det.style.left = (detail_x[set][n]+rect.x-off) + "px";
1512    }
1513    else off = set ? 0 : -1; //nie wiem czemu sie przesuwa o piksel przy pierwszym kliknieciu
1514    //debugLocation(rect, n);
1515    //tryDebug();           // NEW  26.11
1516  }
1517
1518  function elementDrag(e) {
1519    e = e || window.event;
1520    e.preventDefault();
1521    // calculate the new cursor position:
1522    pos1 = pos3 - e.clientX;
1523    pos2 = pos4 - e.clientY;
1524    pos3 = e.clientX;
1525    pos4 = e.clientY;
1526    // set the element's new position:
1527    det.style.top = (det.offsetTop - pos2) + "px";
1528    det.style.left = (det.offsetLeft - pos1) + "px";
1529
1530    //if (detail_side[n] == "l")
1531    //  off = det.getBoundingClientRect().width;
1532    //else off = 0;
1533    set = currentBone("set") ? 1 : 0;
1534    
1535    //rect = pic.getBoundingClientRect();
1536    detail_x[set][n] = Math.round(det.offsetLeft-rect.x+off); 
1537    detail_y[set][n] = Math.round(det.offsetTop-rect.y);
1538      
1539    debug.innerHTML = "X:"+detail_x[set][n]+"  Y:"+detail_y[set][n];
1540    debugLocation(rect, n);
1540 //new 26.11 nie odkomentowywac
1541    
1542    /* console.log(detail_x[set][n] + " :: " + detail_y[set][n]); */
1543  }
1544
1545  function closeDragElement() {
1546    // stop moving when mouse button is released:
1547    document.onmouseup = null;
1548    document.onmousemove = null;
1549    
1550    if (currentBone("set"))
1551      markDetail(det, n, rect);
1552  }
1553}
1554
1555function moveDetail(h, v) {
1556  var off, det, idx, set = currentBone("set") ? 1 : 0;
1557  
1558  if (set && lastDetidx == null) {
1559    lastDetidx = detail_nr.indexOf(lastDetail);
1560    console.log(resolved == 2);
1561    console.log();
1562  }
1563  
1564  idx = lastDetidx; //(set ? lastDetidx : 0);
1565  det = descbox.getElementsByClassName("detal")[set ? lastDetidx : 0];
1566  
1567  //detnr.innerHTML = lastDetail; //detail_nr[0];
1568  det.style.left = (det.offsetLeft + h) + "px";
1569  det.style.top = (det.offsetTop + v) + "px";
1570
1571  if (detail_side[set][idx] == "l")
1572    off = det.getBoundingClientRect().width;
1573  else off = set ? 0 : -1; //nie wiem czemu sie przesuwa o piksel przy pierwszym kliknieciu
1574  
1575  rect = pic.getBoundingClientRect();
1576  if (h) detail_x[set][idx] = Math.round(det.offsetLeft-rect.x+off); 
1577  if (v) detail_y[set][idx] = Math.round(det.offsetTop-rect.y);
1578    
1579  debug.innerHTML = "X:"+detail_x[set][idx]+"  Y:"+detail_y[set][idx];
1580  
1581  /* console.log(detail_x[set][idx] + " :: " + detail_y[set][idx]); */
1582  
1583  //console.log(d.onmouseup); <--jezeli, przesuwaj tez myszke (js nie umozliwia)
1584  //debugLocation(rect, n);
1585}
1586
1587function tab_jumpDetail(shift) {
1588  set = currentBone("set") ? 1 : 0;
1589  if (!set) return;
1590  
1591  var idx = detail_nr.indexOf(lastDetail);
1592  var det = descbox.getElementsByClassName("detal")[lastDetidx];
1593  rect = pic.getBoundingClientRect();
1594  
1595  markDetail(det, idx, rect, false);
1596
1597  if (shift) {
1598    if (--idx < 0) idx = detail_nr.length - 1;
1599  }
1600  else {
1601    if (++idx >= detail_nr.length) idx = 0;
1602  }
1603  lastDetail = detail_nr[idx];
1604  /* console.log(detail_nr); */
1605  lastDetidx = idx;
1606  //console.log("lastDetail <-- "+lastDetail);
1607  //console.log("lastDetidx <-- "+lastDetidx);
1608
1609
1610  detnr.innerHTML = detail_nr[idx]; //resolved == 2 ? n : lastD];
1611  debug.innerHTML = "X:"+detail_x[set][idx]+"  Y:"+detail_y[set][idx];
1612
1613  var check = debugbox.getElementsByTagName("input");
1614  check[1].checked = (detail_side[set][idx] == "l") ? true : false;
1615    
1616  det = descbox.getElementsByClassName("detal")[lastDetidx];
1617  //markDetail(det);
1618  markDetail(det, idx, rect); 
1619  
1620
1621  //tryDebug();
1622}
1623
1624function markDetail(det, n = lastDetidx, rect = pic.getBoundingClientRect(), mark = true) {
1625  //if (lastDetidx != n) {
1626    if (lastDetidx != null) {
1627      var lastD = descbox.getElementsByClassName("detal")[lastDetidx];
1628      lastD.innerHTML = lastD.innerHTML.replace(/<span style="position:relative;"><span class="marker mleft">(&#x261B;|☛)<\/span><\/span>|&nbsp;<span class="marker">(&#x261A;|☚)<\/span>/,"");
1629      if (detail_side[1][lastDetidx] == "l") {
1630        var off = lastD.getBoundingClientRect().width;
1631        lastD.style.left = (detail_x[1][lastDetidx]+rect.x-off) + "px";
1632      }
1633    }
1634    if (!mark) return;
1635    //console.log("MARKING :: "+det.id);
1636    if (detail_side[1][n] == "l")
1637      det.innerHTML = '<span style="position:relative;"><span class="marker mleft">&#x261B;</span></span>'+det.innerHTML;
1638    else
1639      det.innerHTML = det.innerHTML.replace(/(<|&lt;|$)/,'&nbsp;<span class="marker">&#x261A;</span>$1');
1640    //console.log(det.innerHTML);
1641    //console.log(det);
1642  //}
1643}
1644
1645function debugLocation(picRect) {
1646  var n = lastDetidx /*Number(debug.className)*/, r = 0;
1647  var set = currentBone("set") ? 1 : 0;
1648  if (window.innerWidth <= 1170) {
1649    if (detail_x[set][n] < (detail_side[set][n] == "l" ? picRect.width/2 : picRect.width/2/2/2)) {
1650      if (window.innerWidth <= 870) {
1651        var q = qarea.getBoundingClientRect(); 
1652        r = (q.width - window.innerWidth - 10)*0.95;
1653        //r = (window.innerWidth/2-q.width/2-window.scrollX);
1654      }
1655      debugbox.style.right = ""+r; debugbox.style.left = null;
1656    } else { debugbox.style.left = "15"; debugbox.style.right = null; }
1657  } else { debugbox.style.left = debugbox.style.right = null; }
1658}
1659
1660function componentToHex(c) {
1661    var hex = c.toString(16);
1662    return hex.length == 1 ? "0" + hex : hex;
1663}
1664
1665function rgbToHex(r, g, b) {
1666    return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
1667}
1668
1669function rgb(rgb) {
1670    return rgb.substring(4, rgb.length-1).replace(/ /g, '').split(',');
1671}
1672
1673function hexToRgb(hex) {
1674    var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
1675    return result ? {
1676        r: parseInt(result[1], 16),
1677        g: parseInt(result[2], 16),
1678        b: parseInt(result[3], 16)
1679    } : null;
1680}
1681
1682function hexrgb(hex) {
1683    var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
1684    return [ parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16) ]
1685}
1686
1687/*
1688function ogonki(word) {
1689  let ogonki = "ąćęłńóśżźĄĆĘŁŃÓŚŻŹ".split("");
1690  let litery = "acelnoszzACELNOSZZ".split("");
1691  let dictionary = {};
1692
1693  for(let i = 0; i < ogonki.length;i++){
1694      dictionary[ogonki[i]] = litery[i];
1695  }
1696  
1697  let shake = word.split("");
1698  let newword = "";
1699  for(let i = 0; i < shake.length;i++){
1700    if (dictionary[shake[i]])
1701      newword += dictionary[shake[i]]);
1702    else
1703      newword += shake[i];
1704  }
1705  console.log(word + " ===> " + newword);
1706  return newword;
1707}
1708*/
1709
1710function ogonki(str){
1711		re = /[ąćęłńóśżźĄĆĘŁŃÓŚŻŹ]/g;
1712		to = "acelnoszzACELNOSZZ";
1713		function replacer(chr) {
1714		//	alert(chr + " -> " + to.charAt(re.source.indexOf(chr)-1));
1715			return to.charAt(re.source.indexOf(chr)-1);
1716		}
1717		return str.replace(re,replacer);
1718}
1719
1720HTMLElement.prototype.switchClass = function(classn) {
1721    if (this.hasClass(classn)) this.removeClass(classn);
1722    else this.addClass(classn);
1723}
1724
1725HTMLElement.prototype.hasClass = function(classn) {
1726    return new RegExp('(\\s|^)' + classn + '(\\s|$)').test(this.className);
1727}
1728
1729HTMLElement.prototype.addClass = function(classn) {
1730    if (!this.hasClass(classn)){
1731        this.className = (this.className + " " + classn).trim();
1732    }
1733}
1734
1735HTMLElement.prototype.removeClass = function(classn) {
1736    var newClassName = "";
1737    var i;
1738    var classes = this.className.replace(/\s{2,}/g, ' ').split(" ");
1739    for(i = 0; i < classes.length; i++) {
1740        if(classes[i] !== classn) {
1741            newClassName += classes[i] + " ";
1742        }
1743    }
1744    this.className = newClassName.trim();
1745}
1746
1747HTMLElement.prototype.clearClasses = function(classn, exc = null) {
1748    var elements = this.getElementsByClassName(classn);
1749/*     while(elements.length > 0) {
1750        elements[0].removeClass(classn);
1751    }           
1752    exc.addClass(claccn);  */
1753    for(var i = 0; i < elements.length; i++) {
1754        if (exc == elements[i]) continue;
1755        elements[i].removeClass(classn);
1756    }
1757}
1758
1759HTMLElement.prototype.getClass = function(classn) {
1760    return this.getElementsByClassName(classn)[0];
1761}
1762
1763
1764function addEvents() {
1765  var input = d.getElementById("inpucik");
1766  
1767  input.addEventListener("keyup", function(event) {
1768    if (event.keyCode === 13) {
1769      event.preventDefault();
1770      var trimmed = this.value.trim().replace(/[\.,]/g, ' ').replace(/\s\s+/g, ' ');
1771      console.log("comparing \""+trimmed+"\"");
1772      if (this.value != trimmed)
1773        this.value = trimmed;
1774      checkBoneDetal(this.value);
1775      //if (checkBoneDetal(this.value))
1776        //this.value = '';
1777    }
1778    else if (event.keyCode === 27) {
1779      this.value = '';
1780      langMenu(1);
1781    }
1782  });
1783  
1784  window.addEventListener("keydown", function(event) {
1785    //console.log(event.keyCode);
1786
1787    if (event.keyCode === 38) { //UP
1788      if (DEBUG_MODE) moveDetail(0,-1);
1789    }
1790    else if (event.keyCode === 40) { //DOWN
1791      if (DEBUG_MODE) moveDetail(0, 1);      
1792    }
1793    else if (event.keyCode === 37) { //LEFT
1794      //d.getElementById("prev").click();
1795      if (DEBUG_MODE) moveDetail(-1, 0);      
1796      else prevDetail();
1797    }
1798    else if (event.keyCode === 39) { //RIGHT
1799      //d.getElementById("next").click();
1800      if (DEBUG_MODE) moveDetail(1, 0);      
1801      else nextDetail();
1802    }
1803    else if (event.keyCode == 32) { //SPACE
1804       if (d.activeElement.id == "inpucik") return;
1805       event.preventDefault();
1806       d.getElementById("losuj").click();
1807       //losuj();
1808    }
1809    else if (event.keyCode === 9) { //TAB
1810      if (DEBUG_MODE) tab_jumpDetail(event.shiftKey);  
1811      event.preventDefault();
1812    }
1813    else if (event.keyCode === 70) { //f
1814      if (DEBUG_MODE) {
1815        debugbox.getElementsByTagName("input")[0].click();
1816        event.preventDefault();
1817      }
1818    }
1819    else if (event.keyCode === 83) { //s
1820      if (DEBUG_MODE) {
1821        debugbox.getElementsByTagName("input")[1].click();
1822        event.preventDefault();
1823      }
1824    } 
1825    else if (event.keyCode === 87) { //w
1826      if (DEBUG_MODE) {
1827        debugbox.getElementsByTagName("input")[2].click();
1828        event.preventDefault();
1829      }
1830    }    
1831    else if (event.keyCode > 48 && event.keyCode < 54) {
1832      if (buttony.style.display != "none")
1833        event.preventDefault();
1834        buttony.getElementsByTagName("input")[event.keyCode-49].click();
1835    }
1836  });
1837}
1838
1839function donate() {
1840    var div = document.getElementById(target);
1841    div.innerHTML = '<iframe style="width:100%;height:100%;" frameborder="0" src="' + url + '" />';
1842}
1843
1844function reduce() {
1845  console.log("f reduce");
1846  lastBone = kosci.shift();
1847  console.log("6> lastBone --- "+lastBone);
1848  lastDetal = ""+detale[lastBone]; delete detale[lastBone];
1849  index = Object.keys(bones[lastBone]).indexOf(lastDetal);
1850  console.log(kosci);
1851  reduced = true;
1852}
1853
1854function prepareNext(reduce = true, losowanie = 0) {
1855  console.log("f prepareNext "+reduce);
1856  prepared = reduce/* true */; //NEW 2020  SPRAWDZIC CZY PRZY LOSOWANIU NA SETACH PO INDEX DETAL SIE UPDATUJE
1857
1858  if (!reduce && autolos && detale[kosci[0]]) { lastDetail = detale[lastBone = kosci[0]][0]; console.log("7> lastBone --- "+lastBone); }
1859  if (reduce) {  //albo w off warunek bez !autolos albo tu warunek if details > 1
1860    //prepared = true;
1861    console.log(">>usuwam detal "+detale[kosci[0]][autolos ? 0: index]+" || nowa tablica:");
1862    //lastBone = kosci[0]; //tu zalozenie ze taby nie beda ingerowac ani to w taby
1863    lastDetail = (detale[lastBone = kosci[0]].splice(autolos ? 0 : index, 1))[0]; //tabDetail(0);
1864    console.log("8> lastBone --- "+lastBone);
1865    console.log(detale[kosci[0]]); reduced = false;
1866  }
1867
1868  if (!autolos) return; //20.10  --- to wykomentowane dzialalo (poza szuflowaniem przy blednych i !autolos) 18.12
1869  //if (!reduce)
1870  //    lastDetail = detale[lastBone = kosci[0]][0]; //TO GDY NIE USUWAMY PRZY ZWYKLYM BLEDZIE --- PRZENIESC DO INNEJ F.
1871  
1872  //(AUTOLOS) PO NIEPRAWIDLOWYM DETAL NA KONIEC KOSCI, A KOSCI SHUFFLE (NIE PRZEKLADAC KOSCI NA KONIEC)
1873  if (kosci.length > 0) {       //PRZELOZ KOSC ZEBY SIE NIE POWTORZYLA PRZY LOSOWANIU ---- przestarzale rozw.
1874    if (currentBone("details") > 1 && !resolved) {
1875      if (index == 0) {
1876        console.log(">>przekladam detal "+detale[kosci[0]][0]+":");
1877        detale[kosci[0]].push(detale[kosci[0]].shift())
1878        //lastDetail = detale[kosci[0]][0];                         //NEW 7.20
1879        //console.log("SETTING LAST DETAIL = "+lastDetail+" INDEX = "+index);     //NEW 7.20
1880        console.log(detale[kosci[0]]);
1881      }
1882	  else
1883	    console.log(">>nie przekladam (index > 0)");
1884
1885      shuffleNext(); // reduced = false;
1886    }
1887    //console.log("reduced "+reduced);  //tu dodac reduced??
1888    else if (/*currentBone("details") == 1 && */currentBone("name")+".png" != lastPic && !resolved) { shuffleNext("ostatni niewyswietlony detal: ");  /*reduced = false;*/ } // TO ZOSTAWIC, DZIALA GDY OSTATNI DETAL ALE JESZCZE NIE WYSWIETLONY
1889    else if (!reduced && kosci.length > 1) {
1890	  var tmpbone;
1891	  if (!resolved)
1892		tmpbone = kosci.shift();  //kosc ma ostatni detal, bez szuflowania wywal na koniec
1893	  //2020 tu zrobie currentBone zamiast bone[0] zeby index w setach byl rozpoznawany
1894	  else { /* (setbag.indexOf(kosci[0]) != -1) */
1895		tmpbone = kosci.splice(kosci.indexOf(currentBone("base")), 1)[0];
1896      /* if (resolved) */
1897	    console.log("PRZESTAWIAM :::::::::::::: "+tmpbone);
1898        shuffleNext("", 0); //new 11.12
1899      }
1900      kosci.push(tmpbone);
1901      console.log(">>"+(resolved ? "szufluje i " : losowanie ? "" : "ostatni detal: ")+"przekladam kosc \""+tmpbone+"\":");
1902      console.log(kosci);
1903      //reduced = false;
1904    }
1905  }
1906  
1907  index = 0;
1908  reduced = false;
1909  
1910  prepareDetails();
1911
1912  lastDetail = detale[lastBone = kosci[0]][0];                         //NEW 15.10 lastBone
1913  console.log("1> lastBone --- "+lastBone);                           //new 2020.03 problem ze nie przerywa losowania na kosci (zmienia ja)
1914  //return 1; //newBone = 1; 
1915}
1916
1917function shuffleNext(txt = "", log = 1) {
1918    if (log)
1919      console.log(">>"+txt+"szufluje kosci:");  //jak kurwa ostatni detal to przekladaj na koniec
1920    kosci = shuffle(kosci); //kolejne losuj
1921    if (log)
1922      console.log(kosci);
1923}
1924
1925function prepareDetails() {
1926   if (!detale[kosci[0]]) { //10.10
1927    console.log(">>initialize fresh details for "+kosci[0]);
1928    
1929    detale[kosci[0]] = DEBUG_MODE ? Object.keys(bones[kosci[0]]).sort(function(a, b){return a-b}) : shuffle(Object.keys(bones[kosci[0]])); //shuffle(Object.keys(bones[kosci[0]])); //initialize fresh details for bone NEW 26.11
1930    //lastDetail = detale[kosci[0]][0];                         //NEW 7.20
1931    //console.log("SETTING LAST DETAIL = "+lastDetail);     //NEW 7.20
1932    console.log(detale);
1933  }
1934}
1935
1936function revokeDetail(del = true) {
1937  //jezeli hit i size == 1 to nie odzyskuj?  //CZY ODZYSKIWAC ZGADNIETE?
1938  console.log(">>revoking "+lastBone+lastDetail);
1939  //if (/*lastBone in */kosci.includes(lastBone)) 
1940  if (del) kosci.splice(kosci.indexOf(lastBone),1);
1941  kosci.unshift(lastBone);
1942  
1943  if (detale[lastBone]) {
1944    if (detale[lastBone].includes(lastDetail)) {
1945      detale[lastBone].splice(detale[lastBone].indexOf(lastDetail),1);
1946      detale[lastBone].unshift(lastDetail);
1947    }
1948  } else { console.log("there is no details"); }
1949    //else if (!detale[lastBone].length)  //przywroc tylko gdy byl ostatnim detalem (takie anuluj w czy losowac)
1950  //detale[lastBone].unshift(lastDetail); //niee, gdy byl ostatnim elementem anuluj odnosilo do bazy bones
1951  //tylko czy nie potrzeba index elementu
1952  
1953  console.log(kosci);
1954  console.log(detale[kosci[0]]);
1955}
1956
1957
1958function tabDetail(direction) {
1959  if (!DEBUG_MODE && direction) pic.style.opacity = "0.05";
1960  //else index = 0;
1961  //delete detale[kosci[0]][dtr()];
1962  //newBone = 1;
1963
1964  var size = currentBone("set") ? setbag.length : currentBone("details"); //details left   //Object.keys(bones[kosci[0]]).length;
1965  //console.log("SIZE  ===  "+size+"   CURRENT  ===  "+currentBone("name"));
1966  if (!size) {
1967    //console.log("KOSC NIE MA JUZ NIEROZWIAZANYCH DETALI");
1968    size =  Object.keys(bones[lastBone]).length; //KOSC NIE MA JUZ NIEROZWIAZANYCH DETALI
1969  }
1970
1971  index += (direction < 0 ? -1 : direction > 0 ? 1 : 0);
1972  //current = currentBone("nr"); //Number(detale[kosci[0]][0]);
1973
1974  //if (current + index > size)
1975  // index = 1 - current;
1976  //if (size == 0) console.log("new currentbone = "+currentBone("base"));
1977
1978  if (index > size - 1)
1979  index = 0
1980
1981  //else if (current+index < 1)
1982  // index = size - current;
1983
1984  else if (index < 0)
1985  index = size - 1;
1986
1987  if (!currentBone("set")) {
1988    prepareDetails();
1989    lastDetail = detale[kosci[0]][index];                    //NEW 7.20
1990  }
1991  else { //if (DEBUG_MODE) 
1992    lastBone = setbag[index]; //NEW 2020 newnew teraz potrzebne przy tabowaniu zwyklym /// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< to albo zczytywac z setbagu w langswitch
1993    console.log("11> lastBone --- "+lastBone);
1994  }
1995
1996  //newBone = !tabbing;
1997}
1998
1999function checkLastDetail() { //czy
2000  if (currentBone("set") && setbag.length > 1) {
2001    lastDetail = detail_nr[lastDetidx]; //Math.floor(Math.random()*(detail_nr.length-2))
2002    //console.log("losuje detal >> "+lastDetail);
2003  }  
2004}
2005
2006function resolveBones(kosc = kosci[0]/* , modSwitch = false */) { /**ODSŁONIĘCIE KOŚCI GDY RESOLVED 0**/
2007  if (!kosci.length) {
2008    revokeDetail();
2009    kosc = kosci[0];
2010  }
2011
2012  if (!debModSwitch) {
2013    wyniki.style.display = 'none'; 
2014    wyniki.style.opacity = "0.0"  
2015  }
2016
2017  lastBone = kosc; 
2018  console.log("12> lastBone --- "+lastBone);
2019  kosci = Object.keys(bones);   //zbior kosci
2020  
2021  //revokeDetail(true);
2022  kosci.splice(kosci.indexOf(lastBone),1);
2023  kosci.unshift(lastBone);
2024  
2025  //console.log("RESOLVING:::"); console.log(kosci); 
2026  detale[kosc] = Object.keys(bones[kosc]).sort(function(a, b){return a-b}); //zbior detali dla kosci -----tutej zrobic lastBoneDetails [] (przywraca nieposzuflowane)
2027  index = detale[kosc].indexOf(lastDetail);    //latwiej z index niz splice od indexof i unshift?
2028  //console.log("index = "+index);
2029  resolved = 1;
2030  console.log("bones resolved:");
2031  console.log(kosci);  
2032  if (/* !DEBUG_MODE &&  */!debugSwitch && !debModSwitch) 
2033    autolos = false;
2034  showBone(!debugSwitch && !debModSwitch/* && !modSwitch *//*  && !debModSwitch */);   //newBone = !debugSwitch;
2035}
2036
2037function importBones() {
2038  var imgList = readTextFile("./kosci/kosci.lst");
2039
2040  var imgList = imgList.split('\n');
2041  var parser = new DOMParser(), xmlElements, group, subgr, icon, name, bonebag = "";
2042  console.log("importing...");
2043  
2044  var menuinfo, menutemp;
2045
2046  for(var l=0, bone; l<imgList.length; l++) {
2047    bone = imgList[l].split('.').slice(0, -1).join('.');
2048    var lastp = progr ? Math.floor(progr/20) : -1;
2049    var progr = Math.floor(l/imgList.length*100);
2050    
2051    if (progr && (lastp != Math.floor(progr/20)))
2052      console.log(progr+"%");
2053      
2054    if (!bone) break;
2055
2056    var detailnr = bone.substr(-2, 2);
2057    var bonebase = bone.substr(0, bone.length - 2);
2058    var added = false;
2059    
2060    if (Number.isInteger(Number(detailnr))) {
2061      if (detailnr == "00") { if (DETAILSETS || DEBUG_MODE) all_sets.push(bonebase); continue; }
2062      var chkxml = readTextFile("./kosci/"+bonebase+detailnr+".xml"); 
2063      if (chkxml) {
2064         if (!bones[bonebase]) bones[bonebase] = [];
2065         bones[bonebase][detailnr] = [];
2066         //for (var i=0; i<3; i++)
2067           bones[bonebase][detailnr][0] = false;  //czy detal byl odpowiedziany
2068           bones[bonebase][detailnr][1] = false;  //czy z bledem
2069                                                  //czy rodzaj kosci byl odpowiedziany --typ przeniesiony do ogolu
2070                                                  //czy z bledem
2071         //creating menu
2072         if (!bonebag.includes(bonebase)) {
2073           langs.forEach(lng => {         
2074             xmlElements = parser.parseFromString(chkxml, "text/xml");
2075             group = xmlElements.getElementsByTagName("grupa")[0].getElementsByTagName(lng)[0].innerHTML.toLowerCase().trim().replace(/\s\s+/g, ' ');
2076             subgr = xmlElements.getElementsByTagName("grupa")[0].getElementsByTagName("podgr")[0].getElementsByTagName(lng)[0].innerHTML.toLowerCase().trim().replace(/\s\s+/g, ' ');
2077             if (!iconz[group])
2078             try {
2079              icon = xmlElements.getElementsByTagName("grupa")[0].getElementsByTagName("ikona")[0].innerHTML.toLowerCase().trim().replace(/\s\s+/g, ' ');
2080             } catch(e) { }
2081             name =  xmlElements.getElementsByTagName("nazwa")[0].getElementsByTagName(lng)[0].innerHTML.toLowerCase().trim().replace(/\s\s+/g, ' ').split("<s>")[0];
2082             subgr = subgr.charAt(0).toUpperCase() + subgr.slice(1)
2083             group = group.charAt(0).toUpperCase() + group.slice(1)
2084             name = name.charAt(0).toUpperCase() + name.slice(1)
2085             if (!iconz[lng]) iconz[lng] = [];
2086             if (!podgr[lng]) podgr[lng] = [];
2087             if (!grupa[lng]) grupa[lng] = [];
2088             if (!iconz[lng][group]) iconz[lng][group] = icon;
2089             if (!podgr[lng][subgr]) podgr[lng][subgr] = [];
2090             if (!grupa[lng][group]) grupa[lng][group] = [];             
2091             if (grupa[lng][group].indexOf(subgr) == -1) grupa[lng][group].push(subgr);
2092             if (podgr[lng][subgr].indexOf(name) == -1) podgr[lng][subgr].push(bonebase+","+name);
2093           });
2094           bonebag += ","+bonebase;
2095         }
2096      }
2097      else
2098        console.error("importowanie kości > "+bone+".png brakuje pliku "+bone+".xml");
2099    }
2100    else
2101      console.error("importowanie kości > "+bone+".png: zły nr detalu kości");
2102  }
2103  
2104  all_sets.forEach(b => { 
2105    if (!bones[b]) all_sets.splice(all_sets.indexOf(b), 1);
2106  });
2107
2108  kosci = shuffle(Object.keys(bones));   //zbior kosci
2109  zestaw = kosci.length;
2110  detale[kosci[0]] = DEBUG_MODE ? Object.keys(bones[kosci[0]]).sort(function(a, b){return a-b}) : shuffle(Object.keys(bones[kosci[0]])); //zbior detali dla kosci
2111  console.log("> bones imported(100%):");
2112  console.log(kosci);  
2113//  console.log("new bone > "+currentBone("name"));
2114//  console.log(detale);
2115    
2116/*  
2117  for (var key in bones) {
2118    console.log("key " + key + " has value " + bones[key][1]);
2119  }
2120  Object.keys(data).forEach(item => {
2121    console.log(item);
2122  });
2123  
2124  var iterator = bones.keys();
2125  console.log(iterator.next());
2126  console.log(iterator.next());
2127
2128  var sparseKeys = Object.keys(bones);     <------------
2129  var denseKeys = [...bones.keys()];
2130  console.log(sparseKeys); // ['0', '2']
2131  console.log(denseKeys);  // [0, 1,   
2132
2133  console.log(bones["lopatka"][0] == null);
2134  console.log(bones["lopatka"].includes(undefined));   
2135*/
2136}
2137
2138function createMenu(lng = current_lang, all = all_bones) {
2139   var menu = d.getElementById("menulist"), addons = "";
2140   var tmp = menu.getElementsByClassName("addon");
2141   for (var i = 0; i < tmp.length; i++)
2142     addons+=tmp[i].outerHTML;
2143   //var kosci = Object.keys(bones);
2144   var bonegr = grupa[lng], subgr = podgr[lng];
2145   var grupy = Object.keys(bonegr);
2146   var menulist = '<div id="item" onClick="'+(DEBUG_MODE ? "" : "runQuiz()")+'" onMouseOver="hideSubList(true,true,true)">'+all+'</div>';
2147   
2148   for (var i = 0; i < grupy.length; i++) {
2149      //console.log("1>"+grupy[i]);  //konczyna gorna, dolna
2150      menulist += '<div id="item" class="lvl1 sub0 it'+(i+1)+'"><div class="label">'+grupy[i]+'<span style="display:none">&nbsp;⊳</span></div></div>';
2151      for (var j = 0; j < bonegr[grupy[i]].length; j++) {
2152          //console.log("  2>"+bonegr[grupy[i]][j]);  //obrecz, przedramie
2153          if (j == 0) menulist += '<div id="sublist" class="sublista lv-2 pl-0 sl-'+(i+1)+'">';
2154          menulist += '<div id="item" class="lvl2 sub'+(i+1)+' it'+(j+1)+'"><div class="label">'+bonegr[grupy[i]][j]+'<span style="display:none">&nbsp;⊳</span></div></div>';
2155          for (var k = 0; k < subgr[bonegr[grupy[i]][j]].length; k++) {
2156              //console.log("    3>"+subgr[bonegr[grupy[i]][j]][k]);  //strzalkowa, łopatka  ▷
2157              if (k == 0) menulist += '<div id="sublist" class="sublista lv-3 pl-'+(i+1)+' sl-'+(j+1)+'">';
2158              menulist += '<div id="item" class="lvl3 psb'+(i+1)+' sub'+(j+1)+' it'+(k+1)+'"><div>'+subgr[bonegr[grupy[i]][j]][k].split(',')[1]+'</div><span /></div>';
2159              if (k == subgr[bonegr[grupy[i]][j]].length - 1) menulist += '</div>';
2160          }
2161          if ( j == bonegr[grupy[i]].length - 1) menulist += '</div>';
2162      }
2163   }
2164   menu.innerHTML = "";
2165   menu.innerHTML += menulist;
2166   menu.innerHTML += addons;
2167}
2168
2169/*       debug mode click (podczas resolved 1)            [true]         [3] odsłoń wszystkie detale, ale wróć do detalu aktywnego (potrzebne dla debug, zamiast resolveBones()) */
2170
2171function runQuiz(set = null, mod = 0, lng = current_lang) { //ZALACZANE KLIKNIECIEM W ITEM lub posresnio w PEŁNY QUIZ lub w ADDON click
2172/** 
2173    runQuiz()                         ---  A) URUCHOMIENIE QUIZU DLA ZESTAWU           warunek >> resolved: 2
2174                                           B) ODSŁONIĘCIE DETALI :2                    warunek >> resolved:0|1       /ODSŁONIĘCIE DETALI :1 przez resolveBones()
2175                                
2176                                           wywołanie :: ITEM-click, PEŁNYQUIZ-click, ADDON-click
2177                                
2178                                           parametry :: set - [zestaw] do uruchomienia (loop); [true] - zostań w sekcji, odsłonięcie detali; [null] - pomiń sekcję i dalej uruchom pełny quiz; 
2179     switch mode click (podczas resolved)  set [zestaw][true] { mod - [1] detale są odsłonięte: rozpocznij test dla ostatniego zestawu lub całości ([!4])
2180                       (podczas resolved)              [true]         [2] detale są odsłonięte lub częściowo: r1->r2|r2-r0 odsłoń do setu lub wyjdź; ([!4]) +zabieg potrzebny do odblokowania wszystkich kości pozostając na aktywnej
2181             ---nie ma (podczas testu) -> resolved     [true]         [2] pominięte } 
2182                       
2183       menu item click (podczas resolved)        set [zestaw] { mod - [4] detale są odsłonięte: aktywuj pierwszą kość z wybranego przetasowanego zestawu;
2184                       (podczas testu)                                [0] zwykły quiz: odsłoń losową kość z wybranego zestawu, losowe;
2185                                                                     [!4] kontynuuj tworzenie quizu dla wybranego zestawu kości ([2][1]), jeżeli resolved: forsuj wszystkie }
2186      menu all bones click                         set [null] { uruchom quiz dla wszystkich kości (menu) bez różnicy czy resolved (jeżeli tak - wyjdź), przetasowane }
2187      
2188**/
2189  console.log("f runquiz  mod "+mod+"  "+(typeof set === 'object' && set != null ? set.textContent.toLowerCase() : ""));
2190  if (DEBUG_MODE && !mod) return;
2191  //if tryb przegladania, pomin confirm
2192  if (!mobile && !debugSwitch && !debModSwitch)
2193    hideSubList(true);
2194  
2195  //tu sprawdzic czy zestaw ma
2196  
2197  if (set) {  //zezwolic dla resolved, ale odblokowac wszystkie kosci na koniec  |nie aktualne ==>// !resolved 10.10 (gdy odsloniete losowanie ma leciec po wszystkich kosciach wytegowac stad wszystkie ?resolved) -- ale zezwolic dla addona, by wyjsc quizem do aktualnej kosci
2198    if (set !== true) { 
2199
2200      var set_name = (mobile ? set.textContent : set.getElementsByTagName('div')[0].textContent.replace('⊳', '').trim());  //innerText
2201 //   if (!resolved) bonetypes = [];  //15.10  po co to skoro na dole jest reset  //new 10.10 -- to tylko jezeli not resolved
2202    //if ((!resolved || msg) && !confirm((msg ? msg+"\n > " : "Uruchamiam QUIZ : ")+set_name)) return;
2203    
2204   //   if (!resolved || (resolved == 1 && all_sets.length)) { //TRYB TESTU LUB PRZEGLADANIA (BEZ ZBIOROWYCH DETALI)
2205    //  if (resolved || confirm("Odsłonić wszystkie detale?\n > to działanie przerwie quiz")) { 
2206      /* 
2207      if (!resolved || resolved && mod == 1) */
2208      
2209      if ((!resolved || resolved && mod == 1) && !DEBUG_MODE)
2210        if (au_play(4) && (!confirm((resolved ? confirm_exit_mode+"\n > " : confirm_run+" : ")+set_name))) return;  
2211      //if (!debugSwitch)  
2212        au_play(0);
2213      //tutaj juz tworzymy zestaw unresolved dla quizu
2214      /* else if (mobile) closeSidebar(); */
2215      
2216      var itlvl = /lvl(\d)/g.exec(mobile ? set.parentNode.className : set.className)[1]; //set.className.match(/(?<=lvl)\d/g)[0];
2217      var tmpbones = [];
2218      //var grupy = Object.keys(grupa[lng]);
2219
2220      if (itlvl == 1)
2221        for (var i = 0; i < grupa[lng][set_name].length; i++)
2222          //for (var j = 0; j < grupa[lng][set_name].length; j++) 
2223            for (var k = 0; k < podgr[lng][grupa[lng][set_name][i]].length; k++)
2224              tmpbones.push(podgr[lng][grupa[lng][set_name][i]][k].split(',')[0]);
2225      if (itlvl == 2)
2226          for (var k = 0; k < podgr[lng][set_name].length; k++)
2227            tmpbones.push(podgr[lng][set_name][k].split(',')[0]);
2228      if (itlvl == 3) {
2229          var parent_name;
2230          if (!mobile) {
2231            var itsub = /sub(\d)/g.exec(set.className)[1]; //set.className.match(/(?<=sub)\d/g)[0];
2232            var parent = d.getElementsByClassName("lvl2 it"+itsub)[0];
2233            parent_name = parent.getElementsByTagName('div')[0].textContent.replace('⊳', '').trim();
2234          }
2235          else
2236            parent_name = set.parentNode.parentNode.parentNode.childNodes[0].textContent;
2237
2238/*        console.log("parent_node of " + set_name + ":");
2239          console.log(parent_name);
2240 */       for (var k = 0; k < podgr[lng][parent_name].length; k++)
2241            if (set_name == podgr[lng][parent_name][k].split(',')[1]) {
2242              tmpbones.push(podgr[lng][parent_name][k].split(',')[0])
2243              break;
2244            }
2245      }
2246      kosci = shuffle(tmpbones);   //zbior kosc
2247      zestaw = kosci.length;
2248      lastSet = set;
2249    }
2250    if (mod == 4) {  //DLA MENU CLICK PRZY DEBUG MODE//RESOLVED -- uscislic
2251      /* if (mobile) closeSidebar(); */
2252      prepareBone();
2253      setbag = all_sets;  /** setbag ze zbioru wszystkich grupenów00 **/
2254      prepareBag()
2255      //console.log("3> lastBone --- "+lastBone);
2256      console.log("RESOLVED KOSCI::::");
2257      console.log(currentBone("base"));
2258    }     
2259    else {
2260      if (resolved && !debModSwitch) {
2261        //console.log(":::SETTING BAG");
2262        /* if (mobile) closeSidebar(); */
2263        if (mod == 2)
2264          prepareBone();   //VVV potrzebne do ponownego resolved set tab all
2265        setbag = [];
2266        all_sets.forEach(b => { 
2267          if (kosci.indexOf(b) != -1) setbag.push(b); 
2268          //jezeli nie, zwykly resolved (losuj, prepare sprawdza czy actual in setbag)
2269        });
2270        /* console.log(all_sets);
2271        console.log(kosci);
2272        console.log(setbag); */
2273        prepareBag();
2274        // console.log(setbag);
2275        if (mod == 2) {
2276          if (resolved < 2) resolved = 2;
2277          else resolved = 0;        
2278        }
2279      }
2280//      if (resolved/* < 2*/ && mod == 2) {  //NEW 08.12 //ZABIEG POTRZEBNY BY ODSLONIC KOSCI NA AKTYWNEJ, ALE ODBLOKOWAC DO LOSOWANIA WSZYSTKIE
2281//        if (!debModSwitch) VVV
2282//          prepareBone();
2283        /* var bone = kosci[0]; //tu jest dla item resolved (set)
2284        kosci = Object.keys(bones); //14.10 shuffle(Object.keys(bones));  //czemu tu shuffle dla odsloniecia? BEZ SZUFLA I NA INDEXIE ---nie bedzie skakac bo nie bedzie usuwac
2285        var tmpbone = kosci.splice(kosci.indexOf(bone));
2286        kosci = tmpbone.concat(kosci); */
2287        //kosci.unshift(bone);
2288        
2289/*         if (!debModSwitch) {
2290          if (resolved < 2) resolved = 2;
2291          else resolved = 0;
2292        } 
2293      }*/
2294      if (mod == 1) { //end of quiz msg in this example //SURE?? NIE DLA KAZDEGO WYJSCIA?
2295
2296        resolved = 0;  //^? wedlug mnie teraz to a addon click do powrotu do testu
2297        //switchMode(0);
2298      }
2299    }
2300
2301  }  //DLA ALL BONES ITEM: jezeli odsloniete i nie wykonane lub pytaj //CZY RESOLVED NIE BEDZIE ZAWSZE GDY MSG?
2302  else if (au_play(4) &&/*(resolved && !msg) || */(DEBUG_MODE || confirm(resolved == 2 ? confirm_exit_mode : confirm_run_all))) { //koment 10.10 w ciemno
2303    /* if (mobile) closeSidebar(); */
2304    if (resolved < 2) setbag = all_sets;
2305    else setbag = [];  //17.10
2306    kosci = shuffle(Object.keys(bones));  //tu jest dla quiz all (bez roznicy czy resolved)
2307    zestaw = kosci.length;
2308    lastSet = null;
2309    //bonetypes = [];  /////////////PRZED ZAPYTANIEM??? zastosuje tu reset
2310    resolved = 0; //???
2311    //switchMode(0);
2312  }
2313  else return;
2314 
2315  if (mobile) closeSidebar();
2316  //if (resolved) {
2317    //kosci = Object.keys(bones);   //zbior kosci
2318
2319  //}
2320  //else { //15.10
2321  if (/*!resolved*/ mod != 2) {
2322    detale[kosci[0]] = /*DEBUG_MODE || */resolved ? Object.keys(bones[kosci[0]]).sort(function(a, b){return a-b}) : shuffle(Object.keys(bones[kosci[0]])); //); //zbior detali dla kosci //TUTAJ ZBIORCZY?
2323    if (lastDetail == detale[kosci[0]][0] && currentBone("details") > 1)
2324      detale[kosci[0]].push(detale[kosci[0]].shift());
2325    index = 0;  
2326  }
2327 
2328  if (!DEBUG_MODE && !debModSwitch/*&& lastDetidx != null)*/) {
2329    lastDetail = detale[lastBone = kosci[0]][index];
2330    console.log("4> lastBone --- "+lastBone+"  lastDetail --- "+lastDetail);
2331  }
2332
2333    //index = detale[kosci[0]].indexOf(lastDetail);    //latwiej z index niz splice od indexof i unshift?  
2334    //index = 0;  
2335  //console.log("SETTING LAST DETAIL = "+lastDetail);     //NEW 7.20  
2336  //resolved = false;
2337  if (!debModSwitch) {
2338    console.log(resolved ? "resolved bones:" : "quiz for bones:");
2339    console.log(kosci); 
2340  }  
2341  if (CLEARTYPES && resolved == 2) bonetypes = [];  //new 17.10   //06.11 nie czysc typow kosci
2342  //prepared = false; 
2343  //resolved = false;
2344  //lastDetail = detale[lastBone = kosci[0]][0];
2345  if (!mod) switchMode(); //NEW 06.03.2020
2346  if (!debModSwitch) {
2347    poprawnych = zlych = 0;  //TU MSG JEST ODPALANE PRZY WYCHODZENIU Z TRYBU, NIE NA KONIEC TESTU!
2348    //if (currentBone("set")) wyniki.style.display = 'none'; //new 02.24
2349    /* if (currentBone("set")) { */
2350      wyniki.style.display = 'none'; 
2351      wyniki.style.opacity = "0.0"  
2352    /* } */    
2353    if (!resolved) {
2354      reset(); //to sprawdze czy dla wszystkich przypadkow bo bylo commented
2355      prestart();  ////////==============TU JEST PROBLEM -- POTRZEBNE DLA RESETOWANIA ALE KLUCI SIE Z KONCEM TESTU
2356    }
2357  }
2358  else if (debModSwitch)
2359    shutIt(true);
2360  if (/* !DEBUG_MODE &&  */!debModSwitch && !debugSwitch)  //new 02.24
2361    autolos = !resolved;
2362/* console.log("::3");
2363  switchMode(); */  //NEW 2020
2364  //newBone = !debugSwitch;
2365  showBone(!debugSwitch/*  && !debModSwitch */);    
2366  //tryDebug();
2367  return;
2368
2369    /*shutIt(); pic.preload();*/
2370  /*  resolveBoresolveBones();
2371    wyniki.style.display = 'none'; 
2372    wyniki.style.opacity == "0.0"
2373  }
2374*/
2375} 
2376
2377
2378function prepareBag() { /**ustaw aktywną kość na początek setbag żeby odsłonić sety na aktywnej kości**/
2379  if (setbag.indexOf(kosci[0]) != -1) {  //jeżeli kość posiada grupena  //new 06.11 daj na poczatek od kiedy index lata tez po setach
2380    if (setbag[0] != kosci[0]) {
2381      setbag.splice(setbag.indexOf(kosci[0]),1); //daj go na początek
2382      setbag.unshift(kosci[0]);  
2383    }
2384    index = 0;
2385  }
2386}
2387
2388function prepareBone() { /**zresetuj pozostałe kości dla odsloniecia (bez shuffla)**/
2389  console.log("f preparebone  "+kosci[0]+"  currentbone "+currentBone("base"));
2390  var bone = kosci[0];
2391  kosci = Object.keys(bones); //14.10 shuffle(Object.keys(bones));  //czemu tu shuffle dla odsloniecia? BEZ SZUFLA I NA INDEXIE  ---nie bedzie skakac bo nie bedzie usuwac
2392  var tmpbone = kosci.splice(kosci.indexOf(bone));
2393  kosci = tmpbone.concat(kosci);
2394  zestaw = kosci.length;  
2395  lastBone = kosci[0];
2396  console.log("13> lastBone --- "+lastBone);
2397}
2398
2399/*
2400function prepareBoneSet() { /**ustaw aktywną kość na początek setbag żeby odsłonić sety na aktywnej kości/
2401  if (setbag.indexOf(kosci[0]) != -1) {  //jeżeli kość posiada grupena  //new 06.11 daj na poczatek od kiedy index lata tez po setach
2402    if (setbag[0] != kosci[0]) {
2403      setbag.splice(setbag.indexOf(kosci[0]),1); //daj go na początek
2404      setbag.unshift(kosci[0]);  
2405    }
2406    index = 0;
2407  }
2408}
2409*/
2410
2411HTMLElement.prototype.start = function(hit = true, piccheck/*, fun*/) {
2412  if (lastPic != piccheck) return;
2413  console.log("licznik. . .");
2414  d.getElementById("losuj").focus();    
2415  var num = hit || reduced || mobile ? 2 : 3;
2416  var opac = 0.4, inc = 0.05; step = 0, it = true;
2417  var element = this, rot = 0, tmp;
2418  element.innerHTML = ""+num;
2419  if (!mobile) element.style.marginLeft = (d.getElementById("inpucik").disabled ? "270px" : "28px");
2420  licznik = setInterval(function(){
2421    step++;
2422    if ((tmp = Math.floor(step/20)) % 2 == 1 && tmp != rot) {
2423      rot = tmp; it = !it; if (it) inc *= -1; if (it && inc > 0) element.innerHTML = (num-=1);
2424    }
2425    opac += (!it ? 0.0 : inc);
2426    if (opac > 1.0) opac = 1.0;
2427    if (opac <= 0.3) { opac = 0.3; step+=5; }
2428    element.style.opacity = ""+opac;
2429    if (num <= 0) {
2430      element.innerHTML = ""; clearInterval(licznik); /*if (autolos)*/ losuj(false /*, fun*/); /*else prepareNext(hit); *///losuj(hit); //tam sie zalacza autolos!  //d.getElementById("losuj").click();
2431    }
2432  }, 10);
2433}
2434
2435HTMLElement.prototype.stop = function() {
2436  //console.log("f stop");
2437  this.innerHTML = ""; clearInterval(licznik);
2438}
2439
2440function showSubList(lv, nr, psb) {
2441  var /*sub = "lvl"+lv,*/ subitems = d.getElementsByClassName("sublista lv-"+lv+" "+(psb ? "pl-"+psb+" " : "")+"sl-"+nr);  //
2442  //var len = d.getElementsByClassName("lvl"+lv+" sub"+nr).length;
2443  if (!subitems) return;
2444  try {
2445    var len = subitems[0].getElementsByClassName("lvl"+lv/*+" sub"+nr*/).length;
2446  } catch(e) { }
2447  if (!len) { /*hideSubList();*/ return; }
2448
2449  if (!subitems[0].style.bottom) {
2450    //var psb = subitems[0].className.match(/(?<=pl-)\d/g)[0];
2451    var parent = d.getElementsByClassName("lvl"+(lv-1)+" sub"+psb);
2452    var add = d.getElementsByClassName("addon");
2453    if (add) {
2454      var addl = add.length;
2455      var addh = add[0].getBoundingClientRect().height;
2456    }
2457    subitems[0].style.bottom = 40*(parent.length-nr-(len == 1 ? 0 : 1))+(lv == 2 ? addl*addh : 0);
2458  }
2459 
2460  if (!subitems[0].style.left) {
2461    var itembox = d.getElementsByClassName("lvl"+(lv-1)+(psb ? " sub"+psb : ""))[0].getBoundingClientRect();
2462    subitems[0].style.left = itembox.width > 0 ? itembox.width : d.getElementsByClassName("lista")[0].getBoundingClientRect().width;
2463  }
2464  
2465  var sublists = d.getElementsByClassName("sublista lv-"+lv);
2466   
2467  
2468  //var itembox = d.getElementsByClassName("lvl"+(lv-1)+" sub"+nr)[0].getBoundingClientRect(); //parent[0].
2469  //console.log(parent);
2470  //console.log("parent width = "+itembox.width);  
2471    
2472    
2473  for (var i=0; i < sublists.length; i++) {
2474    if (sublists[i].classList.contains("sl-"+nr)) {
2475      //var itembox = d.getElementsByClassName("lvl"+(lv-1))[0].getBoundingClientRect();
2476      //sublists[i].style.left = itembox.width > 0 ? itembox.width : d.getElementsByClassName("lista")[0].getBoundingClientRect().width;
2477      
2478      //console.log(sublists[i].style.left);
2479      //console.log(d.getElementsByClassName("lista")[0].getBoundingClientRect().width);
2480      breakInterval(sublists[i]/*,""+lv+nr+sublist[i].className.match(/(?<=pl-)\d/g)[0]*/);
2481      sublists[i].classList.add("show"); //.addClass("show");
2482      //sublists[i].style.opacity = "1.0";
2483    }
2484    else 
2485      sublists[i].classList.remove("show"); 
2486   // else
2487      //sublists[i].classList.remove("show"); //.addClass("show");
2488  }
2489
2490  //additional lvl clean
2491  var menu_lvl = Number(menuitem.split(',')[0])
2492  var menu_item = Number(menuitem.split(',')[2]);
2493  
2494  if (menu_lvl < 3) { //dodatkowy check -- likwiduje dziwne nieofy
2495    var itm = d.getElementsByClassName("lvl"+menu_lvl);
2496    for (var i = 0; i < itm.length; i++) {
2497      var it = /it(\d)/g.exec(itm[i].className)[1]; //itm[i].className.match(/(?<=it)\d/g)[0];
2498      if (it != menu_item && itm[i].hasClass("active")) {
2499        itm[i].classList.remove("active");
2500        itm[i].getElementsByClassName('label')[0].classList.remove('offset');
2501        itm[i].getElementsByTagName('span')[0].classList.remove('arrow');
2502        if (isFirefox)
2503          itm[i].getElementsByTagName('span')[0].classList.remove('ff');
2504      }
2505    }  
2506  }  
2507}
2508
2509function hideSubList(force = false, lastoff = false, menu = false) {    //tu tez lvl
2510  if (hiding) return;
2511  hiding = true;
2512  var sublist = d.getElementsByClassName("sublista");    //mouseOnList ma miec LVL
2513  //sublist.classList.remove("show");
2514
2515  if (!menuitem) {
2516    updateActives();
2517    menuitem = ""; //if it was null
2518  }
2519  
2520  var menu_lvl = Number(menuitem.split(',')[0])
2521  var menu_sub = Number(menuitem.split(',')[1]);
2522  var menu_item = Number(menuitem.split(',')[2]);
2523
2524  if (lastitem.length && lastoff) {
2525    for (var i = 0; i < lastitem.length; i++) {
2526      var itlvl = /lvl(\d)/g.exec(lastitem[i].className)[1]; //lastitem[i].className.match(/(?<=lvl)\d/g)[0];
2527      if (itlvl == 3) continue;
2528      var itnum = /it(\d)/g.exec(lastitem[i].className)[1]; //lastitem[i].className.match(/(?<=it)\d/g)[0];
2529      if (force || (menu_lvl < itlvl) || (menu_lvl == itlvl && menu_item != itnum)) {
2530        lastitem[i].classList.remove("active");
2531        lastitem[i].getElementsByClassName('label')[0].classList.remove('offset');
2532        lastitem[i].getElementsByTagName('span')[0].classList.remove('arrow');
2533        if (isFirefox)
2534          lastitem[i].getElementsByTagName('span')[0].classList.remove('ff');        
2535      }
2536    }
2537    lastitem = [];
2538  }
2539  else if (!menu_lvl) {
2540    var itm = d.getElementsByClassName("active lvl1 sub0")[0];
2541    if (itm) {
2542      itm.classList.remove("active");
2543      itm.getElementsByClassName('label')[0].classList.remove('offset');
2544      itm.getElementsByTagName('span')[0].classList.remove('arrow');
2545      if (isFirefox)
2546        itm.getElementsByTagName('span')[0].classList.remove('ff');        
2547    }
2548  }
2549  
2550  if (menu) {
2551    Array.from(d.getElementsByClassName("sublista")).forEach(sublist => { 
2552      sublist.classList.remove("show"); 
2553    });      
2554    hiding = false;
2555    return;
2556  }
2557  
2558  for (var i = 0; i < sublist.length; i++) {
2559    var lvl = /lv-(\d)/g.exec(sublist[i].className)[1]; //sublist[i].className.match(/(?<=lv-)\d/g)[0];
2560    var sub = /sl-(\d)/g.exec(sublist[i].className)[1]; //sublist[i].className.match(/(?<=sl-)\d/g)[0];
2561    var psb = /pl-(\d)/g.exec(sublist[i].className)[1]; //sublist[i].className.match(/(?<=pl-)\d/g)[0];
2562/*
2563    try {
2564      var llvl = Number(lastitem.split(',')[0])
2565      var lsub = Number(lastitem.split(',')[1]);
2566    } catch(e) { }
2567*/    
2568    if (!menuitem || force || (sublist[i].hasClass("show") && (lvl > menu_lvl || (lvl == menu_lvl && menu_sub != sub)) && !(menu_lvl + 1 == lvl && menu_sub == psb && menu_item == sub))) {
2569        //console.log("usuwam>> menu_lvl "+menu_lvl+" lvl "+lvl+" menu_item "+menu_item+" sub "+sub+"  menu_sub "+menu_sub+" psb "+psb);
2570        //console.log(sublist[i].className);
2571        //if (!menuitem || menu_lvl < lvl) {
2572        //console.log("hide:");
2573        //console.log(sublist[i]);
2574        showup(sublist[i], -0.0, 42, 0, false, ""+lvl+psb+sub); //new from 1.0
2575        //}
2576        //else
2577        //  sublist[i].removeClass("show");  
2578    }
2579    /*
2580    else {
2581      if (lvl == menu_lvl) console.log("nie usuwam: ten sam lvl");
2582      if (menu_lvl + 1 == lvl && menu_sub == psb && menu_item == sub) console.log("nie usuwam: rozwiniete menu nalezy do hover itemu  menu_lvl "+menu_lvl+" lvl "+lvl+" menu_item "+menu_item+" sub "+sub);
2583    }
2584    */
2585  }
2586  if (force) toggleList(false);
2587  hiding = false;
2588}
2589
2590
2591function breakInterval(elem/*, id*/) {
2592  var lvl = /lv-(\d)/g.exec(elem.className)[1]; //elem.className.match(/(?<=lv-)\d/g)[0];
2593  var sub = /sl-(\d)/g.exec(elem.className)[1]; //elem.className.match(/(?<=sl-)\d/g)[0];
2594  var psb = /pl-(\d)/g.exec(elem.className)[1]; //elem.className.match(/(?<=pl-)\d/g)[0];
2595  if (lvl == 3) {
2596        var sublist = d.getElementsByClassName("sublista lv-2 pl-0 sl-"+psb);
2597        breakInterval(sublist[0]);
2598  }
2599  else
2600    restoreActives(Number(lvl)-1, psb, sub)  //lvl, sub, it       sl- ---->  it    pl- ----> sub    lv- ----> lvl-1
2601  clearInterval(showtimer[elem.id+lvl+psb+sub]);
2602  elem.style.opacity = "1.0";
2603  //console.log("breaking " + elem.id+lvl+psb+sub + " " + elem.className);
2604}
2605
2606function toggleList(toggle = true) {
2607  var menulist = d.getElementById("menulist");
2608  if (menulist.onmouseout) menulist.onmouseout = null;
2609  if (toggle)
2610    menulist.classList.toggle("show");
2611  else
2612    menulist.classList.remove("show");
2613  if (menulist.classList.contains('show'))
2614  {
2615    menubtn.addClass("pressed"); 
2616    au_play(1);
2617  }
2618  else
2619  {
2620    menubtn.removeClass("pressed"); 
2621    au_play(0);
2622  }
2623}
2624
2625function langMenu(trigg = 0) {
2626  var langbtn = d.getElementById("lang");
2627  var btndash = d.getElementById("dash");
2628  var menulist = d.getElementsByClassName("langlist")[0];
2629  if (!langbtn.hasClass('lng')) //classList.contains('lng'))
2630  {
2631    langbtn.removeClass("off"); 
2632    langbtn.addClass("lng");  
2633    btndash.src = "grf/dash.png";
2634  /*   if (!mobile)
2635      showup(menulist, -0.0, 20);    
2636    else */
2637      setTimeout(function() { showup(menulist, -0.0, 20); }, 0); 
2638    /* menulist.removeClass("show"); */
2639    setTimeout(function() { menulist.addClass("off"); }, 300); 
2640    if (!trigg) au_play(4);
2641  }
2642  else if (!trigg)
2643  {
2644    langbtn.removeClass("lng"); 
2645    langbtn.addClass("off"); 
2646    btndash.src = "grf/dashoff.png";
2647    /* menulist.style.opacity = "0.0"; */
2648    /* menulist.addClass("show"); */
2649    menulist.removeClass("off");
2650    showup(menulist, 0.8, 40);
2651    au_play(4)
2652  }
2653}
2654
2655
2656function restoreActives(lvl, sub, it) {
2657  var item = d.getElementsByClassName('lvl'+lvl+' sub'+sub+' it'+it)[0];
2658  if (lvl > 1) {
2659    restoreActives(lvl-1, lvl == 2 ? 0 : /psb(\d)/g.exec(item.className)[1], sub); //item.className.match(/(?<=psb)\d/g)[0]
2660  }
2661
2662  if (!item.classList.contains('active')) { 
2663    item.className = "active "+item.className; //if contains
2664    item.getElementsByClassName('label')[0].classList.add('offset');
2665    item.getElementsByTagName('span')[0].classList.add('arrow');
2666    if (isFirefox)
2667      item.getElementsByTagName('span')[0].classList.add('ff');     
2668  }     
2669}
2670
2671
2672function updateActives() {
2673    var itm = d.getElementsByClassName("active");
2674    for (var i = 0; i < itm.length; i++) {
2675      lastitem.push(itm[i]); 
2676    }
2677}
2678
2679
2680function switchDetails(init = 0) { //ZALACZANE PRZEZ ADDON CLICK
2681  console.log("---------------------------"); 
2682  console.log("f switchdetails");
2683  timersStop();
2684  if (DEBUG_MODE)
2685    debugSwitch = true;
2686  //if (!debugSwitch) {
2687	/* hideSubList(true);
2688		console.log("::2"); */
2689	 // }	
2690  var set = currentBone("set");
2691  if (DEBUG_MODE && set) {  //resolved == 2 new 26.11
2692  console.log("<<<<<<2");
2693    if (debugbox.style.display == "none") return;
2694    //var debugbox = d.getElementById("debug");
2695
2696    var check = debugbox.getElementsByTagName("input");
2697    check[0].click();
2698    au_play(0);
2699  }
2700  //else
2701  //if (!init && DEBUG_MODE && setbag.indexOf(lastBone) == -1) { //TO BLOKUJE GDY NAJPIERW DEBUG POZNIEJ RESOLVED
2702  //console.log("<<<<<<3");
2703  //  return;
2704  //}
2705  else
2706  if (resolved && !(resolved == 1 && all_sets.length)) {  //TRYB DETALI - uruchom test
2707  console.log("<<<<<<4");
2708    //console.log("---------------------------"); 
2709//    bonetypes = [];
2709  /////////////PRZED ZAPYTANIEM???
2710    reset();                                                  //                _ zalaczane klikniecem w item
2711    //hideSubList(true);  //powtorzenie --trzeba drugi raz                       /
2712    //if (runQuiz(lastSet ? lastSet : true)) {  //resolveDetails --> restartQuiz(set) --> runQuiz(set)
2713    runQuiz(lastSet ? lastSet : true, 1); //) {  //resolveDetails --> restartQuiz(set) --> runQuiz(set)
2714      //switchMode(0);
2715    //}
2716    //restart();
2717  }
2718  else //TRYB TESTU - odslon wszystkie detale
2719  if (resolved || au_play(5) && (DEBUG_MODE || confirm(confirm_resolve+"\n > "+resolve_warning))) { //to tylko gdy resolved != 1  //POJEDYNCZE RESOLVED ALBO POTWIERDZENIE DO RESOLVED ==>FULL RESOLVED
2720  console.log("<<<<<<5");
2721    //console.log("---------------------------"); 
2722    autolos = false;
2723    prepared = false;
2724    /*shutIt(); pic.preload();*/
2725    resolved = 1; //15.10
2726    //switchMode(1); //koment NEW 2020
2727    runQuiz(true, 2);
2728  }
2729  
2730  if (!mobile) {
2731    if (DEBUG_MODE)
2732      debugSwitch = false;
2733    
2734    if (!(DEBUG_MODE && set)) {
2735      /* console.log("::1"); */
2736      switchMode();  
2737    }
2738    waitMenuOut();
2739  }
2740}
2741
2742function switchDebug() {
2743    timersStop();
2744    /* hideSubList(true); */
2745    debugbox.style.display = (DEBUG_MODE = !DEBUG_MODE) ? "block" : "none";
2746    console.log("---------------------------"); 
2747    console.log("f switchdebug");
2748    prepared = false;
2749    /* if (DEBUG_MODE)  */debModSwitch = true;
2750    if (!resolved) {
2751      /* au_play(0); */
2752      //resolveBones();   //pozbyc sie migniecia kosci
2753      if (!setbag.length) { // && setbag.indexOf(lastBone) == -1) {
2754        console.log(">>details bag empty >> preparing set");
2755        resolved = 1;
2756        //lastDetidx = detail_nr.indexOf(lastDetail); // detnum = Object.keys(bones[bone]).sort(function(a, b){return a-b});
2757        runQuiz(true, 2);   //NEW 2020 02.21
2758      }
2759      resolveBones();
2760      /* debModSwitch = false; */
2761      tryDebug(1);
2762    }
2763    else {
2764      //resolved = resolved == 2 ? /* (currentBone("set") ? 1 : 0) */1 : 0;
2765      //resolved = 0;
2766      if (resolved == 2) {
2767        //debModSwitch = false;
2768        // tryDebug();
2769        runQuiz(true, 2);
2770        tryDebug(1);
2771      }
2772      else {
2773        resolved = 0;
2774        runQuiz(true, 2);
2775      }
2776    }
2777    /* if (DEBUG_MODE)  */debModSwitch = false;
2778    au_play(0);
2779    switchMode(); 
2780
2781    waitMenuOut();
2782}
2783
2784function switchMode(/* , mod = 0 */) {  //resolved == 2 new 26.11
2785  console.log("f switchmode"); 
2786  var qset = d.getElementsByClassName("addon")[0];
2787  var dmod = d.getElementsByClassName("addon")[1];
2788  
2789  HTMLElement.prototype.modifyMenu = function (str, on = 0, full = 0) {
2790    this.title = (on ? turn_off : turn_on)+" "+str;
2791    if (full) this.innerHTML = this.innerHTML.replace(/^[^:]+/,str);
2792    var trigger = this.getElementsByTagName("span")[0];
2793    trigger.style.color = (on ? "#6a957c" : "#9e7961");
2794    trigger.textContent = (on ? lng_on : lng_off);
2795  }
2796  var on = (DEBUG_MODE && currentBone("set") || !DEBUG_MODE && (currentBone("set") || (!currentBone("set")/* !DETAILSETS */ && resolved) ? 1 : 0))/* set_view mod_menu[mod] */
2797  qset.modifyMenu(DEBUG_MODE ? set_view : mod_menu[0], on, ALLOW_DEBG);
2798  dmod.modifyMenu(mod_menu[1], DEBUG_MODE);
2799}
2800
2801function waitMenuOut() {
2802  var menu = d.getElementById("menulist");
2803  if (!menu.onmouseout) 
2804    /* if (DEBUG_MODE) */ {
2805      menu.onmouseout = function(e) {
2806        var x = event.clientX, y = event.clientY;
2807        var element = d.elementFromPoint(x, y);
2808        if (element.id != "item" && !element.hasClass("label") && !element.hasClass("arrow")) {
2809          hideSubList(true);
2810          menu.onmouseout = null;
2811        }
2812        else if (element.id == "item" && element.hasClass("lvl2"))
2813          menu.onmouseout = null;
2814      }
2815    }
2816    /* else
2817      menu.onmouseout = null; */
2818}
2819
2820function shuffle(array) {
2821  var currentIndex = array.length, temporaryValue, randomIndex;
2822  while (0 !== currentIndex) {
2823    randomIndex = Math.floor(Math.random() * currentIndex);
2824    currentIndex -= 1;
2825
2826    temporaryValue = array[currentIndex];
2827    array[currentIndex] = array[randomIndex];
2828    array[randomIndex] = temporaryValue;
2829  }
2830  return array;
2831}
2832
2833function initializeAu() {
2834  fu = new Audio('au/no.mp3');
2835  ee = new Audio('au/ee.mp3');
2836  ok = new Audio('au/ok.mp3');
2837  ef = new Audio('au/effect.mp3');
2838  sl = new Audio('au/slide.mp3');
2839  bt = [];
2840  
2841  for (var k = 0; k < 5; k++) {
2842    bt.push(new Audio('au/click'+k+'.mp3'));
2843  }
2844}
2845
2846function au_play(nr) {
2847  if (!snd) return;
2848  console.log(nr == 6 ? "♬" : nr == 5 ? "♫" : "♪".repeat(nr+1)); //♪♩♬♫
2849  var promise = (nr == 6 ? sl.play() : nr == 5 ? ef.play() : bt[nr].play());
2850
2851  if (promise !== undefined) {
2852      promise.then(_ => {
2853          // Autoplay started!
2854      }).catch(error => {
2855          // Autoplay was prevented.
2856          // Show a "Play" button so that user can start playback.
2857      });
2858  }
2859  
2860  return true; //s1w_
2861}
2862
2863function initMenu(lvls) {
2864//menu lista jako parametr
2865
2866  for (var lvl = 1; lvl <= lvls; lvl++) {
2867    //console.log("LVL :: "+lvl);
2868    var lvl_group = d.getElementsByClassName("lvl"+lvl);
2869//    if (!lvl_group) continue;
2870    //dla wszystkich elementow danego poziomu
2871    for (var item_ = 0; item_ < lvl_group.length; item_++) {
2872      var item = lvl_group[item_].innerHTML;
2873      //console.log("ITEM:: "+item);
2874      //console.log(lvl_group[item_]);
2875      lvl_group[item_].onmouseover = function() {
2876        au_play(0); //bt[0].play();     
2877        var l = /lvl(\d)/g.exec(this.className)[1]; //this.className.match(/(?<=lvl)\d/g)[0];
2878        var s = /sub(\d)/g.exec(this.className)[1]; //this.className.match(/(?<=sub)\d/g)[0];
2879        var p = /psb(\d)/g.exec(this.className); if (p) p = p[1]; else p = 0; //this.className.match(/(?<=psb)\d/g); 
2880        var n = this.className.substr(-1, 1);
2881
2882        if (l < 3 && !this.classList.contains('active')) { 
2883          this.className = "active "+this.className; //if contains
2884          this.getElementsByClassName('label')[0].classList.add('offset');
2885          this.getElementsByTagName('span')[0].classList.add('arrow');
2886          if (isFirefox)
2887            this.getElementsByTagName('span')[0].classList.add('ff');               
2888        }
2889        /*
2890        try {
2891          var p = this.className.match(/(?<=psb)\d/g)[0];
2892          console.log("setting p = "+p);
2893        } catch(e) { }
2894        */
2895/*
2896          '<div id="sublist" class="sublista lv-2 pl-0 sl-'+(i+1)+'">';
2897          menulist += '<div id="item" class="lvl2 sub'+(i+1)+' it'+(j+1)+'"><div class="label">'+grupa[lng][grupy[i]][j]+'<span style="display:none">&nbsp;⊳</span></div></div>';
2898
2899   ist += '<div id="sublist" class="sublista lv-3 pl-'+(i+1)+' sl-'+(j+1)+'">';
2900          menulist += '<div id="item" class="lvl3 psb'+(i+1)+' sub'+(j+1)+' it'+(k+1)+'"><div>'+podgr[lng][grupa[lng][grupy[i]][j]][k].split(',')[1]+'</div><span /></div>';
2901        lv-3 == lvl3   pl- = psb   sl- == sub
2902*/        /*
2903    var lvl = sublist[i].className.match(/(?<=lv-)\d/g)[0];
2904    var sub = sublist[i].className.match(/(?<=sl-)\d/g)[0];
2905    var psb = sublist[i].className.match(/(?<=pl-)\d/g)[0];    
2906                     lvl sub psb   lv- sl- pl- */
2907        var sublist = d.getElementsByClassName("sublista lv-"+l+" pl-"+p+" sl-"+s); 
2908        if (sublist.length)
2909          breakInterval(sublist[0]/*, ""+l+s+p*/);
2910
2911        Array.from(d.getElementsByClassName("sublista lv-"+(Number(l)+2))).forEach(sublist => { 
2912          sublist.classList.remove("show"); 
2913        });             
2914          
2915          //lastitem = menuitem;
2916        menuitem = l+","+s+","+n;
2917        //console.log("menu "+this.className);
2918        showSubList(++l, n, s);
2919      }
2920      lvl_group[item_].onmouseout = function() {
2921        //d.getElementById("arrow").classList.toggle("show"); //usunac dopiero po przejsciu do wczesniejszego
2922        menuitem = "";
2923        lastitem.push(this);
2924        
2925        
2926        //gdy menuitem null lub lvl show dwa razy wieksze od menuitem  //showup(sublist[i], 130, 0, true);
2927        
2928        setTimeout(function() { hideSubList(false, menuitem); }, 50); 
2929      }
2930      lvl_group[item_].onmouseup = function() {
2931        console.log("---------------------------");
2932        //hideSubList(true);
2933        runQuiz(this, resolved ? 4 : 0); //z tym mod juz sie zajebalem, ale uzywam do przeskoczenia do odblokowania wszystkich kosci jezeli resolved
2934      }
2935    } 
2936  }  
2937}
2938
2939function scrollbarVisible(gbody_) {
2940  //console.log(gbody_.scrollHeight); console.log(support.clientHeight);
2941  return gbody_.scrollHeight > support.clientHeight;
2942}    
2943
2944function keepSupportPos() {
2945  if (box_on) return;
2946  var box = support.getBoundingClientRect();
2947  support.style.bottom = ""+(12-box.height)+"px";
2948}
2949
2950/*
2951function loadScript( url, callback ) {
2952  var script = document.createElement("script")
2953  script.type = "text/javascript";
2954  script.charset = "UTF-8";
2955  if(script.readyState) {  // only required for IE <9
2956    script.onreadystatechange = function() {
2957      if ( script.readyState === "loaded" || script.readyState === "complete" ) {
2958        script.onreadystatechange = null;
2959        callback();
2960      }
2961    };
2962  } else {  //Others
2963    script.onload = function() {
2964      callback();
2965    };
2966  }
2967
2968  script.src = url;
2969  //document.getElementsByTagName( "head" )[0].appendChild( script );
2970  d.getElementsByClassName("statsy")[0].getElementsByTagName("div")[0].appendChild( script );
2971}
2972
2973loadScript("https://", function() {
2974  alert('script ready!'); 
2975});
2976*/
2977
2978function getCookies() {
2979  //eraseCookie("lang");
2980  var lang = getCookie('lang');
2981  if (SWITCH_MEM) {
2982    c_en = getCookie('en');
2983    c_la = getCookie('la');
2984    snd = getCookie('snd');
2985  }
2986  if (c_en === null) c_en = true;
2987  if (c_la === null) c_la = true;  
2988  if (snd === null) {
2989    if (SWITCH_MEM)
2990    setCookie('snd',true, 730);
2991    snd = true; 
2992  }
2993
2994  if (!lang) {
2995    var locale = navigator.userLanguage;
2996    if (!locale) locale = navigator.language;
2997    if (!locale) locale = navigator.browserLanguage
2998    if (!locale) locale = navigator.systemLanguage
2999    if (locale) {
3000      locale = locale.substr(0, 2).toLowerCase();
3001      if (langs.indexOf(locale) != -1) current_lang = locale;
3002    }    
3003    setCookie('lang', current_lang, 730);
3004    setCookie('en',true,SWITCH_MEM ? 730 : -1);
3005    setCookie('la',true,SWITCH_MEM ? 730 : -1);
3006    lang = current_lang;
3007    /* if (SWITCH_MEM) {
3008      c_en = true;
3009      c_la = true;
3010    } */
3011  }
3012  if (SWITCH_MEM) {
3013    if (!c_en) { eng = c_en = false; }
3014    if (!c_la) { lat = c_la = false; }
3015  }
3016  
3017  setLang(lang, true);  
3018  d.getElementById("flag").style.visibility = ""; 
3019  if (!mobile && !switche.hasClass("hide"))
3020    setTimeout(function() { switche.style.display = ""; switche.style.opacity = "0.0"; }, 100);
3021  d.getElementById("angielski").checked = c_en;
3022  d.getElementById("lacina").checked = c_la;  
3023  d.getElementById("dzwiek").checked = snd;      
3024}
3025
3026function initGuestBox(lang, init = 0) {
3027  gbook = d.getElementsByClassName("book")[0].contentWindow;
3028  gback = d.getElementsByClassName("back")[0].contentWindow;
3029  gback.location.href = "https://siwego.net/kosci/support/header.php?lang="+lang;
3030  var n = 0;
3031  var reloading = false;
3032  var checkBack = setInterval(function(){  
3033    if (gback.document.readyState !== 'complete')
3034      reloading = true;
3035    if (n++ >= 100 || (reloading && gback.document.readyState === 'complete')) {
3036      clearInterval(checkBack);
3037      var hrefs = gback.document.getElementsByTagName("a");
3038      //console.log(gback.document.readyState);
3039      Array.from(hrefs).forEach(link => {
3040        link.removeAttribute("href"); //.href = "#";
3041      });
3042    }
3043  }, 10);
3044
3045  if (init || gbook.location.href.includes("add.php"))
3046    gbook.location.href = "https://siwego.net/kosci/support/list.php?page=1&order=asc&lang="+lang;
3047  else
3048    gbook.location.href = gbook.location.href.replace(/(lang=)[a-z]+/i, '$1'+lang);
3049
3050  n = 0;
3051  reloading = false;
3052  var checkBook = setInterval(function(){  
3053    if (gbook.document.readyState !== 'complete')
3054      reloading = true;
3055    if (n++ >= 100 || (reloading && gbook.document.readyState === 'complete')) {
3056      clearInterval(checkBook);
3057      //console.log(gbook.document.readyState);
3058      /* var hrefs = gbook.document.getElementsByTagName("a");
3059      Array.from(hrefs).forEach(link => {
3060        if (link.href.includes(".php"))
3061          link.href = link.href+(link.href.includes("?") ? "&" : "?")+"lang="+lang;
3062      }); */
3063      setTimeout(function() { gbook.onclick = gclick; }, 1000);   
3064    }
3065  }, 10);
3066}
3067
3068function init() {
3069
3070  qarea = d.getElementsByClassName("quizarea")[0];
3071  buttony = d.getElementsByClassName("buttony")[0];
3072  inputy = d.getElementsByClassName("inputy")[0];
3073  switche = d.getElementsByClassName("switches")[0];
3074  //menu = d.getElementsByClassName("lvl1");
3075  menubtn = d.getElementById("menu");
3076  losowanie = d.getElementById("licznik");
3077  quiztxt = d.getElementById("quiztxt");
3078  descbox = d.getElementById("detailset");
3079  wyniki = d.getElementById("wynik");
3080  quizpic = pic = d.getElementById("quizpic");
3081  //pic.preload();
3082  pic.ondragstart = function() { return false; };
3083
3084  
3085  if (isFirefox) {
3086    quiztxt.addClass("ff");
3087    quiztxt.parentElement.style.height = "15px";
3088  }
3089  
3090  if (ALLOW_DEBG) {
3091    console.log("RUNNING DEBUG MODE");
3092    debugbox = d.getElementById("debug");
3093    debug = debugbox.getElementsByTagName("span")[0];
3094    detnr = debugbox.getElementsByTagName("span")[1];
3095    debug.onclick = function(e) {
3096      var /*n = lastDetidx,*/ tag, mods, side, check = debugbox.getElementsByTagName("input");
3097      var set = currentBone("set") ? 1 : 0;
3098      if (set) {
3099        /*n = lastDetidx;*/ mods = ""; tag = "set";
3100      }
3101      else { /*n = 0;*/ tag = "d"; 
3102        side = detail_side[1][lastDetidx] + (detail_side[0][lastDetidx] != detail_side[1][lastDetidx] ? detail_side[0][lastDetidx] : ""); //(check[1].checked ? "l" : "r")
3103        mods = 'side="'+side+(!check[2].disabled ? '" wrap="'+(check[2].checked ? "1" : "0")+'"' : '"');
3104      }
3105      
3106      var copy = "    <"+tag+"x>"+detail_x[set][lastDetidx]+"</"+tag+"x>\n    <"+tag+"y>"+detail_y[set][lastDetidx]+"</"+tag+"y>"+mods;
3107
3108      console.log("---------------------------");    
3109      console.log("copied :::: ----> "+detail_nr[lastDetidx])
3110      
3111      navigator.clipboard.writeText(copy).then(
3112        function()    { alert('copied');   }, 
3113        function(err) { alert('copy error!');
3114      });      
3115
3116    }
3117    var check = debugbox.getElementsByTagName("input");
3118    check[0].onclick = function(e) {
3119      //if (resolved == 2 && !debModSwitch) console.log("---------------------------");    
3120      var check = debugbox.getElementsByTagName("input");
3121      debugSwitch = true;
3122      //console.log("DS <--- "+debugSwitch);
3123      if (lastDetidx == null)
3124        lastDetidx = detail_nr.indexOf(lastDetail);
3125        
3126      if (resolved == 2) {
3127        resolveBones(currentBone("base")); //GOTO :r1
3128        /* console.log("::4"); */
3129        switchMode();        
3130      }
3131      else 
3132        switchDetails();
3133
3134      var set = currentBone("set") ? 1 : 0;
3135      debug.innerHTML = "X:"+detail_x[set][lastDetidx]+"  Y:"+detail_y[set][lastDetidx];
3136      //debugSwitch = false;
3137      //console.log("DS <--- "+debugSwitch);
3138      //tryDebug(); //debugbox.style.display = "block";
3139      //draggable(lastDetail, n);
3140    }
3141    check[1].onclick = function(e) {
3142      //resolved == 2 ? (lastDetidx ? lastDetidx : detail_nr.indexOf(lastDetail)) : 0
3143/*       if (lastDetidx == null)
3144        lastDetidx = detail_nr.indexOf(lastDetail); */
3145
3146      var set = currentBone("set") ? 1 : 0;
3147      var check = debugbox.getElementsByTagName("input");
3148        
3149      detail_side[set][lastDetidx] = (e.target.checked) ? "l" : "r";
3150      
3151      if (set || check[2].checked) {
3152        var all_details = descbox.getElementsByClassName("detal");
3153        var detail_rect = all_details[set ? lastDetidx : 0].getBoundingClientRect();
3154        detail_x[set][lastDetidx] += ((e.target.checked) ? 1 : -1) * Math.ceil((detail_rect.width+1)/10)*10;
3155      }
3156      
3157      updDetail();
3158      tryDebug();
3159    }
3160    check[2].onclick = function(e) {    
3161      detail_wrap[lastDetidx] = (e.target.checked) ? "1" : "0";
3162
3163      updDetail();
3164      tryDebug();
3165    }
3166  }
3167
3168  /* euh-e info */
3169/*   var info = getCookie('info');
3170  if (!info) {
3171    setCookie('info', 1, 730);
3172    setTimeout(function() { 
3173      alert("Program powstał w ramach pracy na zaliczenie Anatomia EUH-E\n"
3174           +"kierunek RATMED R1D2019\n[przewidziany jest rozwój programu o dodatkowe układy]\n\n"
3175           +"prowadzący dr hab. Adam Kosiński\n"
3176           +"wykonał Michał Sztolcman 18593 gr.I");
3177    }, 1000);   
3178  } */
3179    
3180  getCookies();
3181  initializeAu();
3182  addEvents();
3183  importBones();
3184  createMenu();
3185  initMenu(3);
3186  
3187  
3188  //window.addEventListener('contextmenu', event => event.preventDefault());
3189  window.addEventListener('contextmenu', function(e) {
3190    updateActives();
3191    hideSubList(true, true);
3192    langMenu(1);
3193    menubtn.removeClass("pressed");
3194    if (!mobile) d.getElementById("inpucik").focus();   
3195    e.preventDefault();
3196  }, false);
3197
3198
3199  window.onclick = function(event) {
3200    if (!event.target.id || !("langflagdash".includes(event.target.id))) {
3201      langMenu(1);
3202    }
3203    if (!event.target.matches('.menubtn') && d.getElementById("menulist").classList.contains("show") && event.target.id != "item" && !event.target.classList.contains("label")) {
3204      //var i;
3205      //var menulist = d.getElementById("menulist").classList.contains("show");      // to wyjebac, czemu klik na window odpala hidesublist
3206      //if (menulist.classList.contains("show")) {
3207        updateActives();
3208      if (/* !debugSwitch && */!DEBUG_MODE || !event.target.hasClass("fswitch") )
3209      hideSubList(true, true);
3210        menubtn.removeClass("pressed");   //to to samo co classList.remove("..
3211      //}
3212
3213      if (!mobile) d.getElementById("inpucik").focus();    
3214    }
3215
3216    if (box_on && !event.target.matches('.menu'))
3217      support.click();
3218
3219    if (slided) {
3220      if (d.createEvent)
3221        qarea.dispatchEvent(new Event('mouseover'));
3222      else
3223        qarea.fireEvent("onmouseover", event);
3224    }
3225  }
3226  
3227
3228  /* GUESTBOOK */
3229  gclick = function(event) {
3230    /* d.getElementsByClassName("back")[0].contentWindow.document.body.opacity = "0.0"; */
3231    var elem = event.target.parentElement.nodeName;
3232    if (elem != 'LI' && elem != 'CLICK-X')
3233      return;
3234    var gback, gfore;
3235    var n = 0;
3236    var reloading = false;
3237    au_play(0); //bt[0].play();
3238    
3239    var checkSlider = setInterval(function(){
3240      //console.log(gbook.document.readyState);
3241      if (gbook.document.readyState !== 'complete' && !reloading)
3242      {
3243        reloading = true;
3244        gback = d.getElementsByClassName("back")[0];
3245        gfore = d.getElementsByClassName("fore")[0];
3246        //if (isChrome && !isOpera)
3247          if (gback.style.display != "block") {
3248            gback.style.display = "block";
3249            gfore.style.opacity = "1.0";
3250          }
3251      }
3252        //console.log("n("+n+") | readyState == "+gbook.document.readyState);
3253      else if (n++ >= 100 || (reloading && gbook.document.readyState !== 'loading')) {
3254        /* gbook.document.getElementsByTagName('nav')[0].style.opacity = "0.0"; */
3255        clearInterval(checkSlider);
3256        var gbody = gbook.document.getElementsByTagName('body')[0];  
3257        //gbook.document.getElementsByTagName('body')[0].style.display = 'none';
3258        //console.log("is scroll visible ?? "+scrollbarVisible(gbody));
3259        if (!scrollbarVisible(gbody)) {
3260          if (window.innerWidth > 650)
3261            gbody.style.marginRight = "18px";
3262        }
3263        //if (isChrome && !isOpera) {
3264          gback.style.display = "none";
3265          showup(gfore, -0.0, 8);
3266        //}
3267        gbook.onclick = gclick;
3268      }
3269    }, 10);
3270  }  
3271 
3272  /* SUPPORT BOX */
3273  support = d.getElementById("support");
3274  initGuestBox(current_lang, 1);
3275  keepSupportPos();
3276  
3277  support.style.opacity = "0.9";
3278  support.style.visibility = "visible";
3279  
3280  support.onclick = function(e) {
3281    if (sliding) return;
3282    sliding = true;
3283    var box = support.getBoundingClientRect();
3284    var off = parseInt(support.style.bottom, 10);
3285    var up  = off == 0 ? 0 : 1;
3286    if (snd) {
3287      if (up) sl.play();
3288      else au_play(0); //bt[0].play();
3289    }
3290    support.style.opacity = "0.95";
3291    slider2 = setInterval(function(){
3292      off += up ? 12 : -15;
3293      support.style.bottom = ""+off+"px";
3294      if (up && off >= 0 || off <= 12-box.height) { 
3295        clearInterval(slider2);
3296        support.style.bottom = up ? "0px" : ""+(12-box.height)+"px"; 
3297        support.style.opacity = up ? "1.0" : "0.9";
3298        if (box_on = up ? 1 : 0)
3299          support.addClass("bon");
3300        else
3301          support.removeClass("bon");
3302        sliding = false;
3303      }
3304    }, 1);
3305  }
3306  
3307  /* STATSY BOX */
3308  darr = d.getElementById("remark-arrow");
3309  rarrtimer = setInterval(function(){
3310    if (doff = !doff && !darr.hasClass("aoff")) {
3311      showup(darr, 0.7, 36, 0, true);
3312      setTimeout(function() {  
3313        showup(darr, 0.7, 36, 0, true);
3314      }, 900);
3315    }
3316    else if (darr.hasClass("aoff"))
3317      clearInterval(rarrtimer);
3318  }, 6000);
3319  statsy = d.getElementById("statsy");
3320  statsy.style.opacity = "0.7";
3321  statsy.style.boxShadow = "0px 0px 15px rgba(0,0,0,0.08)";
3322  statsy.onmouseover = function(e) {
3323    if (sliding || slided) return;
3324    sliding = true;
3325    darr.addClass("aoff");
3326    var off = -145;
3327    slider = setInterval(function(){
3328      off += 3;
3329      statsy.style.left = ""+off+"px";
3330      if (off >
3330= 0) { statsy.style.left = "0px";  statsy.style.opacity = "0.95"; clearInterval(slider);
3331        qarea.onmouseover = function(e) {
3332          if (sliding) return;
3333          sliding = true;
3334          statsy.style.opacity = "0.7"; 
3335          var off = 0;
3336          slider = setInterval(function(){
3337            off -= 4;
3338            statsy.style.left = ""+off+"px";
3339            if (off <= -145) { statsy.style.left = "-144px"; clearInterval(slider); qarea.onmouseover = null; /* darr.removeClass("aoff"); */ slided = false; sliding = false; }
3340          }, 1);
3341        }; slided = true; sliding = false; }
3342    }, 1);
3343  }
3344  
3345  setTimeout(function() { 
3346    statsy.getElementsByTagName("iframe")[0].contentWindow.location.href = "staty.html";
3347  }, 0);  
3348
3349  /*  
3350  setTimeout(function() {  
3351    var srect = statsy.getBoundingClientRect();
3352    var ddd = d.getElementsByClassName("statbot")[0].style.top = srect.height;
3353  }, 200);
3354  */
3355  qarea.onclick = function (event) {
3356    if (inputy.style.display != "none" /* visibility == "" */)
3357      if (!(event.target.id == "menu" && menubtn.hasClass("pressed")) && event.target.id != "item")
3358        if (!mobile) d.getElementById("inpucik").focus();
3359  }
3360  
3361  lastDetail = detale[lastBone = kosci[0]][0];
3362  console.log("5>  lastBone <--- "+lastBone);
3363  //newBone = 1;
3364 
3365  if (DEBUG_MODE) {
3366    //switchMode(1);
3367    //runQuiz(true, 2);  
3368    switchDetails(1);
3369  }
3370  else
3371    showBone();
3372}
3373
3374function tryDebug(force = false) {
3375  if (!DEBUG_MODE || (debModSwitch && !force)) return;
3376  console.log("f trydebug");
3377
3378  var check = debugbox.getElementsByTagName("input");
3379  var set = currentBone("set") ? 1 : 0;
3380  
3381  if (lastDetidx == null)
3382    lastDetidx = detail_nr.indexOf(lastDetail);
3383        
3384  if (set) {
3385    //if (debugbox.style.display == "none") {
3386      
3387      check[0].disabled = false;
3388      check[0].checked = (resolved == 2) ? true : false;
3389      check[2].disabled = true;
3390      
3391      //if (setbag.indexOf(lastBone) == -1) {
3392      //  check[0].checked = false;
3393      //  check[0].disabled = true;
3394      //}
3395    //}
3396    //if (lastDetidx != null) {
3397    
3398      debugbox.style.display = "block";
3399      //var check = debugbox.getElementsByTagName("input");
3400      //check[0].disabled = false;
3401      //check[0].checked = true;
3402      /*
3403      var d = descbox.getElementsByClassName("detal")[lastDetidx];
3404      console.log(d);      
3405      markDetail(d);
3406      console.log("--timeouting--");   
3407      setTimeout(function() { var d = descbox.getElementsByClassName("detal")[lastDetidx]; console.log(d); markDetail(d); }, 50);
3408      /*
3409      var d;
3410      var off = 35
3411      waitdetail = setInterval(function(){
3412        off -= 5;
3413        d = descbox.getElementsByClassName("detal")[lastDetidx];
3414        console.log("checking details "+off+"  -----------------");
3415        console.log(d.getElementsByClassName("resolved").length);
3416        console.log(d);
3417        if (d.getElementsByClassName("resolved") || off <= 0) { clearInterval(waitdetail); markDetail(d); }
3418      }, 1);      
3419      */
3420
3421      detnr.innerHTML = lastDetail; //detail_nr[0];
3422      debug.innerHTML = "X:"+detail_x[set][lastDetidx]+"  Y:"+detail_y[set][lastDetidx];
3423    //}
3424      var det = descbox.getElementsByClassName("detal")[lastDetidx];
3425      //console.log(det.innerHTML.length);  //<<----- jest tu lag, interwal czeka na detal do zamarkowania
3426      //setTimeout(function() { console.log(det.innerHTML.length); markDetail(det); }, 50);
3427      var off = 10, i = 0, len;
3428      waitdetail = setInterval(function(){
3429        i += 1; len = det.innerHTML.length;
3430        //console.log("checking details ("+i+") == "+len);
3431        //console.log(det.innerHTML);
3432        if (det.innerHTML.length || i >= off) { clearInterval(waitdetail); markDetail(det); console.log("> "+det.id+(!len ? " NOT" : "")+" marked after "+i+" intervals"); }
3433      }, 40);  
3434      
3435    
3436    debugbox.style.display = "block";
3437  }
3438  else {
3439  
3440    //lastD = Number(debug.className); 
3441    detnr.innerHTML = lastDetail; //detail_nr[0];
3442    debug.innerHTML = "X:"+detail_x[set][lastDetidx]+"  Y:"+detail_y[set][lastDetidx];
3443    
3444    //debug.className = n; 
3445    var check = debugbox.getElementsByTagName("input"); //----------------------------------------------------
3446    //console.log("setbag :: "+setbag.indexOf(lastBone));
3447    //console.log(setbag);
3448    check[0].checked = false;
3449    check[0].disabled = (setbag.indexOf(lastBone) == -1);
3450    check[2].disabled = false;
3451    debugbox.style.display = "block";
3452    /*
3453    var det = descbox.getElementsByClassName("detal")[0];
3454    if (d.createEvent) {
3455      det.dispatchEvent(new Event('mousedown'));
3456      det.dispatchEvent(new Event('mouseup'));
3457    }
3458    else {
3459      det.fireEvent("onmousedown", event); // Internet Explorer (I think)
3460      det.fireEvent("onmouseup", event);
3461    }
3462    */
3463  }
3464                       //resolved == 2 ? (lastDetidx ? lastDetidx : detail_nr.indexOf(lastDetail)) : 0
3465  check[1].checked = (detail_side[set][lastDetidx] == "l") ? true : false;
3466    
3467  if (check[1].checked)
3468    check[2].disabled = true;
3469
3470  check[2].checked = (detail_wrap[lastDetidx] == "0") ? false : true;
3471
3472}
3473/*
3474function tryDebug() {
3475  if (!DEBUG_MODE) return;
3476  
3477  var check = debugbox.getElementsByTagName("input");
3478  if (!currentBone("set")) {
3479
3480  //lastD = Number(debug.className); 
3481    detnr.innerHTML = lastDetail; //detail_nr[0];
3482    debug.innerHTML = "X:"+detail_x[0]+"  Y:"+detail_y[0];
3483    
3484    //debug.className = n; 
3485    if (setbag.indexOf(lastBone) == -1) {
3486      check[0].checked = false;
3487      check[0].disabled = true;
3488    }
3489    debugbox.style.display = "block";
3490  }
3491  else 
3492  if (resolved == 2 && lastD) {
3493    if (!lastDetail) lastD = 
3494    check[0].disabled = false; 
3495    check[0].checked = true;
3496    debug.innerHTML = "X:"+detail_x[lastD]+"  Y:"+detail_y[lastD];
3497    debugbox.style.display = "block";
3498  }
3499  console.log("lastD  :::  "+lastD);
3500}
3501*/
3502
3503function timersStop() {
3504  //console.log("f timersstop");
3505  losowanie.stop();
3506  clearInterval(alerttimer);
3507//clearInterval(showtimer);
3508  Object.keys(showtimer).forEach(timer => { 
3509    //console.log("---> clearing "+timer);
3510    clearInterval(timer);
3511  });
3512}
3513
3514function przegladanie() {
3515  return (inputy.style.display == "none" /* visibility == "hidden" */ && buttony.style.display == "none" && descbox.style.display == "block");
3516}
3517  
3518  
3519function losuj(sound = true /*, prepfun = prepareNext*/) {
3520  console.log("---------------------------");
3521  console.log("f losuj  prepared = "+prepared);//  (reduced "+reduced+", prepared "+prepared+")");
3522  //setTimeout(function() { descbox.style.opacity = "0.0"; }, 0);
3523  timersStop(); //setTimeout(function() { timersStop() }, 300);
3524  autolos = true; //czy to z licznika pieprzy
3525  //disrupted = false;
3526  if (sound)
3527    au_play(3); //bt[3].play();
3528  if (revoked) { reduce(); revoked = false; }
3529  if (kosci.length == 0)
3530    if (!confirmEnd())
3531      return;
3532  shutIt();
3533  pic.preload();
3534  //if (prepfun) prepfun(reduce);
3535  if (!prepared) prepareNext(false, 1)  //NEW 2020!!?! PO PUDLE W !AUTOLOS BYLA PREPAROWANA, ALE CHUJOWO
3536  prepared = false;
3537  //prepareNext(reduce); //przegladanie()
3538  //console.log("current bone: "+currentBone("name")+"  details: "+currentBone("details"));
3539  if (resolved) prepareBag();
3540  showBone();  //tu upewnic sie, czy kosc sie zmienila -- buttonsOff/inputsOff? (inaczej !newBone)
3541  /* posChoices(); */
3542  //setTimeout(function() { posChoices(); }, 300); 
3543  updScore(); //to tylko dla stacktxt
3544}
3545
3546function nextDetail() {
3547  console.log("---------------------------");
3548  tabbing = true; //potrzebne tylko dla checkLastDetail()
3549  if (!currentBone("set")) au_play(2); //bt[2].play();
3550  if (!mobile) autolos = false;
3551  //if (losowanie.innerHTML != "") revokeDetail(); //{ disrupted = true; console.log("disrupting"); } //potrzebne??? -- teraz nie trzeba przywracac kosci, bo lastbone bedzie z warunkiem czy reduced
3552  //if (!kosci.length) revokeDetail(false);  //10.10
3553  //else disrupted = false;
3554  //if (losowanie.innerHTML != "") disrupting = true;  //new 2020.03
3555  //else disrupting = false;
3556  prepared = false;
3557  timersStop();
3558  shutIt();
3559  tabDetail(1);
3560  //prepareNext(false); //!przegladanie() 
3561  console.log("f nextDetail  index "+index/* +"   "+currentBone("base")+"   lastBone "+lastBone */);
3562  showBone(!DEBUG_MODE || currentBone("set")); //currentBone("set") //DEBUG_MODE && currentBone("set") || !DEBUG_MODE
3563  if (mobile) posChoices();
3564  tabbing = false; 
3565}
3566
3567function prevDetail() {
3568  console.log("---------------------------");
3569  tabbing = true; 
3570  if (!currentBone("set")) au_play(2); //bt[2].play();
3571  if (!mobile) autolos = false;
3572  //if (losowanie.innerHTML != "") revokeDetail(); //{ disrupted = true; console.log("disrupting"); }  //potrzebne???
3573  //if (!kosci.length) revokeDetail(false);  //10.10
3574  //else disrupted = false;
3575  //if (losowanie.innerHTML != "") disrupting = true;  //new 2020.03
3576  //else disrupting = false;  
3577  prepared = false;
3578  timersStop();
3579  shutIt();
3580  //prepareNext(false); //!przegladanie()
3581  tabDetail(-1);
3582  console.log("f prevDetail  index "+index);
3583  showBone(!DEBUG_MODE || currentBone("set"));  //currentBone("set")  //DEBUG_MODE && currentBone("set") || !DEBUG_MODE
3584  if (mobile) posChoices();
3585  tabbing = false; 
3586  
3587}
3588
3589function boneMenu() {
3590  toggleList();
3591}

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.