misc/hats_js_anim.xhtml
changeset 15564 732b82f44c83
parent 15563 af4bcdbf2c8f
child 15565 ff58b2a18d85
equal deleted inserted replaced
15563:af4bcdbf2c8f 15564:732b82f44c83
     4 <!-- There is, at present, no official xsd for (X)HTML5. A pity. Usefulness would depend on the parser and extensions made by the site.  -->
     4 <!-- There is, at present, no official xsd for (X)HTML5. A pity. Usefulness would depend on the parser and extensions made by the site.  -->
     5     <title>Hedgewars Hats</title>
     5     <title>Hedgewars Hats</title>
     6 
     6 
     7     <style type="text/css">
     7     <style type="text/css">
     8 * {padding: 0; margin: 0; }
     8 * {padding: 0; margin: 0; }
     9 body 
     9 body
    10 {
    10 {
    11     background: url('//hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Themes/Nature/Sky.png') fixed no-repeat bottom left;
    11     background: url('https://hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Themes/Nature/Sky.png') fixed no-repeat bottom left;
    12     background-color: #0B203D;
    12     background-color: #0B203D;
    13     color: #FFD902;
    13     color: #FFD902;
    14     -moz-background-size: 200%;
    14     -moz-background-size: 200%;
    15     background-size: 100% 100%;
    15     background-size: 100% 100%;
    16     font-family: sans-serif;
    16     font-family: sans-serif;
    17 }
    17 }
    18 h1 { text-shadow: 0 0 2px white; color: black;}
    18 form, p
    19 a 
    19 {
       
    20     background-color: #0B203D;
       
    21     padding: 1em;
       
    22     margin: 1em;
       
    23     border-style: solid;
       
    24     border-radius: 5px;
       
    25     border-width: 2px;
       
    26     border-color: #FFD902;
       
    27 }
       
    28 h1 {
       
    29     text-shadow: 0 0 2px white;
       
    30     color: black;
       
    31     margin:10px;
       
    32 }
       
    33 a {
       
    34     color: #BFBED0;
       
    35     text-decoration: none;
       
    36 }
       
    37 .hat
    20 {
    38 {
    21     margin-top: 12px;
    39     margin-top: 12px;
    22     margin-left: 20px;
    40     margin-left: 20px;
    23     float: left;
    41     float: left;
    24     height: 32px;
    42     height: 32px;
    25     width: 32px;
    43     width: 32px;
    26     color: transparent;
    44     color: transparent;
    27     background-image: url("//hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Graphics/Hedgehog/Idle.png");
    45     background-image: url("https://hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Graphics/Hedgehog/Idle.png");
    28 }
    46 }
    29 .girder
    47 .girder
    30 {
    48 {
    31     width: 100%;
    49     width: 100%;
    32     height: 30px;
    50     height: 30px;
    33     clear: left;
    51     clear: left;
    34     background-image: url('//hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Themes/Nature/Girder.png');
    52     background-image: url('https://hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Themes/Nature/Girder.png');
    35     background-repeat: repeat-x;
    53     background-repeat: repeat-x;
    36 }
    54 }
    37 .hide { visibility: hidden; }
    55 .hide { visibility: hidden; }
    38 a div
    56 a div
    39 {
    57 {
    42     width: 32px;
    60     width: 32px;
    43 }
    61 }
    44     </style>
    62     </style>
    45     <script type="application/ecmascript">
    63     <script type="application/ecmascript">
    46 //<![CDATA[
    64 //<![CDATA[
    47 /* javascript version of a sprite sheet - this could be pretty trivially done in pure HTML, but maintenance
    65 var IS_LOCAL=false; // set to true to fetch hats locally. Useful for testing.
       
    66 var masks;
       
    67 if (IS_LOCAL) {
       
    68 /* JavaScript version of a sprite sheet - this could be pretty trivially done in pure HTML, but maintenance
    48 would be easier with a server-side portion. list of sprites could be gotten from server, but would require XSS whitelisting */
    69 would be easier with a server-side portion. list of sprites could be gotten from server, but would require XSS whitelisting */
    49 /*var masks = ['2001suit2', '2001suit', '4gsuif', 'AkuAku', 'android', 'angel', 'anzac', 'apple', 'ash', 'Balrog', 'banana', 'Bandit', 'bat', 'beaver', 'beefeater', 'Blanka', 'BlankaToothless', 'BlueCap', 'BlueHair', 'bobby2v', 'bobby', 'Bob', 'BrainSlugMouth', 'BrainSlug', 'britishpithhelmet', 'britmedic', 'britsapper', 'Bub', 'Bunny', 'bushhider', 'charlesdegaulle', 'charmander', 'chef', 'chikorita', 'Chunli', 'clown-copper', 'clown-crossed', 'clown', 'Coonskin3', 'Cororon', 'Cowboy', 'crown', 'cyborg', 'darthvader', 'Deer', 'desertgrenadier01', 'desertgrenadier02', 'desertgrenadier04', 'desertgrenadier05', 'desertgrenadierofficer', 'desertmedic', 'desertsapper1', 'desertsapper2', 'diglett', 'Disguise', 'Dragon', 'dwarf', 'eastertop', 'Elvis', 'Eva_00b', 'Eva_00y', 'Falcon', 'frenchwwigasmask', 'frenchwwihelmet', 'Gasmask', 'Geordi', 'germanwiimedichelmet', 'germanwwihelmetmustache', 'germanwwiipithhelmetdes', 'germanwwitankhelmet', 'Glasses', 'GreenCap', 'GreenHair', 'grenadier1', 'GreyHair', 'Guile', 'hedgehogk', 'HogInTheHat', 'hogpharoah', 'Honda', 'IndianChief', 'infernalhorns', 'InfernalHorns', 'Jason', 'jigglypuff', 'judo', 'junior', 'Ken', 'KirbyMask', 'kiss_criss', 'kiss_frehley', 'kiss_simmons', 'kiss_stanley', 'knight', 'Kululun', 'Ladle', 'lambda', 'Laminaria', 'laurel', 'lemon', 'link', 'lugia', 'Luigi', 'Mario', 'MegaHogX', 'metalband', 'mexicansunbrero', 'mickey_ears', 'Moose', 'mp3', 'mudkip', 'Mummy', 'naruto', 'NinjaFull', 'NinjaStraight', 'NinjaTriangle', 'OldMan', 'OrangeHair', 'orange', 'Pantsu', 'Pig', 'pikachu', 'PinkHair', 'pinksunhat', 'pirate_jack_bandana', 'pirate_jack', 'plainpith', 'Plunger', 'policecap', 'porkey', 'PrincessDaisy', 'PrincessPeach', 'Pumpkin_Hat', 'PurpleHair', 'quotecap', 'Rain', 'Rambo', 'rasta', 'RedCap', 'RedHair', 'RobinHood', 'royalguard', 'RSR', 'Ryu', 'Samurai', 'Samus', 'Santa', 'SauceBoatSilver', 'ShaggyYeti', 'sheep', 'ShortHair_Black', 'ShortHair_Brown', 'ShortHair_Grey', 'ShortHair_Red', 'ShortHair_Yellow', 'Skull', 'Sleepwalker', 'slowpoke', 'Sniper', 'Sonic', 'sovietcomrade2', 'sovietcomrade', 'SparkleSuperFun', 'SparkssHelmet', 'spartan', 'spcartman', 'spidey', 'spkenny', 'spkyle', 'spstan', 'squirtle', 'sth_AmyClassic', 'sth_Amy', 'sth_Eggman', 'sth_Knux', 'sth_Metal', 'sth_Shadow', 'sth_Sonic', 'sth_Super', 'sth_Tails', 'stormcloud', 'stormtrooper', 'StrawHatEyes', 'StrawHatFacial', 'StrawHat', 'Sunglasses', 'SunWukong', 'Teacup', 'Teapot', 'terminatorc', 'Terminator_Glasses', 'thug', 'Toad', 'tophats', 'touhou_chen', 'touhou_marisa', 'touhou_patchouli', 'touhou_remelia', 'touhou_suwako', 'touhou_yukari', 'trenchgrenadier1', 'trenchgrenadier2', 'trenchgrenadier3', 'ushanka', 'vampirichog', 'Vega', 'venom', 'Viking', 'voltorb', 'Wario', 'WhySoSerious', 'WizardHat', 'YellowCap', 'YellowHair', 'Zombi'];*/
    70 // Last updated: 1.0.0
    50 var masks = [];
    71 masks = ['4gsuif','AkuAku','android','angel','anzac','Bandit','barrelhider','bb_bob','bb_bub','bb_cororon','bb_kululun','beefeater','beefeaterhat','bishop','bobby','bobby2v','bubble','bushhider','cap_blue','cap_green','cap_junior','cap_red','cap_thinking','cap_yellow','car','chef','chuckl','clown','clown-copper','clown-crossed','constructor','Coonskin3','Cowboy','cratehider','crown','cyborg1','cyborg2','cyclops','Dan','Dauber','DayAndNight','Disguise','dish_Ladle','dish_SauceBoatSilver','dish_Teacup','dish_Teapot','doctor','Dragon','dwarf','eastertop','Einstein','Elvis','Eva_00b','Eva_00y','Evil','flag_french','flag_germany','flag_italy','flag_usa','footballhelmet','fr_apple','fr_banana','fr_lemon','fr_orange','fr_pumpkin','fr_tomato','Gasmask','Glasses','hair_blue','hair_green','hair_grey','hair_orange','hair_pink','hair_purple','hair_red','hair_yellow','HogInTheHat','hogpharoah','IndianChief','InfernalHorns','Jason','jester','Joker','judo','kiss_criss','kiss_frehley','kiss_simmons','kiss_stanley','knight','lambda','lambdahat','Laminaria','lamp','laurel','leprechaun','mechanicaltoy','MegaHogX','metalband','Meteorhelmet','mexicansunbrero','mickey_ears','Moustache','Moustache_glasses','mp3','Mummy','mv_Spidey','mv_Venom','naruto','NinjaFull','NinjaStraight','NinjaTriangle','noface','ntd_Falcon','ntd_Kirby','ntd_Link','ntd_Samus','nurse','nursehat','OldMan','Pantsu','pinksunhat','pirate_bandana','pirate_eyepatch','pirate_hat','pirate_jack','pirate_jack_bandana','Plunger',
       
    72 'poke_ash','poke_ash_hat','poke_charmander','poke_chikorita','poke_diglett','poke_jigglypuff','poke_lugia','poke_mudkip','poke_pikachu','poke_slowpoke','poke_squirtle','poke_voltorb','policecap','policegirl','punkman','quotecap','Rain','Rambo','RamboClean','rasta','RobinHood','royalguard','RSR','Samurai','Santa','scif_2001O','scif_2001Y','scif_BrainSlug','scif_BrainSlug2','scif_cosmonaut','scif_cyberpunk','scif_Geordi','scif_SparkssHelmet','scif_swDarthvader','scif_swStormtrooper','sf_balrog','sf_blanka','sf_blankatoothless','sf_chunli','sf_guile','sf_guile_hat','sf_honda','sf_ken','sf_ryu','sf_vega','sf_vega_hat','ShaggyYeti','ShortHair_Black','ShortHair_Brown','ShortHair_Grey','ShortHair_Red','ShortHair_Yellow','simple_green','simple_red','simple_yellow','Skull','Sleepwalker','sm_daisy','sm_luigi','sm_mario','sm_peach','sm_toad','sm_wario','Sniper','snorkel','snowhog','SparkleSuperFun','spartan','spcartman','spkenny','spkyle','spstan','sth_Amy','sth_AmyClassic','sth_Eggman','sth_Knux','sth_Metal','sth_Shadow','sth_Sonic','sth_SonicClassic','sth_Super','sth_Tails','stormcloud',
       
    73 'StrawHat','StrawHatEyes','StrawHatFacial','Sunglasses','SunWukong','swordsmensquire','TeamHeadband','TeamSoldier','TeamWheatley','Terminator_Glasses','tf_demoman','tf_scout','thug','thugclean','tiara','tophats','touhou_chen','touhou_marisa','touhou_patchouli','touhou_remelia','touhou_suwako','touhou_yukari','ushanka','vampirichog','vc_gakupo','vc_gumi','vc_kaito','vc_len','vc_luka','vc_meiko','vc_miku','vc_rin','Viking','war_airwarden02','war_airwarden03','war_americanww2helmet','war_britmedic','war_britpthhelmet','war_britsapper','war_desertgrenadier1','war_desertgrenadier2','war_desertgrenadier4','war_desertgrenadier5','war_desertmedic','war_desertofficer','war_desertsapper1','war_desertsapper2','war_frenchww1gasmask','war_frenchww1helmet','war_germanww1helmet2','war_germanww1tankhelm','war_germanww2medic','war_germanww2pith','war_grenadier1','war_plainpith','war_sovietcomrade1','war_sovietcomrade2','war_trenchfrench01','war_trenchfrench02','war_trenchgrenadier1','war_trenchgrenadier2','war_trenchgrenadier3','war_UNPeacekeeper01','war_UNPeacekeeper02','WhySoSerious','WizardHat','Zombi','zoo_Bat','zoo_Beaver','zoo_Bunny','zoo_chicken','zoo_crocodile','zoo_Deer','zoo_elephant','zoo_fish','zoo_frog','zoo_Hedgehog','zoo_Moose','zoo_octopus','zoo_Pig','zoo_Porkey','zoo_Sheep','zoo_snail','zoo_turtle'
       
    74 ,'NoHat','cap_team','hair_team','TeamTophat'
       
    75 ];
       
    76 }
       
    77 else
       
    78 {
       
    79 masks = [];
       
    80 }
       
    81 
    51 var themes = {
    82 var themes = {
       
    83 // Last updated: 1.0.0
       
    84 "Art":1,
       
    85 "Beach":1,
       
    86 "Bamboo":1,
       
    87 "Bath":1,
       
    88 //"Blox":0, //unused, has no Sky.png or Border.png
       
    89 "Brick":0,
       
    90 "Cake":0,
       
    91 "Castle":1,
    52 "Cave":1,
    92 "Cave":1,
       
    93 "City":1,
       
    94 "Cheese":0,
       
    95 "Christmas":1,
       
    96 "Compost":1,
       
    97 "CrazyMission":0,
       
    98 "Deepspace":0,
       
    99 "Desert":1,
       
   100 "EarthRise":0,
       
   101 "Eyes":0,
       
   102 "Freeway":0,
       
   103 "Fruit":1,
       
   104 "Halloween":1,
       
   105 "Hell":0,
       
   106 "Hoggywood":1,
       
   107 "Island":0,
       
   108 "Jungle":1,
    53 "Golf":1,
   109 "Golf":1,
       
   110 "Nature":1,
       
   111 "Olympics":1,
       
   112 "Planes":0,
       
   113 "Sheep":1,
       
   114 "Snow":1,
    54 "Stage":1,
   115 "Stage":1,
    55 "Island":0,
   116 "Underwater":1};
    56 "Eyes":0,
       
    57 "Deepspace":0,
       
    58 "Jungle":1,
       
    59 "Cake":0,
       
    60 "Compost":1,
       
    61 "Planes":0,
       
    62 "Olympics":1,
       
    63 "Bath":1,
       
    64 "Cheese":0,
       
    65 "Desert":1,
       
    66 "Christmas":1,
       
    67 "CrazyMission":0,
       
    68 "Sheep":1,
       
    69 "Brick":0,
       
    70 "Underwater":1,
       
    71 "City":1,
       
    72 "EarthRise":0,
       
    73 "Blox":0,
       
    74 "Hell":0,
       
    75 "Bamboo":1,
       
    76 "Freeway":0,
       
    77 "Nature":1,
       
    78 "Art":1,
       
    79 "Halloween":1,
       
    80 "Snow":1,
       
    81 "Castle":1};
       
    82 var girder;
   117 var girder;
    83 var animationInterval;
   118 var animationInterval;
    84 window.onload = function()
   119 
    85 {
   120 var staticMasks = [];
    86     var xml=new XMLHttpRequest();
   121 
    87     xml.open("GET", "/hedgewars/file/tip/share/hedgewars/Data/Graphics/Hats/", false);
   122 on_xml_loaded = function(ex)
    88     xml.send(null);
   123 {
    89     /*var resp = xml.responseXML; unfortunately not served as XHTML
   124     var resp = this.responseText;
    90     var a = resp.getElementsByTagName("a");
       
    91     for(var i=0;i<a.length;i++);
       
    92         if (/\.png/.test(a[0].href)) m.push(a[0].replace(/.png/,''));*/
       
    93 
       
    94     var resp = xml.responseText;
       
    95     var r = />([^<]*).png</g;
   125     var r = />([^<]*).png</g;
    96     var x;
   126     var x;
    97     while(x = r.exec(resp)) 
   127     while(x = r.exec(resp))
    98         if (!/NoHat|hair_team|cap_team|TeamTophat/.test(x[1])) // Exclude NoHat as uninteresting. hair_team, cap_team and TeamTophat as repetitive team hats
   128     {
    99             masks.push(x[1]);
   129         masks.push(x[1]);
   100 
   130     }
   101     var opt = document.createElement("option");
   131     on_hats_loaded();
   102     opt.appendChild(document.createTextNode(""));
   132 }
   103     var sel = document.body.appendChild(document.createElement("select"));
   133 
   104     sel.onchange = switchTheme;
   134 on_xml_error = function()
   105     for(var theme in themes)
   135 {
   106     {
   136     var p = document.createElement("p");
   107         sel.appendChild(opt.cloneNode(true));
   137     p.appendChild(document.createTextNode("ERROR: List of hats could not be fetched from the server!"));
   108         sel.lastChild.value = theme;
   138     document.body.appendChild(p);
   109         sel.lastChild.lastChild.data = theme;
   139 }
   110         if(theme === "Nature") sel.lastChild.selected = true;
   140 
   111     }
   141 window.onload = function()
   112     var chk = document.createElement("input");
   142 {
   113     chk.type = "checkbox";
   143     // Load list of hats
   114     chk.onclick = switchAnim;
   144     if (!IS_LOCAL) {
   115     document.body.appendChild(chk);
   145         // Request list of hats from repository URL
   116     chk = chk.cloneNode(false);
   146         var xml=new XMLHttpRequest();
   117     chk.onclick = hideGirders;
   147         xml.open("GET", "https://hg.hedgewars.org/hedgewars/file/tip/share/hedgewars/Data/Graphics/Hats/");
   118     document.body.appendChild(chk);
   148         xml.addEventListener("error", on_xml_error);
       
   149         xml.onload = on_xml_loaded;
       
   150         xml.send();
       
   151     }
       
   152     else
       
   153     {
       
   154         on_hats_loaded();
       
   155     }
       
   156 }
       
   157 
       
   158 on_hats_loaded = function()
       
   159 {
       
   160     // Exclude NoHat as uninteresting. Exclude team hats as we can't properly display them yet
       
   161     // TODO: Add support for team hats
       
   162     var disallowedMasks = {
       
   163         "NoHat":true,
       
   164         "hair_team":true,
       
   165         "cap_team":true,
       
   166         "TeamTophat":true,
       
   167     };
       
   168 
       
   169     // Render girders
   119     var s = document.styleSheets[0].cssRules;
   170     var s = document.styleSheets[0].cssRules;
   120     for(var i=0;i<s.length;i++)
   171     for(var i=0;i<s.length;i++)
   121         if (s[i].selectorText.toLowerCase() === ".girder") girder = s[i];
   172     {
   122         
   173         if (s[i].selectorText.toLowerCase() === ".girder")
       
   174             girder = s[i];
       
   175     }
       
   176 
   123     var a = document.createElement("a");
   177     var a = document.createElement("a");
   124     var g = document.createElement("div");
   178     var g = document.createElement("div");
   125     g.className="girder";
   179     g.className="girder";
       
   180     a.className="hat";
   126     a.appendChild(document.createElement("div"));
   181     a.appendChild(document.createElement("div"));
   127     a.lastChild.appendChild(document.createTextNode(""));
   182     a.lastChild.appendChild(document.createTextNode(""));
       
   183 
       
   184     // Render hats
       
   185     var missingMasks = [];
       
   186     var img;
       
   187     var j = 0;
       
   188     var toDelete = [];
   128     for (var i=0;i<masks.length;i++)
   189     for (var i=0;i<masks.length;i++)
   129     {
   190     {
       
   191         if (disallowedMasks[masks[i]] === true) {
       
   192             missingMasks.push(masks[i]);
       
   193             toDelete.push(i);
       
   194             continue;
       
   195         }
   130         var h = document.body.appendChild(a.cloneNode(true));
   196         var h = document.body.appendChild(a.cloneNode(true));
   131         h.href = "//hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Graphics/Hats/"+masks[i]+".png";
   197         if (IS_LOCAL)
       
   198             h.href = "../share/hedgewars/Data/Graphics/Hats/"+masks[i]+".png";
       
   199         else
       
   200             h.href = "https://hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Graphics/Hats/"+masks[i]+".png";
       
   201 
       
   202         img = new Image();
       
   203         img.onload = function() {
       
   204             var name = this.id.substr(7);
       
   205             if (this.height === 32) {
       
   206                 staticMasks[name] = true;
       
   207             }
       
   208             this.remove();
       
   209         }
       
   210         img.src = h.href;
       
   211         img.id = "__mask_"+masks[i];
       
   212 
   132         h.lastChild.style.backgroundImage = 'url("'+h.href+'")';
   213         h.lastChild.style.backgroundImage = 'url("'+h.href+'")';
   133         h.lastChild.lastChild.data = masks[i];
   214         h.lastChild.lastChild.data = masks[i];
   134         h.title = masks[i];
   215         h.title = masks[i];
   135         h.idle = Math.floor(Math.random()*19);
   216         h.idle = Math.floor(Math.random()*19);
   136         if (i%17 === 16 || i === masks.length-1) document.body.appendChild(g.cloneNode(false));
   217         if (j%17 === 16 || i === masks.length-1)
   137     }
   218             document.body.appendChild(g.cloneNode(false));
   138     
   219         j++;
   139 /* quick and dirty animation */
   220     }
   140 animationInterval = setInterval(animateHogs, 128);
   221     // Cleanup masks array
       
   222     for (var i=0; i<toDelete.length; i++)
       
   223         masks.splice(toDelete[i], 1);
       
   224 
       
   225     // List missing hats
       
   226     if (missingMasks.length > 0)
       
   227     {
       
   228         var pm = document.createElement("p");
       
   229         pm.appendChild(document.createTextNode("Other hats: "));
       
   230         for (var i=0; i<missingMasks.length; i++)
       
   231         {
       
   232             if (missingMasks[i] === "NoHat")
       
   233                 continue;
       
   234             var link = document.createElement("a");
       
   235             if (IS_LOCAL)
       
   236                 link.href = "../share/hedgewars/Data/Graphics/Hats/"+masks[i]+".png";
       
   237             else
       
   238                 link.href = "https://hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Graphics/Hats/"+masks[i]+".png";
       
   239             link.appendChild(document.createTextNode(masks[i]));
       
   240             pm.appendChild(link);
       
   241             if (i < missingMasks.length -1)
       
   242                 pm.appendChild(document.createTextNode(", "));
       
   243         }
       
   244         document.body.appendChild(pm);
       
   245     }
       
   246 
       
   247     // Quick and dirty animation
       
   248     animationInterval = setInterval(animateHogs, 128);
       
   249 
       
   250     // Theme selection drop-down list
       
   251     var form = document.body.appendChild(document.createElement("form"));
       
   252 
       
   253     var opt = document.createElement("option");
       
   254     opt.appendChild(document.createTextNode(""));
       
   255 
       
   256     var label = document.createElement("label");
       
   257     label.htmlFor = "theme_select";
       
   258     label.appendChild(document.createTextNode("Theme: "));
       
   259     form.appendChild(label);
       
   260 
       
   261     var sel = form.appendChild(document.createElement("select"));
       
   262     sel.id = "theme_select";
       
   263     sel.onchange = switchTheme;
       
   264     for(var theme in themes)
       
   265     {
       
   266         sel.appendChild(opt.cloneNode(true));
       
   267         sel.lastChild.value = theme;
       
   268         sel.lastChild.lastChild.data = theme;
       
   269         if(theme === "Nature")
       
   270             sel.lastChild.selected = true;
       
   271     }
       
   272     form.appendChild(document.createElement("br"));
       
   273 
       
   274     // Checkbox: Switch animation
       
   275     var chk = document.createElement("input");
       
   276     chk.id = "anim";
       
   277     chk.type = "checkbox";
       
   278     chk.onclick = switchAnim;
       
   279     chk.checked = true;
       
   280     form.appendChild(chk);
       
   281     label = document.createElement("label");
       
   282     label.htmlFor = "anim";
       
   283     label.appendChild(document.createTextNode("Animate hats"));
       
   284     form.appendChild(label);
       
   285 
       
   286     form.appendChild(document.createElement("br"));
       
   287 
       
   288     // Checkbox: Hide girders
       
   289     chk = document.createElement("input");
       
   290     chk.id = "hide_girders";
       
   291     chk.type = "checkbox";
       
   292     chk.onclick = hideGirders;
       
   293     chk.checked = true;
       
   294     form.appendChild(chk);
       
   295     label = document.createElement("label");
       
   296     label.htmlFor = "hide_girders";
       
   297     label.appendChild(document.createTextNode("Show girders"));
       
   298     form.appendChild(label);
       
   299 
       
   300     document.body.appendChild(form);
       
   301 
       
   302 
   141 }
   303 }
   142 
   304 
   143 function animateHogs()
   305 function animateHogs()
   144 {
   306 {
   145     var a = document.getElementsByTagName("a");
   307     var a = document.getElementsByTagName("a");
   146     for (var i=0;i<a.length;i++)
   308     for (var i=0;i<a.length;i++)
   147     {
   309     {
       
   310         if (a.className === "hat")
       
   311             continue;
       
   312         // Cycle through hedgehog and hat animation frames
       
   313 
       
   314         // Hedgehog
   148         a[i].style.backgroundPosition=Math.floor(a[i].idle/16)*-32+"px "+(a[i].idle%16)*-32+"px";
   315         a[i].style.backgroundPosition=Math.floor(a[i].idle/16)*-32+"px "+(a[i].idle%16)*-32+"px";
   149         a[i].firstChild.style.backgroundPosition=Math.floor(a[i].idle/16)*-32+"px "+(a[i].idle%16)*-32+"px";
   316 
       
   317         // Hat
       
   318         if (staticMasks[masks[i]] === true) {
       
   319             // Hat offset for static hats
       
   320             if (a[i].idle === 2 || a[i].idle === 7 || a[i].idle === 12)
       
   321                 a[i].firstChild.style.marginTop="-4px";
       
   322             else if (a[i].idle === 16)
       
   323                 a[i].firstChild.style.marginTop="-6px";
       
   324             else
       
   325                 a[i].firstChild.style.marginTop="-5px";
       
   326 
       
   327             a[i].firstChild.style.backgroundPosition="0px 0px";
       
   328         }
       
   329         else
       
   330         {
       
   331             // Animated hat frames
       
   332             a[i].firstChild.style.backgroundPosition=Math.floor(a[i].idle/16)*-32+"px "+(a[i].idle%16)*-32+"px";
       
   333         }
       
   334 
       
   335         // Next frame
   150         a[i].idle++;
   336         a[i].idle++;
   151         if (a[i].idle > 18) a[i].idle = 0;
   337         if (a[i].idle > 18)
   152     }
   338             a[i].idle = 0;
   153 }
   339     }
   154 
   340 }
       
   341 
       
   342 // Turn on or off hog+hat animation
   155 function switchAnim()
   343 function switchAnim()
   156 {
   344 {
   157     if (animationInterval) 
   345     if (animationInterval)
   158     {
   346     {
   159         clearInterval(animationInterval);
   347         clearInterval(animationInterval);
   160         animationInterval = null;
   348         animationInterval = null;
   161     }
   349     }
   162     else animationInterval = setInterval(animateHogs, 128);
   350     else animationInterval = setInterval(animateHogs, 128);
   163 }
   351 }
   164 
   352 
       
   353 // Turn on or off girders
   165 function hideGirders()
   354 function hideGirders()
   166 {
   355 {
   167     var g = document.getElementsByClassName("girder");
   356     var g = document.getElementsByClassName("girder");
   168     for(var i=0;i<g.length;i++) 
   357     for(var i=0;i<g.length;i++)
   169         if (this.checked)
   358         if (this.checked)
       
   359             g[i].className = "girder";
       
   360         else
   170             g[i].className = "girder hide";
   361             g[i].className = "girder hide";
   171         else
   362 
   172             g[i].className = "girder";
   363 }
   173     
   364 
   174 }
   365 // Select theme according to drop-down list value
   175 
       
   176 function switchTheme()
   366 function switchTheme()
   177 {
   367 {
   178     document.body.style.backgroundImage='url("//hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Themes/'+this.value+'/Sky.png")';
   368     var prefix;
       
   369     if (!IS_LOCAL)
       
   370         prefix = "https://hg.hedgewars.org/hedgewars/raw-file/tip";
       
   371     else
       
   372         prefix = "..";
       
   373     document.body.style.backgroundImage='url("'+prefix+'/share/hedgewars/Data/Themes/'+this.value+'/Sky.png")';
   179     if (themes[this.value])
   374     if (themes[this.value])
   180         girder.style.backgroundImage='url("//hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Themes/'+this.value+'/Girder.png")';
   375         girder.style.backgroundImage='url("'+prefix+'/share/hedgewars/Data/Themes/'+this.value+'/Girder.png")';
   181     else
   376     else
   182         girder.style.backgroundImage='url("//hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Graphics/Girder.png")';
   377         girder.style.backgroundImage='url("'+prefix+'/share/hedgewars/Data/Graphics/Girder.png")';
   183 }
   378 }
   184 //]]>
   379 //]]>
   185     </script>
   380     </script>
   186 </head>
   381 </head>
   187 <body>
   382 <body>
   188 <h1>List of Hedgewars hats</h1>
   383 <h1>List of Hedgewars hats</h1>
   189 <noscript>
   384 <noscript>
   190 <p><strong>ERROR</strong>: We're so sorry, but this webpage only works with JavaScript enabled. It seems JavaScript is disabled or not supported in your browser.</p>
   385 <p><strong>ERROR</strong>: We're so sorry, but this webpage only works with JavaScript enabled. It seems JavaScript is disabled or not supported in your browser.<br/>
   191 <p>Normally, this webpage would display an animated preview of the hats in Hedgewars.</p>
   386 Normally, this webpage would display an animated preview of the hats in Hedgewars.</p>
   192 </noscript>
   387 </noscript>
   193 </body>
   388 </body>
   194 </html>
   389 </html>