diff --git a/.idea/wordRotator.iml b/.idea/wordRotator.iml index 1cb9668..d89d15e 100755 --- a/.idea/wordRotator.iml +++ b/.idea/wordRotator.iml @@ -3,7 +3,6 @@ - diff --git a/bin/build.sh b/bin/build.sh index 303bef1..fcb1378 100755 --- a/bin/build.sh +++ b/bin/build.sh @@ -1,4 +1,4 @@ #!/usr/bin/env bash cd $(dirname "$0")/.. -npm run build \ No newline at end of file +npm run build 1 \ No newline at end of file diff --git a/bin/test.sh b/bin/test.sh index 6f45b7c..67d6ad1 100644 --- a/bin/test.sh +++ b/bin/test.sh @@ -2,5 +2,5 @@ cd $(dirname "$0")/.. -testcafe firefox test/test.testcafe.js +testcafe firefox test/test.testcafe.js --debug-on-fail #node bin/testcafe.js; \ No newline at end of file diff --git a/config/autoload/global.php b/config/autoload/global.php index c41db4b..7363390 100755 --- a/config/autoload/global.php +++ b/config/autoload/global.php @@ -18,6 +18,7 @@ return [ 'driver_options' => array( PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'' ), + 'charset' => "UTF8", ), 'appVariables' => [ diff --git a/config/autoload/local.php b/config/autoload/local.php index 5c2ae26..025f072 100755 --- a/config/autoload/local.php +++ b/config/autoload/local.php @@ -32,6 +32,7 @@ return [ PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8' ), 'useStrict' => true, + 'charset' => 'utf8' ], ), ), diff --git a/orga/test.sql b/orga/test.sql index 0069953..ef28ad0 100644 --- a/orga/test.sql +++ b/orga/test.sql @@ -78,10 +78,14 @@ INSERT INTO `Level` (`id`, `words`, `positions`, `renderer`, `lastUpdated`, `lan (15, '["ARCHIV","CHARME"]', '[1,1,3]', 20, '2018-07-14 17:01:18', 1, 0, 2), (26, '["BRAUEREI","THERAPIE"]', '[3,2,0,1]', 40, '2018-07-14 17:01:18', 1, 0, 40), (217, '["ZEITSTRAFE","HOCHSAISON"]', '[1,0,3,3,1]', 60, '2018-07-14 17:01:18', 1, 0, 60), -(220, '["FEINGUSS","R\\u00dcCKFALL","PHYSIKER","RESIDENZ","BERATUNG","KOCHTOPF"]', '[2,0,0,1,2,2,3,3,2,1,1,2,0,0]', 100, '2018-07-14 17:01:18', 1, 0, 100), +(220, '["FEINGUSS","RÜCKFALL","PHYSIKER","RESIDENZ","BERATUNG","KOCHTOPF"]', '[2,0,0,1,2,2,3,3,2,1,1,2,0,0]', 100, '2018-07-14 17:01:18', 1, 0, 100), (24, '["BETONUNG","ANBETUNG","ALLERGIE","BAUMHAUS"]', '[0,3,1,1,3,1,2,0,0,0]', 120, '2018-07-14 17:01:18', 1, 0, 120), (62, '["FEHLPROGNOSE","GEISTESKRAFT","ARBEITSPAUSE","BEREITSCHAFT","MOSAIKARBEIT","INFRAROTFILM"]', '[0,3,0,1,0,3,2,3,1,2,3,1,2,2,0,2,3,0,2,1,1]', 140, '2018-07-14 17:01:18', 1, 0, 140), (260, '["SCHREIBTISCH","URHEBERRECHT","PFLANZENKOST","OPERNKONZERT"]', '[1,3,2,1,3,0,1,2,3,0,2,0,1,0,0]', 160, '2018-07-14 17:01:18', 1, 0, 160), (67,'["AHNUNG","AUSBAU"]','[0,0,1]',20,'2018-10-10 00:00:00',1,0,1), -(341,'["NACHLASS","BUSLINIE","REITBAHN","LAUFGANG","KASCHMIR","BADETUCH"]','[1,3,0,2,3,0,1,0,0,0,3,1,0,0]',100,'2018-04-15 12:22:11',1,0,61) +(341,'["NACHLASS","BUSLINIE","REITBAHN","LAUFGANG","KASCHMIR","BADETUCH"]','[1,3,0,2,3,0,1,0,0,0,3,1,0,0]',100,'2018-04-15 12:22:11',1,0,90), +(1921,'["HACKBRATEN","FLÜCHTLING","HOFTHEATER","KIELWASSER"]','[3,1,3,0,0,1,3,0,1,0,1]',81,'2018-11-06 17:08:37',1,0,70), +(2270,'["AUFKLÄRUNG","FALTENROCK","HERZFEHLER","RESTAURANT"]','[0,0,0,2,0,1,0,3,2,1,3]',80,'2018-11-06 17:08:50',1,0,80), +(2266,'["SPRÜHREGEN","SITZKISSEN","FÜHRERHAUS","NAVIGATION"]','[3,1,1,2,1,3,3,3,2,1,3]',82,'2018-11-06 17:08:50',1,0,81), +(2265,'["ZINSESZINS","TISCHLAMPE","ABSPALTUNG","BRANDWUNDE"]','[2,3,3,2,2,3,0,1,0,1,2]',83,'2018-11-06 17:08:50',1,0,82) ; \ No newline at end of file diff --git a/orga/updateUsedFlagsSql.sql b/orga/updateUsedFlagsSql.sql index 9966718..c855c08 100644 --- a/orga/updateUsedFlagsSql.sql +++ b/orga/updateUsedFlagsSql.sql @@ -1,2 +1,7 @@ +UPDATE Level SET words = REPLACE(words, "\\u00fc", "Ü"); +UPDATE Level SET words = REPLACE(words, "\\u00dc", "Ü"); +UPDATE Level SET words = REPLACE(words, "\\u00f6", "Ö"); +UPDATE Level SET words = REPLACE(words, "\\u00df", "ß"); +UPDATE Level SET words = REPLACE(words, "\\u00e4", "Ä"); UPDATE Word SET Word.used = 0; UPDATE Word SET Word.used = 1 WHERE deleted = 0 AND (SELECT count(*) FROM Level WHERE words LIKE CONCAT("%\"", Word.word, "\"%") AND deleted = 0) > 0 \ No newline at end of file diff --git a/public/css/wordRotator.css b/public/css/wordRotator.css index 9e5fb1d..1bff4f8 100755 --- a/public/css/wordRotator.css +++ b/public/css/wordRotator.css @@ -1 +1 @@ -.top-bar-title{white-space:nowrap}#action-bar .close-listener{position:fixed;top:0;left:0;right:0;bottom:0;background:transparent;z-index:9000}#action-bar #responsive-menu .top-bar-right{position:relative;text-align:right;width:100%}#action-bar .top-bar-right{width:auto}#action-bar .top-bar-right .menu.action-bar a img+span{display:none}#action-bar .top-bar-right .menu.action-bar .action{position:relative;z-index:9000}#action-bar .top-bar-right .menu.action-bar .action.is-dropdown-submenu-parent{z-index:9001}#action-bar .top-bar-right .menu.action-bar .action.hidden{display:none}@media screen and (max-width:24.9375em){#action-bar .top-bar-right .menu.action-bar .action.smedium{display:none}}@media screen and (max-width:39.9375em){#action-bar .top-bar-right .menu.action-bar .action li{display:table-cell}#action-bar .top-bar-right .menu.action-bar .action.medium{display:none}}@media screen and (max-width:63.9375em){#action-bar .top-bar-right .menu.action-bar .action.large{display:none}}#action-bar .top-bar-right .menu.action-bar .action.never{display:none}#action-bar .top-bar-right .menu.action-bar.hidden{display:inline-block;position:absolute;z-index:9000;border:1px solid #cacaca;padding:.2rem;-webkit-transform:translateX(-100%);transform:translateX(-100%);text-align:left}#action-bar .top-bar-right .menu.action-bar.hidden .action.hidden{display:none}#action-bar .top-bar-right .menu.action-bar.hidden .action.is-dropdown-submenu-parent{z-index:9001}#action-bar .top-bar-right .menu.action-bar.hidden .action.is-dropdown-submenu-parent ul.is-dropdown-submenu{top:auto}#action-bar .top-bar-right .menu.action-bar.hidden .action.is-dropdown-submenu-parent ul.is-dropdown-submenu>.close-listener,#action-bar .top-bar-right .menu.action-bar.hidden .action.is-dropdown-submenu-parent ul.is-dropdown-submenu>li.action{z-index:9001}#action-bar .top-bar-right .menu.action-bar.hidden .action.is-dropdown-submenu-parent>a:after{display:block;width:0;height:0;border:6px inset;content:"";border-bottom-width:0;border-top-style:solid;border-color:#fff transparent transparent;right:5px;left:auto;margin-top:-3px}#action-bar .top-bar-right .menu.action-bar.hidden .action a{white-space:nowrap}#action-bar .top-bar-right .menu.action-bar.hidden .action a img{display:none}#action-bar .top-bar-right .menu.action-bar.hidden .action a img+span{display:inherit}@media print,screen and (min-width:40em){#action-bar .top-bar-right .menu.action-bar.hidden .action.medium{display:none}}@media print,screen and (min-width:25em){#action-bar .top-bar-right .menu.action-bar.hidden .action.smedium{display:none}}@media print,screen and (min-width:64em){#action-bar .top-bar-right .menu.action-bar.hidden .action.large{display:none}}@media screen and (max-width:24.9375em){#action-bar .top-bar-right .menu.action-bar.hidden .action.smedium{display:block}#action-bar .top-bar-right .menu.action-bar.hidden .action.smedium.hidden{display:none}}@media screen and (max-width:39.9375em){#action-bar .top-bar-right .menu.action-bar.hidden .action.medium{display:block}#action-bar .top-bar-right .menu.action-bar.hidden .action.medium.hidden{display:none}}@media screen and (max-width:63.9375em){#action-bar .top-bar-right .menu.action-bar.hidden .action.large{display:block}#action-bar .top-bar-right .menu.action-bar.hidden .action.large.hidden{display:none}}#action-bar .top-bar-right .menu.action-bar.hidden .action.never{display:block}#action-bar .top-bar-right .menu.action-bar.hidden .action.always,#action-bar .top-bar-right .menu.action-bar.hidden .action.never.hidden{display:none}#action-bar .top-bar-right .menu .action{z-index:100}@media screen and (max-width:39.9375em){#action-bar .top-bar-right .menu .action a{width:100%;padding-left:.68rem}}@media screen and (max-width:24.9375em){#action-bar .top-bar-right .menu .action a{padding-left:.236rem}}@media screen and (max-width:39.9375em){#action-bar .top-bar-right .menu .action:not(.is-dropdown-submenu-parent) a{padding-right:.68rem}}@media screen and (max-width:24.9375em){#action-bar .top-bar-right .menu .action:not(.is-dropdown-submenu-parent) a{padding-right:.236rem}}#action-bar .top-bar-right .menu .action.img a{padding-top:0}#action-bar .top-bar-right .menu .action.img a img{vertical-align:inherit;max-height:1.4rem}#action-bar .top-bar-right .menu>li>ul.is-dropdown-submenu{min-width:0}#action-bar .top-bar-right .menu>li>ul.is-dropdown-submenu .action{display:inherit}#action-bar .top-bar-right .menu>li.opens-right>ul.is-dropdown-submenu{right:auto;left:auto}#action-bar .top-bar-right .menu>li.opens-right>ul.is-dropdown-submenu a{text-align:left}.dropdown.menu>li.is-dropdown-submenu-parent>a:after{border-color:#fff transparent transparent}form{position:relative}.sending .sending-loader{position:absolute;background-color:hsla(0,0%,49%,.3);display:block;pointer-events:all;width:100%;height:100%;top:0;left:0;bottom:0;right:0;z-index:10;border-radius:2px}.sending .sending-loader .loader{position:absolute}.sending-loader{display:none}label{position:relative}label [type=color],label [type=date],label [type=datetime-local],label [type=datetime],label [type=email],label [type=month],label [type=number],label [type=password],label [type=search],label [type=tel],label [type=text],label [type=time],label [type=url],label [type=week],label input:not([type]),label input[type=text],label textarea{display:block;width:100%;height:2.4375rem;padding:.5rem;-webkit-box-shadow:none!important;box-shadow:none!important;font-size:1rem;font-weight:400;line-height:1.5;border:none;outline:0;margin:0 0 15px}label [type=color]:focus,label [type=date]:focus,label [type=datetime-local]:focus,label [type=datetime]:focus,label [type=email]:focus,label [type=month]:focus,label [type=number]:focus,label [type=password]:focus,label [type=search]:focus,label [type=tel]:focus,label [type=text]:focus,label [type=time]:focus,label [type=url]:focus,label [type=week]:focus,label input:not([type]):focus,label input[type=text]:focus,label textarea:focus{border:none;-webkit-box-shadow:none!important;box-shadow:none!important}label [type=color].notEmpty:not(:focus)~span,label [type=color]:focus~span,label [type=date].notEmpty:not(:focus)~span,label [type=date]:focus~span,label [type=datetime-local].notEmpty:not(:focus)~span,label [type=datetime-local]:focus~span,label [type=datetime].notEmpty:not(:focus)~span,label [type=datetime]:focus~span,label [type=email].notEmpty:not(:focus)~span,label [type=email]:focus~span,label [type=month].notEmpty:not(:focus)~span,label [type=month]:focus~span,label [type=number].notEmpty:not(:focus)~span,label [type=number]:focus~span,label [type=password].notEmpty:not(:focus)~span,label [type=password]:focus~span,label [type=search].notEmpty:not(:focus)~span,label [type=search]:focus~span,label [type=tel].notEmpty:not(:focus)~span,label [type=tel]:focus~span,label [type=text].notEmpty:not(:focus)~span,label [type=text]:focus~span,label [type=time].notEmpty:not(:focus)~span,label [type=time]:focus~span,label [type=url].notEmpty:not(:focus)~span,label [type=url]:focus~span,label [type=week].notEmpty:not(:focus)~span,label [type=week]:focus~span,label input:not([type]).notEmpty:not(:focus)~span,label input:not([type]):focus~span,label input[type=text].notEmpty:not(:focus)~span,label input[type=text]:focus~span,label textarea.notEmpty:not(:focus)~span,label textarea:focus~span{top:-11px;left:0;bottom:0;font-size:11px;opacity:1}label [type=color]~span,label [type=date]~span,label [type=datetime-local]~span,label [type=datetime]~span,label [type=email]~span,label [type=month]~span,label [type=number]~span,label [type=password]~span,label [type=search]~span,label [type=tel]~span,label [type=text]~span,label [type=time]~span,label [type=url]~span,label [type=week]~span,label input:not([type])~span,label input[type=text]~span,label textarea~span{position:absolute;pointer-events:none;left:10px;bottom:10px;top:7px;-webkit-transition:all .2s ease;transition:all .2s ease}label textarea{height:10rem;border-top-right-radius:3px;border-top-left-radius:3px}label [type=checkbox].before-text{margin-bottom:0}.listjs{position:relative}.listjs label{display:inline-block}.listjs label input{margin-bottom:0}.listjs table{border-collapse:collapse}.listjs table tfoot tr th,.listjs table thead tr th{text-align:left}.listjs table tfoot tr th.sort,.listjs table thead tr th.sort{cursor:pointer}.listjs table tbody.list tr:first-child td{border-top:1px solid #696969}.listjs table tbody.list tr:last-child td{border-bottom:1px solid #696969}.listjs table tbody.list tr td{border-top:1px solid #c8c8c8;padding:.3rem}.listjs ul.pagination{float:right;display:inline-block;margin:0}.listjs ul.pagination li{display:inline-block;padding-left:5px;padding-right:5px;text-decoration:underline}.listjs ul.pagination li.active,.listjs ul.pagination li.disabled{text-decoration:none}.background{position:fixed;z-index:1000000;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgba(55,55,55,.6)}.background .modal{position:relative;top:50%;margin:auto;width:80%;-webkit-transform:translateY(-50%);transform:translateY(-50%);padding:.5rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;max-height:80%;max-width:1024px}@media screen and (max-width:63.9375em){.background .modal.small-margin{width:90%}}@media screen and (max-width:24.9375em){.background .modal.small-margin{width:95%}}.background .modal.max-small{max-width:0}.background .modal.max-smedium{max-width:400px}.background .modal.max-medium{max-width:640px}.background .modal.max-large{max-width:1024px}.background .modal.max-xlarge{max-width:1200px}.background .modal.max-xxlarge{max-width:1440px}.background .modal .title{font-weight:700;padding-bottom:.5rem}.background .modal .content-container{overflow-y:auto;max-height:100%}.background .modal .content-container .loader{position:static;-webkit-transform:none;transform:none}.background .modal .close{text-align:right;float:right;font-size:28px;font-weight:700;line-height:1}.background .modal .close:focus,.background .modal .close:hover{text-decoration:none;cursor:pointer}.background .modal .modal-button-container{padding-top:.5rem}.background .modal .modal-button-container .button{margin-left:.2rem;margin-bottom:0!important;padding:.6em .8em}@media screen and (max-width:24.9375em){.background .modal .modal-button-container .button{margin-left:.1rem;padding:.3em .5em}}.rotated{-webkit-transform-origin:bottom center;transform-origin:bottom center;height:50%;position:absolute;top:0;bottom:0;left:0;right:0}.share-icon{margin:.1rem}.share-icon,.share-icon svg{width:1.5rem;max-width:1.5rem}.tab-header-container .tab-header{display:inline-block;background-color:#eee;border:1px solid #b0b0b0;border-top-left-radius:4px;border-top-right-radius:4px;padding:0 5px}.tab-header-container .tab-header.active{border-bottom:0;background-color:#fff}*,:after,:before{-webkit-box-sizing:inherit;box-sizing:inherit}html{width:100%;font-size:18px;letter-spacing:1px}.max-height,html{min-height:100%;height:100%}body{margin:0;padding:0;height:100%;width:100%;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-weight:400;line-height:1.5;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;background:#fefefe;color:#0a0a0a}footer{border-top:1px solid #d8d8d8;text-align:center}.top-bar .top-bar-title strong{vertical-align:middle;display:inline-block}nav.top-bar{color:#fff;font-size:20px;-webkit-box-shadow:0 4px 5px 0 rgba(0,0,0,.14),0 2px 9px 1px rgba(0,0,0,.12),0 4px 2px -2px rgba(0,0,0,.2);box-shadow:0 4px 5px 0 rgba(0,0,0,.14),0 2px 9px 1px rgba(0,0,0,.12),0 4px 2px -2px rgba(0,0,0,.2);padding:.6rem;display:block}a.button,button.button{border-radius:2px}.fill-me{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-ms-flex-direction:column;flex-direction:column}.fill-me,.fill-me.vertical{-webkit-box-direction:normal}.fill-me.vertical{-webkit-box-orient:horizontal;-ms-flex-direction:row;flex-direction:row}.fill-me .grow{-webkit-box-flex:1;-ms-flex:1;flex:1}.flex-center{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.flex-center>*{max-height:100%}.dropdown.menu a,.menu a{padding:.4rem .5rem}svg path{fill:currentColor}div.mainContainer{position:relative;max-height:100%;max-width:100%;overflow:auto;-webkit-box-flex:1;-ms-flex:1;flex:1;margin:.5rem}div.mainContainer #main-content,div.mainContainer #site-content,div.mainContainer>.row{position:absolute;width:100%;height:100%;top:0;bottom:0;left:0;right:0}.inline-block{display:inline-block}.right{float:right}#logo-img{max-height:2.2rem}a{cursor:pointer}a,a.hidden-link{text-decoration:none;color:inherit}label{cursor:pointer}.align-right{text-align:right}.view-panel{display:none}.loader{left:50%;top:50%;position:fixed;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);text-align:center}.loader.inline{left:auto;top:auto;position:static;-webkit-transform:initial;transform:none;text-align:center;display:inline}.loader.small #spinner{-webkit-transform:scale(.5);transform:scale(.5)}.loader #spinner{-webkit-box-sizing:border-box;box-sizing:border-box;stroke:#b71c1a;stroke-width:3px;-webkit-transform-origin:50%;transform-origin:50%;-webkit-animation:line 1.6s cubic-bezier(.4,0,.2,1) infinite,rotate 1.6s linear infinite;animation:line 1.6s cubic-bezier(.4,0,.2,1) infinite,rotate 1.6s linear infinite}@-webkit-keyframes rotate{0%{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(450deg);transform:rotate(450deg)}}@keyframes rotate{0%{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(450deg);transform:rotate(450deg)}}@-webkit-keyframes line{0%{stroke-dasharray:2,85.964;-webkit-transform:rotate(0);transform:rotate(0)}50%{stroke-dasharray:65.973,21.9911;stroke-dashoffset:0}to{stroke-dasharray:2,85.964;stroke-dashoffset:-65.973;-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@keyframes line{0%{stroke-dasharray:2,85.964;-webkit-transform:rotate(0);transform:rotate(0)}50%{stroke-dasharray:65.973,21.9911;stroke-dashoffset:0}to{stroke-dasharray:2,85.964;stroke-dashoffset:-65.973;-webkit-transform:rotate(90deg);transform:rotate(90deg)}}#print-content{display:none}.action-button{max-height:1.7rem;margin-left:.4rem;margin-right:.4rem}.action-button:hover{background:#e8e8e8}.vcenter-container{width:100%;height:100%;display:table}.vcenter-container .vcenter{vertical-align:middle;display:table-cell;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.max-width{width:100%}button,input{letter-spacing:1px!important}.no-padding{padding:0;border:0}.center{text-align:center}@media print{#styles,.mainContainer,footer,nav{display:none!important}#print-content{display:block!important}}.overflow-y-auto{overflow-y:auto!important}.row.no-after:after{content:normal}.margin-bottom{margin-bottom:1rem}@media print,screen and (min-width:25em){.margin-bottom{margin-bottom:2rem}}@media print,screen and (min-width:40em){.margin-bottom{margin-bottom:3rem}}@media print,screen and (min-width:64em){.margin-bottom{margin-bottom:4rem}}@media screen and (min-width:75em){.margin-bottom{margin-bottom:5rem}}.font-small{font-size:.7em}.border-bottom{border-bottom:1px solid #cacaca}.border-right{border-right:1px solid #cacaca}.border-left{border-left:1px solid #cacaca}img.logo{vertical-align:inherit;display:inline-block;height:auto;max-width:1.1rem;margin-right:2px}.align-center{text-align:center}hr.separator{margin:1rem 0}.button-line{display:-webkit-box;display:-ms-flexbox;display:flex}.button-line .button{-webkit-box-flex:1;-ms-flex:1;flex:1;margin-left:1px;margin-right:1px;padding:.5rem .77rem}@media screen and (max-width:24.9375em){.small-small{font-size:small}}select{border:0;padding:.3rem}.hidden{display:none}img.action-image{max-height:1.4rem;cursor:pointer}img.back-button{max-height:.6rem;margin-right:.2rem;cursor:pointer;vertical-align:inherit}.no-margin-bottom{margin-bottom:0}div.flashMessage{font-size:.8rem;border-radius:25px;letter-spacing:0;z-index:1001;max-width:100%;display:inline-block;position:relative;-webkit-box-shadow:2px 2px 10px rgba(0,0,0,.28);box-shadow:2px 2px 10px rgba(0,0,0,.28);border:1px solid #626262;background-color:#6b6b6b;padding:.3em .6em;text-align:center;color:#fff}div.flashMessage:hover{opacity:.4;cursor:pointer}div.flashMessage:after,div.flashMessage:before{display:block;content:""}span.flashMessage{float:right;cursor:pointer}div.default{background-color:#1a9cc8}#flashMessageContainer{text-align:center;position:absolute}#flashMessageContainer,#flashMessageContainerAbsoulte{height:0!important;width:100%;overflow:visible!important}#flashMessageContainerAbsoulte{margin:5px 0;position:relative}.relative{position:relative}.no-transition,.no-transition *{-webkit-transition:none!important;transition:none!important}.settings-container{border:1px solid #000;border-radius:2px;padding:.3rem}@media print,screen and (min-width:40em){.settings-container #settings-fragments-container{border-left:1px solid #cacaca}}.settings-container #settings-fragments-container #settings-fragments>*{display:none}.settings-container #settings-fragments-container #settings-fragments>.active{display:block}.switch{position:relative;display:inline-block}@media screen and (max-width:24.9375em){.switch{font-size:.6em}}@media screen and (max-width:39.9375em){.switch{font-size:.7em}}.switch input{display:none}.switch input:checked+.slider:before{-webkit-transform:translateX(1.5em);transform:translateX(1.5em)}.switch .slider{display:inline-block;position:relative;cursor:pointer;width:3em;height:1.5em;border-radius:1.5em;background-color:#ccc;-webkit-transition:.4s;transition:.4s}.switch .slider:before{position:absolute;content:"";height:1.1em;width:1.1em;left:.15em;bottom:.15em;background-color:#fff;-webkit-transition:.4s;transition:.4s;border-radius:50%}.switch img,.switch svg{width:1.4em;display:inline;vertical-align:initial}.switch img path,.switch svg path{stroke-color:inherit}.zf-green{color:#68b604}.column:last-child:not(:first-child),.columns:last-child:not(:first-child){float:left}input[type=checkBox].form-control{height:24px;height:1.5rem;width:100%}[type=submit]{display:block;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;height:39px;height:2.4375rem;padding:8px;padding:.5rem;border:1px solid #cacaca;margin:0 0 16px;margin:0 0 1rem;font-family:inherit;font-size:16px;font-size:1rem;color:#0a0a0a;background-color:#fefefe;-webkit-box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);border-radius:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s;-webkit-appearance:none;-moz-appearance:none}form ul li{color:red;font-size:12.8px;font-size:.8rem}.button-dropdown:after{border-color:#000 transparent transparent;border-width:.4em;border-style:solid;content:"";position:absolute;top:.4em;display:block;height:0;width:0;right:1em}.button-dropdown{position:relative;display:block;padding-right:2em}.button-dropdown.open:after{border-color:transparent transparent #000;top:0}a.ui-datepicker-next,a.ui-datepicker-prev{height:100%!important}div.container a.navbar-brand>img{display:inline;margin-right:4px}ul.menu.plain li.active a{background-color:#ededed;color:#000}ul.menu.plain li a{color:#000}ul.menu.plain li a:hover{color:#525252}ul.submenu{border-top:1px solid #bcbcbc;border-bottom:1px solid #bcbcbc;margin-left:10px}#cookie-compliance{line-height:1.2;font-size:.8rem;width:100%;margin:0;padding:.3rem 0}#cookie-compliance #close-cookie-msg{float:right;margin-bottom:0;margin-right:3px;padding:.4rem .8rem}.menu-container .button{text-align:center;width:100%}.height-5{height:5%}.max-height-5{max-height:5%}.width-5{width:5%}.max-width-5{max-width:5%}.height-10{height:10%}.max-height-10{max-height:10%}.width-10{width:10%}.max-width-10{max-width:10%}.height-15{height:15%}.max-height-15{max-height:15%}.width-15{width:15%}.max-width-15{max-width:15%}.height-20{height:20%}.max-height-20{max-height:20%}.width-20{width:20%}.max-width-20{max-width:20%}.height-25{height:25%}.max-height-25{max-height:25%}.width-25{width:25%}.max-width-25{max-width:25%}.height-30{height:30%}.max-height-30{max-height:30%}.width-30{width:30%}.max-width-30{max-width:30%}.height-35{height:35%}.max-height-35{max-height:35%}.width-35{width:35%}.max-width-35{max-width:35%}.height-40{height:40%}.max-height-40{max-height:40%}.width-40{width:40%}.max-width-40{max-width:40%}.height-45{height:45%}.max-height-45{max-height:45%}.width-45{width:45%}.max-width-45{max-width:45%}.height-50{height:50%}.max-height-50{max-height:50%}.width-50{width:50%}.max-width-50{max-width:50%}.height-55{height:55%}.max-height-55{max-height:55%}.width-55{width:55%}.max-width-55{max-width:55%}.height-60{height:60%}.max-height-60{max-height:60%}.width-60{width:60%}.max-width-60{max-width:60%}.height-65{height:65%}.max-height-65{max-height:65%}.width-65{width:65%}.max-width-65{max-width:65%}.height-70{height:70%}.max-height-70{max-height:70%}.width-70{width:70%}.max-width-70{max-width:70%}.height-75{height:75%}.max-height-75{max-height:75%}.width-75{width:75%}.max-width-75{max-width:75%}.height-80{height:80%}.max-height-80{max-height:80%}.width-80{width:80%}.max-width-80{max-width:80%}.height-85{height:85%}.max-height-85{max-height:85%}.width-85{width:85%}.max-width-85{max-width:85%}.height-90{height:90%}.max-height-90{max-height:90%}.width-90{width:90%}.max-width-90{max-width:90%}.height-95{height:95%}.max-height-95{max-height:95%}.width-95{width:95%}.max-width-95{max-width:95%}.height-100{height:100%}.max-height-100{max-height:100%}.width-100{width:100%}.max-width-100{max-width:100%}*{-webkit-transition:.25s ease-out,color .25s ease-out;transition:.25s ease-out,color .25s ease-out}body.red{background:#fff;color:#000}body.red #cookie-compliance{background-color:#870015;color:#fff}body.red #cookie-compliance a.link,body.red #cookie-compliance a.link:hover{color:#ff3d00;border-bottom-color:#ff3d00}body.red a.link{text-decoration:none;color:#ff3d00;border-bottom:none}body.red a.link:hover{color:#ff3d00;border-bottom-color:#ff3d00}body.red .loader #spinner{stroke:#b71c1a}body.red nav.top-bar{color:#fff;background:red}body.red .top-bar ul{background:red!important}body.red .top-bar ul a{color:#fff}body.red .switch input:checked+.slider,body.red a.button,body.red a.button.disabled,body.red a.button.disabled:focus,body.red a.button.disabled:hover,body.red a.button:hover,body.red button.button,body.red button.button.disabled,body.red button.button.disabled:focus,body.red button.button.disabled:hover,body.red button.button:hover{background-color:red}body.red .switch input:focus+.slider{-webkit-box-shadow:0 0 1px red;box-shadow:0 0 1px red}body.red label{color:#000}body.red .background .modal{background-color:#fff}body.red svg.fill-color,body.red svg .fill-color{fill:currentColor}body.red svg.fill-background,body.red svg .fill-background{fill:#fff}body.red label [type=color],body.red label [type=date],body.red label [type=datetime-local],body.red label [type=datetime],body.red label [type=email],body.red label [type=month],body.red label [type=number],body.red label [type=password],body.red label [type=search],body.red label [type=tel],body.red label [type=text],body.red label [type=time],body.red label [type=url],body.red label [type=week],body.red label input:not([type]),body.red label input[type=text],body.red label textarea{border-bottom:solid #000;background:#fff;color:#000}body.red label [type=color]:focus,body.red label [type=date]:focus,body.red label [type=datetime-local]:focus,body.red label [type=datetime]:focus,body.red label [type=email]:focus,body.red label [type=month]:focus,body.red label [type=number]:focus,body.red label [type=password]:focus,body.red label [type=search]:focus,body.red label [type=tel]:focus,body.red label [type=text]:focus,body.red label [type=time]:focus,body.red label [type=url]:focus,body.red label [type=week]:focus,body.red label input:not([type]):focus,body.red label input[type=text]:focus,body.red label textarea:focus{border-bottom:solid #000}body.red label [type=color].notEmpty:not(:focus)~span,body.red label [type=color]:focus~span,body.red label [type=date].notEmpty:not(:focus)~span,body.red label [type=date]:focus~span,body.red label [type=datetime-local].notEmpty:not(:focus)~span,body.red label [type=datetime-local]:focus~span,body.red label [type=datetime].notEmpty:not(:focus)~span,body.red label [type=datetime]:focus~span,body.red label [type=email].notEmpty:not(:focus)~span,body.red label [type=email]:focus~span,body.red label [type=month].notEmpty:not(:focus)~span,body.red label [type=month]:focus~span,body.red label [type=number].notEmpty:not(:focus)~span,body.red label [type=number]:focus~span,body.red label [type=password].notEmpty:not(:focus)~span,body.red label [type=password]:focus~span,body.red label [type=search].notEmpty:not(:focus)~span,body.red label [type=search]:focus~span,body.red label [type=tel].notEmpty:not(:focus)~span,body.red label [type=tel]:focus~span,body.red label [type=text].notEmpty:not(:focus)~span,body.red label [type=text]:focus~span,body.red label [type=time].notEmpty:not(:focus)~span,body.red label [type=time]:focus~span,body.red label [type=url].notEmpty:not(:focus)~span,body.red label [type=url]:focus~span,body.red label [type=week].notEmpty:not(:focus)~span,body.red label [type=week]:focus~span,body.red label input:not([type]).notEmpty:not(:focus)~span,body.red label input:not([type]):focus~span,body.red label input[type=text].notEmpty:not(:focus)~span,body.red label input[type=text]:focus~span,body.red label textarea.notEmpty:not(:focus)~span,body.red label textarea:focus~span{color:#000}body.red label [type=color]~span,body.red label [type=date]~span,body.red label [type=datetime-local]~span,body.red label [type=datetime]~span,body.red label [type=email]~span,body.red label [type=month]~span,body.red label [type=number]~span,body.red label [type=password]~span,body.red label [type=search]~span,body.red label [type=tel]~span,body.red label [type=text]~span,body.red label [type=time]~span,body.red label [type=url]~span,body.red label [type=week]~span,body.red label input:not([type])~span,body.red label input[type=text]~span,body.red label textarea~span{color:rgba(0,0,0,.65)}body.red label textarea{-webkit-box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important;box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important}body.red input.notEmpty:invalid{background-color:rgba(255,0,0,.65)}body.blue{background:#fff;color:#000}body.blue #cookie-compliance{background-color:#1a3062;color:#fff}body.blue #cookie-compliance a.link,body.blue #cookie-compliance a.link:hover{color:#546cfe;border-bottom-color:#546cfe}body.blue a.link{text-decoration:none;color:#546cfe;border-bottom:none}body.blue a.link:hover{color:#546cfe;border-bottom-color:#546cfe}body.blue .loader #spinner{stroke:#673ab7}body.blue nav.top-bar{color:#fff;background:#2c58ae}body.blue .top-bar ul{background:#2c58ae!important}body.blue .top-bar ul a{color:#fff}body.blue .switch input:checked+.slider,body.blue a.button,body.blue a.button.disabled,body.blue a.button.disabled:focus,body.blue a.button.disabled:hover,body.blue a.button:hover,body.blue button.button,body.blue button.button.disabled,body.blue button.button.disabled:focus,body.blue button.button.disabled:hover,body.blue button.button:hover{background-color:#2c58ae}body.blue .switch input:focus+.slider{-webkit-box-shadow:0 0 1px #2c58ae;box-shadow:0 0 1px #2c58ae}body.blue label{color:#000}body.blue .background .modal{background-color:#fff}body.blue svg.fill-color,body.blue svg .fill-color{fill:currentColor}body.blue svg.fill-background,body.blue svg .fill-background{fill:#fff}body.blue label [type=color],body.blue label [type=date],body.blue label [type=datetime-local],body.blue label [type=datetime],body.blue label [type=email],body.blue label [type=month],body.blue label [type=number],body.blue label [type=password],body.blue label [type=search],body.blue label [type=tel],body.blue label [type=text],body.blue label [type=time],body.blue label [type=url],body.blue label [type=week],body.blue label input:not([type]),body.blue label input[type=text],body.blue label textarea{border-bottom:solid #000;background:#fff;color:#000}body.blue label [type=color]:focus,body.blue label [type=date]:focus,body.blue label [type=datetime-local]:focus,body.blue label [type=datetime]:focus,body.blue label [type=email]:focus,body.blue label [type=month]:focus,body.blue label [type=number]:focus,body.blue label [type=password]:focus,body.blue label [type=search]:focus,body.blue label [type=tel]:focus,body.blue label [type=text]:focus,body.blue label [type=time]:focus,body.blue label [type=url]:focus,body.blue label [type=week]:focus,body.blue label input:not([type]):focus,body.blue label input[type=text]:focus,body.blue label textarea:focus{border-bottom:solid #000}body.blue label [type=color].notEmpty:not(:focus)~span,body.blue label [type=color]:focus~span,body.blue label [type=date].notEmpty:not(:focus)~span,body.blue label [type=date]:focus~span,body.blue label [type=datetime-local].notEmpty:not(:focus)~span,body.blue label [type=datetime-local]:focus~span,body.blue label [type=datetime].notEmpty:not(:focus)~span,body.blue label [type=datetime]:focus~span,body.blue label [type=email].notEmpty:not(:focus)~span,body.blue label [type=email]:focus~span,body.blue label [type=month].notEmpty:not(:focus)~span,body.blue label [type=month]:focus~span,body.blue label [type=number].notEmpty:not(:focus)~span,body.blue label [type=number]:focus~span,body.blue label [type=password].notEmpty:not(:focus)~span,body.blue label [type=password]:focus~span,body.blue label [type=search].notEmpty:not(:focus)~span,body.blue label [type=search]:focus~span,body.blue label [type=tel].notEmpty:not(:focus)~span,body.blue label [type=tel]:focus~span,body.blue label [type=text].notEmpty:not(:focus)~span,body.blue label [type=text]:focus~span,body.blue label [type=time].notEmpty:not(:focus)~span,body.blue label [type=time]:focus~span,body.blue label [type=url].notEmpty:not(:focus)~span,body.blue label [type=url]:focus~span,body.blue label [type=week].notEmpty:not(:focus)~span,body.blue label [type=week]:focus~span,body.blue label input:not([type]).notEmpty:not(:focus)~span,body.blue label input:not([type]):focus~span,body.blue label input[type=text].notEmpty:not(:focus)~span,body.blue label input[type=text]:focus~span,body.blue label textarea.notEmpty:not(:focus)~span,body.blue label textarea:focus~span{color:#000}body.blue label [type=color]~span,body.blue label [type=date]~span,body.blue label [type=datetime-local]~span,body.blue label [type=datetime]~span,body.blue label [type=email]~span,body.blue label [type=month]~span,body.blue label [type=number]~span,body.blue label [type=password]~span,body.blue label [type=search]~span,body.blue label [type=tel]~span,body.blue label [type=text]~span,body.blue label [type=time]~span,body.blue label [type=url]~span,body.blue label [type=week]~span,body.blue label input:not([type])~span,body.blue label input[type=text]~span,body.blue label textarea~span{color:rgba(0,0,0,.65)}body.blue label textarea{-webkit-box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important;box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important}body.blue input.notEmpty:invalid{background-color:rgba(44,88,174,.65)}body.green{background:#fff;color:#000}body.green #cookie-compliance{background-color:#003613;color:#fff}body.green #cookie-compliance a.link,body.green #cookie-compliance a.link:hover{color:#009829;border-bottom-color:#009829}body.green a.link{text-decoration:none;color:#009829;border-bottom:none}body.green a.link:hover{color:#009829;border-bottom-color:#009829}body.green .loader #spinner{stroke:green}body.green nav.top-bar{color:#fff;background:green}body.green .top-bar ul{background:green!important}body.green .top-bar ul a{color:#fff}body.green .switch input:checked+.slider,body.green a.button,body.green a.button.disabled,body.green a.button.disabled:focus,body.green a.button.disabled:hover,body.green a.button:hover,body.green button.button,body.green button.button.disabled,body.green button.button.disabled:focus,body.green button.button.disabled:hover,body.green button.button:hover{background-color:green}body.green .switch input:focus+.slider{-webkit-box-shadow:0 0 1px green;box-shadow:0 0 1px green}body.green label{color:#000}body.green .background .modal{background-color:#fff}body.green svg.fill-color,body.green svg .fill-color{fill:currentColor}body.green svg.fill-background,body.green svg .fill-background{fill:#fff}body.green label [type=color],body.green label [type=date],body.green label [type=datetime-local],body.green label [type=datetime],body.green label [type=email],body.green label [type=month],body.green label [type=number],body.green label [type=password],body.green label [type=search],body.green label [type=tel],body.green label [type=text],body.green label [type=time],body.green label [type=url],body.green label [type=week],body.green label input:not([type]),body.green label input[type=text],body.green label textarea{border-bottom:solid #000;background:#fff;color:#000}body.green label [type=color]:focus,body.green label [type=date]:focus,body.green label [type=datetime-local]:focus,body.green label [type=datetime]:focus,body.green label [type=email]:focus,body.green label [type=month]:focus,body.green label [type=number]:focus,body.green label [type=password]:focus,body.green label [type=search]:focus,body.green label [type=tel]:focus,body.green label [type=text]:focus,body.green label [type=time]:focus,body.green label [type=url]:focus,body.green label [type=week]:focus,body.green label input:not([type]):focus,body.green label input[type=text]:focus,body.green label textarea:focus{border-bottom:solid #000}body.green label [type=color].notEmpty:not(:focus)~span,body.green label [type=color]:focus~span,body.green label [type=date].notEmpty:not(:focus)~span,body.green label [type=date]:focus~span,body.green label [type=datetime-local].notEmpty:not(:focus)~span,body.green label [type=datetime-local]:focus~span,body.green label [type=datetime].notEmpty:not(:focus)~span,body.green label [type=datetime]:focus~span,body.green label [type=email].notEmpty:not(:focus)~span,body.green label [type=email]:focus~span,body.green label [type=month].notEmpty:not(:focus)~span,body.green label [type=month]:focus~span,body.green label [type=number].notEmpty:not(:focus)~span,body.green label [type=number]:focus~span,body.green label [type=password].notEmpty:not(:focus)~span,body.green label [type=password]:focus~span,body.green label [type=search].notEmpty:not(:focus)~span,body.green label [type=search]:focus~span,body.green label [type=tel].notEmpty:not(:focus)~span,body.green label [type=tel]:focus~span,body.green label [type=text].notEmpty:not(:focus)~span,body.green label [type=text]:focus~span,body.green label [type=time].notEmpty:not(:focus)~span,body.green label [type=time]:focus~span,body.green label [type=url].notEmpty:not(:focus)~span,body.green label [type=url]:focus~span,body.green label [type=week].notEmpty:not(:focus)~span,body.green label [type=week]:focus~span,body.green label input:not([type]).notEmpty:not(:focus)~span,body.green label input:not([type]):focus~span,body.green label input[type=text].notEmpty:not(:focus)~span,body.green label input[type=text]:focus~span,body.green label textarea.notEmpty:not(:focus)~span,body.green label textarea:focus~span{color:#000}body.green label [type=color]~span,body.green label [type=date]~span,body.green label [type=datetime-local]~span,body.green label [type=datetime]~span,body.green label [type=email]~span,body.green label [type=month]~span,body.green label [type=number]~span,body.green label [type=password]~span,body.green label [type=search]~span,body.green label [type=tel]~span,body.green label [type=text]~span,body.green label [type=time]~span,body.green label [type=url]~span,body.green label [type=week]~span,body.green label input:not([type])~span,body.green label input[type=text]~span,body.green label textarea~span{color:rgba(0,0,0,.65)}body.green label textarea{-webkit-box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important;box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important}body.green input.notEmpty:invalid{background-color:rgba(0,128,0,.65)}body.pink{background:#fff;color:#000}body.pink #cookie-compliance{background-color:#70374a;color:#fff}body.pink #cookie-compliance a.link,body.pink #cookie-compliance a.link:hover{color:#fe64af;border-bottom-color:#fe64af}body.pink a.link{text-decoration:none;color:#fe64af;border-bottom:none}body.pink a.link:hover{color:#fe64af;border-bottom-color:#fe64af}body.pink .loader #spinner{stroke:#ff69b4}body.pink nav.top-bar{color:#fff;background:#ff69b4}body.pink .top-bar ul{background:#ff69b4!important}body.pink .top-bar ul a{color:#fff}body.pink .switch input:checked+.slider,body.pink a.button,body.pink a.button.disabled,body.pink a.button.disabled:focus,body.pink a.button.disabled:hover,body.pink a.button:hover,body.pink button.button,body.pink button.button.disabled,body.pink button.button.disabled:focus,body.pink button.button.disabled:hover,body.pink button.button:hover{background-color:#ff69b4}body.pink .switch input:focus+.slider{-webkit-box-shadow:0 0 1px #ff69b4;box-shadow:0 0 1px #ff69b4}body.pink label{color:#000}body.pink .background .modal{background-color:#fff}body.pink svg.fill-color,body.pink svg .fill-color{fill:currentColor}body.pink svg.fill-background,body.pink svg .fill-background{fill:#fff}body.pink label [type=color],body.pink label [type=date],body.pink label [type=datetime-local],body.pink label [type=datetime],body.pink label [type=email],body.pink label [type=month],body.pink label [type=number],body.pink label [type=password],body.pink label [type=search],body.pink label [type=tel],body.pink label [type=text],body.pink label [type=time],body.pink label [type=url],body.pink label [type=week],body.pink label input:not([type]),body.pink label input[type=text],body.pink label textarea{border-bottom:solid #000;background:#fff;color:#000}body.pink label [type=color]:focus,body.pink label [type=date]:focus,body.pink label [type=datetime-local]:focus,body.pink label [type=datetime]:focus,body.pink label [type=email]:focus,body.pink label [type=month]:focus,body.pink label [type=number]:focus,body.pink label [type=password]:focus,body.pink label [type=search]:focus,body.pink label [type=tel]:focus,body.pink label [type=text]:focus,body.pink label [type=time]:focus,body.pink label [type=url]:focus,body.pink label [type=week]:focus,body.pink label input:not([type]):focus,body.pink label input[type=text]:focus,body.pink label textarea:focus{border-bottom:solid #000}body.pink label [type=color].notEmpty:not(:focus)~span,body.pink label [type=color]:focus~span,body.pink label [type=date].notEmpty:not(:focus)~span,body.pink label [type=date]:focus~span,body.pink label [type=datetime-local].notEmpty:not(:focus)~span,body.pink label [type=datetime-local]:focus~span,body.pink label [type=datetime].notEmpty:not(:focus)~span,body.pink label [type=datetime]:focus~span,body.pink label [type=email].notEmpty:not(:focus)~span,body.pink label [type=email]:focus~span,body.pink label [type=month].notEmpty:not(:focus)~span,body.pink label [type=month]:focus~span,body.pink label [type=number].notEmpty:not(:focus)~span,body.pink label [type=number]:focus~span,body.pink label [type=password].notEmpty:not(:focus)~span,body.pink label [type=password]:focus~span,body.pink label [type=search].notEmpty:not(:focus)~span,body.pink label [type=search]:focus~span,body.pink label [type=tel].notEmpty:not(:focus)~span,body.pink label [type=tel]:focus~span,body.pink label [type=text].notEmpty:not(:focus)~span,body.pink label [type=text]:focus~span,body.pink label [type=time].notEmpty:not(:focus)~span,body.pink label [type=time]:focus~span,body.pink label [type=url].notEmpty:not(:focus)~span,body.pink label [type=url]:focus~span,body.pink label [type=week].notEmpty:not(:focus)~span,body.pink label [type=week]:focus~span,body.pink label input:not([type]).notEmpty:not(:focus)~span,body.pink label input:not([type]):focus~span,body.pink label input[type=text].notEmpty:not(:focus)~span,body.pink label input[type=text]:focus~span,body.pink label textarea.notEmpty:not(:focus)~span,body.pink label textarea:focus~span{color:#000}body.pink label [type=color]~span,body.pink label [type=date]~span,body.pink label [type=datetime-local]~span,body.pink label [type=datetime]~span,body.pink label [type=email]~span,body.pink label [type=month]~span,body.pink label [type=number]~span,body.pink label [type=password]~span,body.pink label [type=search]~span,body.pink label [type=tel]~span,body.pink label [type=text]~span,body.pink label [type=time]~span,body.pink label [type=url]~span,body.pink label [type=week]~span,body.pink label input:not([type])~span,body.pink label input[type=text]~span,body.pink label textarea~span{color:rgba(0,0,0,.65)}body.pink label textarea{-webkit-box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important;box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important}body.pink input.notEmpty:invalid{background-color:rgba(255,105,180,.65)}body.black{background:#fff;color:#000}body.black #cookie-compliance{background-color:#353535;color:#fff}body.black #cookie-compliance a.link{color:#fff;border-bottom-color:#fff}body.black #cookie-compliance a.link:hover{color:#cacaca;border-bottom-color:#cacaca}body.black a.link{text-decoration:none;color:#000;border-bottom:1px solid #000}body.black a.link:hover{color:#4e4e4e;border-bottom-color:#4e4e4e}body.black .loader #spinner{stroke:#000}body.black nav.top-bar{color:#fff;background:#000}body.black .top-bar ul{background:#000!important}body.black .top-bar ul a{color:#fff}body.black .switch input:checked+.slider,body.black a.button,body.black a.button.disabled,body.black a.button.disabled:focus,body.black a.button.disabled:hover,body.black a.button:hover,body.black button.button,body.black button.button.disabled,body.black button.button.disabled:focus,body.black button.button.disabled:hover,body.black button.button:hover{background-color:#000}body.black .switch input:focus+.slider{-webkit-box-shadow:0 0 1px #000;box-shadow:0 0 1px #000}body.black label{color:#000}body.black .background .modal{background-color:#fff}body.black svg.fill-color,body.black svg .fill-color{fill:currentColor}body.black svg.fill-background,body.black svg .fill-background{fill:#fff}body.black label [type=color],body.black label [type=date],body.black label [type=datetime-local],body.black label [type=datetime],body.black label [type=email],body.black label [type=month],body.black label [type=number],body.black label [type=password],body.black label [type=search],body.black label [type=tel],body.black label [type=text],body.black label [type=time],body.black label [type=url],body.black label [type=week],body.black label input:not([type]),body.black label input[type=text],body.black label textarea{border-bottom:solid #000;background:#fff;color:#000}body.black label [type=color]:focus,body.black label [type=date]:focus,body.black label [type=datetime-local]:focus,body.black label [type=datetime]:focus,body.black label [type=email]:focus,body.black label [type=month]:focus,body.black label [type=number]:focus,body.black label [type=password]:focus,body.black label [type=search]:focus,body.black label [type=tel]:focus,body.black label [type=text]:focus,body.black label [type=time]:focus,body.black label [type=url]:focus,body.black label [type=week]:focus,body.black label input:not([type]):focus,body.black label input[type=text]:focus,body.black label textarea:focus{border-bottom:solid #000}body.black label [type=color].notEmpty:not(:focus)~span,body.black label [type=color]:focus~span,body.black label [type=date].notEmpty:not(:focus)~span,body.black label [type=date]:focus~span,body.black label [type=datetime-local].notEmpty:not(:focus)~span,body.black label [type=datetime-local]:focus~span,body.black label [type=datetime].notEmpty:not(:focus)~span,body.black label [type=datetime]:focus~span,body.black label [type=email].notEmpty:not(:focus)~span,body.black label [type=email]:focus~span,body.black label [type=month].notEmpty:not(:focus)~span,body.black label [type=month]:focus~span,body.black label [type=number].notEmpty:not(:focus)~span,body.black label [type=number]:focus~span,body.black label [type=password].notEmpty:not(:focus)~span,body.black label [type=password]:focus~span,body.black label [type=search].notEmpty:not(:focus)~span,body.black label [type=search]:focus~span,body.black label [type=tel].notEmpty:not(:focus)~span,body.black label [type=tel]:focus~span,body.black label [type=text].notEmpty:not(:focus)~span,body.black label [type=text]:focus~span,body.black label [type=time].notEmpty:not(:focus)~span,body.black label [type=time]:focus~span,body.black label [type=url].notEmpty:not(:focus)~span,body.black label [type=url]:focus~span,body.black label [type=week].notEmpty:not(:focus)~span,body.black label [type=week]:focus~span,body.black label input:not([type]).notEmpty:not(:focus)~span,body.black label input:not([type]):focus~span,body.black label input[type=text].notEmpty:not(:focus)~span,body.black label input[type=text]:focus~span,body.black label textarea.notEmpty:not(:focus)~span,body.black label textarea:focus~span{color:#000}body.black label [type=color]~span,body.black label [type=date]~span,body.black label [type=datetime-local]~span,body.black label [type=datetime]~span,body.black label [type=email]~span,body.black label [type=month]~span,body.black label [type=number]~span,body.black label [type=password]~span,body.black label [type=search]~span,body.black label [type=tel]~span,body.black label [type=text]~span,body.black label [type=time]~span,body.black label [type=url]~span,body.black label [type=week]~span,body.black label input:not([type])~span,body.black label input[type=text]~span,body.black label textarea~span{color:rgba(0,0,0,.65)}body.black label textarea{-webkit-box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important;box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important}body.black input.notEmpty:invalid{background-color:rgba(0,0,0,.65)}body.dark{background:#000;color:#fff}body.dark #cookie-compliance{background-color:#4b4b4b;color:#fff}body.dark #cookie-compliance a.link,body.dark #cookie-compliance a.link:hover{color:#fff;border-bottom-color:#fff}body.dark a.link{text-decoration:none;color:#fff;border-bottom:1px solid #fff}body.dark a.link:hover{color:#fff;border-bottom-color:#fff}body.dark .loader #spinner{stroke:#fff}body.dark nav.top-bar{color:#fff;background:#373737}body.dark .top-bar ul{background:#373737!important}body.dark .top-bar ul a{color:#fff}body.dark .switch input:checked+.slider,body.dark a.button,body.dark a.button.disabled,body.dark a.button.disabled:focus,body.dark a.button.disabled:hover,body.dark a.button:hover,body.dark button.button,body.dark button.button.disabled,body.dark button.button.disabled:focus,body.dark button.button.disabled:hover,body.dark button.button:hover{background-color:#373737}body.dark .switch input:focus+.slider{-webkit-box-shadow:0 0 1px #373737;box-shadow:0 0 1px #373737}body.dark label{color:#fff}body.dark .background .modal{background-color:#000}body.dark svg.fill-color,body.dark svg .fill-color{fill:currentColor}body.dark svg.fill-background,body.dark svg .fill-background{fill:#000}body.dark label [type=color],body.dark label [type=date],body.dark label [type=datetime-local],body.dark label [type=datetime],body.dark label [type=email],body.dark label [type=month],body.dark label [type=number],body.dark label [type=password],body.dark label [type=search],body.dark label [type=tel],body.dark label [type=text],body.dark label [type=time],body.dark label [type=url],body.dark label [type=week],body.dark label input:not([type]),body.dark label input[type=text],body.dark label textarea{border-bottom:solid #fff;background:#000;color:#fff}body.dark label [type=color]:focus,body.dark label [type=date]:focus,body.dark label [type=datetime-local]:focus,body.dark label [type=datetime]:focus,body.dark label [type=email]:focus,body.dark label [type=month]:focus,body.dark label [type=number]:focus,body.dark label [type=password]:focus,body.dark label [type=search]:focus,body.dark label [type=tel]:focus,body.dark label [type=text]:focus,body.dark label [type=time]:focus,body.dark label [type=url]:focus,body.dark label [type=week]:focus,body.dark label input:not([type]):focus,body.dark label input[type=text]:focus,body.dark label textarea:focus{border-bottom:solid #fff}body.dark label [type=color].notEmpty:not(:focus)~span,body.dark label [type=color]:focus~span,body.dark label [type=date].notEmpty:not(:focus)~span,body.dark label [type=date]:focus~span,body.dark label [type=datetime-local].notEmpty:not(:focus)~span,body.dark label [type=datetime-local]:focus~span,body.dark label [type=datetime].notEmpty:not(:focus)~span,body.dark label [type=datetime]:focus~span,body.dark label [type=email].notEmpty:not(:focus)~span,body.dark label [type=email]:focus~span,body.dark label [type=month].notEmpty:not(:focus)~span,body.dark label [type=month]:focus~span,body.dark label [type=number].notEmpty:not(:focus)~span,body.dark label [type=number]:focus~span,body.dark label [type=password].notEmpty:not(:focus)~span,body.dark label [type=password]:focus~span,body.dark label [type=search].notEmpty:not(:focus)~span,body.dark label [type=search]:focus~span,body.dark label [type=tel].notEmpty:not(:focus)~span,body.dark label [type=tel]:focus~span,body.dark label [type=text].notEmpty:not(:focus)~span,body.dark label [type=text]:focus~span,body.dark label [type=time].notEmpty:not(:focus)~span,body.dark label [type=time]:focus~span,body.dark label [type=url].notEmpty:not(:focus)~span,body.dark label [type=url]:focus~span,body.dark label [type=week].notEmpty:not(:focus)~span,body.dark label [type=week]:focus~span,body.dark label input:not([type]).notEmpty:not(:focus)~span,body.dark label input:not([type]):focus~span,body.dark label input[type=text].notEmpty:not(:focus)~span,body.dark label input[type=text]:focus~span,body.dark label textarea.notEmpty:not(:focus)~span,body.dark label textarea:focus~span{color:#fff}body.dark label [type=color]~span,body.dark label [type=date]~span,body.dark label [type=datetime-local]~span,body.dark label [type=datetime]~span,body.dark label [type=email]~span,body.dark label [type=month]~span,body.dark label [type=number]~span,body.dark label [type=password]~span,body.dark label [type=search]~span,body.dark label [type=tel]~span,body.dark label [type=text]~span,body.dark label [type=time]~span,body.dark label [type=url]~span,body.dark label [type=week]~span,body.dark label input:not([type])~span,body.dark label input[type=text]~span,body.dark label textarea~span{color:hsla(0,0%,100%,.65)}body.dark label textarea{-webkit-box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important;box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important}body.dark input.notEmpty:invalid{background-color:rgba(55,55,55,.65)}@-webkit-keyframes tutorialPointer{0%{top:75%}to{top:25%}}@keyframes tutorialPointer{0%{top:75%}to{top:25%}}.tutorial-blanket{display:none;position:fixed;top:0;bottom:0;left:0;right:0;z-index:9001;background:rgba(98,98,98,.51)}.tutorial .tutorial-blanket{display:block}.tutorial .tutorial-text{color:#fff;font-size:1.5rem;display:-webkit-box;display:-ms-flexbox;display:flex}.tutorial .tutorial-text,.tutorial .tutorial-text *{-webkit-transition:none!important;transition:none!important}.tutorial.step-1 #level .segment-row{position:inherit}.tutorial.step-1 #level .segment-parent:nth-child(3),.tutorial.step-1 #level .segment-parent:nth-child(3).rotating{z-index:9900!important}.tutorial.step-1 .tutorial-text .step-1{display:initial;z-index:9900!important;position:relative}.tutorial.step-2 #level{z-index:9900!important}.tutorial.step-2 .tutorial-text .step-2,.tutorial.step-3 .tutorial-text .step-3{display:initial;z-index:9900!important;position:relative}.tutorial.step-3 #help-button{position:relative;z-index:9900!important;overflow:visible;margin-right:10px;margin-top:10px;-webkit-box-shadow:0 0 10px 5px #fff;box-shadow:0 0 10px 5px #fff}.tutorial.step-4 .tutorial-text .step-4{display:initial;z-index:9900!important;position:relative}.tutorial.step-4 #level .segment-row{position:inherit}.tutorial.step-4 #level .segment-row>.child-container .segment-parent.layer-2,.tutorial.step-4 #level .segment-row>.child-container>.segment-parent.layer-2.rotating{z-index:9900!important}.tutorial.step-4 #level .segment-row>.child-container .segment-parent.layer-2 #tutorial-pointer,.tutorial.step-4 #level .segment-row>.child-container>.segment-parent.layer-2.rotating #tutorial-pointer{width:.6em;height:.6em;border-radius:50%;left:25%;right:50%;position:absolute;top:75%;bottom:50%;z-index:1;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);-webkit-animation:tutorialPointer 2s infinite;animation:tutorialPointer 2s infinite;pointer-events:none}body.red #tutorial-pointer{background:red}body.red #level-number-container.in-main-menu{background:#fff;border-color:#000}body.red .segment.segment-parent{border-color:#555}body.red .segment.segment-parent.layer-2{border-color:#000}body.red #site-content>:not(.won) .segment.locked{border-color:#870015;background-color:red!important}body.red .segment:not(.segment-row):not(.segment-triangle).rotate-90,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-90,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-180,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-270,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-360,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-180,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-90,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-180,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-270,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-360,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-270,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-90,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-180,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-270,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-360,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-360,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-90,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-180,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-270,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-360{background-color:#fff}body.blue #tutorial-pointer{background:#2c58ae}body.blue #level-number-container.in-main-menu{background:#fff;border-color:#000}body.blue .segment.segment-parent{border-color:#555}body.blue .segment.segment-parent.layer-2{border-color:#000}body.blue #site-content>:not(.won) .segment.locked{border-color:#1a3062;background-color:#2c58ae!important}body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-90,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-90,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-180,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-270,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-360,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-180,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-90,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-180,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-270,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-360,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-270,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-90,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-180,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-270,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-360,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-360,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-90,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-180,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-270,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-360{background-color:#fff}body.green #tutorial-pointer{background:green}body.green #level-number-container.in-main-menu{background:#fff;border-color:#000}body.green .segment.segment-parent{border-color:#555}body.green .segment.segment-parent.layer-2{border-color:#000}body.green #site-content>:not(.won) .segment.locked{border-color:#003613;background-color:green!important}body.green .segment:not(.segment-row):not(.segment-triangle).rotate-90,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-90,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-180,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-270,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-360,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-180,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-90,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-180,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-270,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-360,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-270,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-90,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-180,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-270,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-360,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-360,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-90,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-180,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-270,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-360{background-color:#fff}body.pink #tutorial-pointer{background:#ff69b4}body.pink #level-number-container.in-main-menu{background:#fff;border-color:#000}body.pink .segment.segment-parent{border-color:#555}body.pink .segment.segment-parent.layer-2{border-color:#000}body.pink #site-content>:not(.won) .segment.locked{border-color:#70374a;background-color:#ff69b4!important}body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-90,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-90,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-180,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-270,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-360,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-180,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-90,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-180,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-270,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-360,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-270,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-90,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-180,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-270,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-360,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-360,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-90,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-180,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-270,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-360{background-color:#fff}body.black #tutorial-pointer{background:#000}body.black #level-number-container.in-main-menu{background:#fff;border-color:#000}body.black .segment.segment-parent{border-color:#555}body.black .segment.segment-parent.layer-2{border-color:#000}body.black #site-content>:not(.won) .segment.locked{border-color:#353535;background-color:#000!important}body.black .segment:not(.segment-row):not(.segment-triangle).rotate-90,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-90,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-180,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-270,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-360,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-180,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-90,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-180,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-270,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-360,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-270,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-90,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-180,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-270,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-360,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-360,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-90,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-180,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-270,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-360{background-color:#fff}body.dark #tutorial-pointer{background:#373737}body.dark #level-number-container.in-main-menu{background:#000;border-color:#fff}body.dark .segment.segment-parent{border-color:#9b9b9b}body.dark .segment.segment-parent.layer-2{border-color:#fff}body.dark #site-content>:not(.won) .segment.locked{border-color:#4b4b4b;background-color:#373737!important}body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-90,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-90,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-180,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-270,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-360,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-180,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-90,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-180,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-270,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-360,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-270,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-90,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-180,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-270,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-360,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-360,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-90,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-180,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-270,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-360{background-color:#000}body.dark .switch input:checked+.slider{border-color:#000}body.dark .switch .slider{border:1px solid #fff;background-color:inherit;padding:1px}body.dark #site-content>:not(.won) .segment.locked.layer-2{border-color:#565656}body.dark .modal{border:1px solid #fff;border-radius:2px}body.black #site-content>:not(.won) .segment.locked{background-color:#9d9d9d!important;border-color:#6e6e6e!important}body.black #site-content>:not(.won) .segment.locked>.child-container>.segment-leaf{background-color:transparent!important}body.black #logo{border:1px solid grey;border-radius:50%}body label{font-size:1em!important}body .setting-row:not(.hidden){line-height:1;padding-top:.5em;padding-bottom:.5em;width:100%;cursor:pointer;background:hsla(0,0%,76%,.13);display:inline-block}nav.top-bar.title-bar{padding:.3rem .6rem 0}#logo{max-width:2rem;-webkit-transition:none;transition:none}#action-bar .top-bar-right .menu .action.img a{padding-bottom:0}#action-bar .top-bar-right .menu .action.img a img{max-height:1.8rem}.dropdown.menu a,.menu a{padding:.2rem .5rem}.relative-level-number{position:relative}.relative-level-number #level-number-container{top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}#level-number-container{z-index:1;-webkit-transition:none;transition:none;position:absolute;left:50%;-webkit-transform:translate(-50%);transform:translate(-50%);border:3px solid #fff;border-radius:50%;visibility:hidden;display:table-cell;height:35px;width:35px;text-align:center;vertical-align:middle}#level-number-container.visible{visibility:visible}#level-number-container.in-main-menu{background:#fff;border-color:#000;height:1em;width:1em;min-height:1em;min-width:1em;max-height:1em;max-width:1em}#level-number-container #level-number{-webkit-transition:none;transition:none;position:absolute;left:50%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);font-weight:700}.coin-counter{display:inline-block;position:relative;font-size:1.6rem}@media screen and (max-width:24.9375em){.coin-counter{font-size:1rem}}.coin-counter :after{background-image:url(../img/coinTower.png);background-size:28px 28px;width:28px;height:28px;display:inline-block;content:""}#coin-container{line-height:1}#coin-container .coin{margin-left:3px;margin-right:3px;max-width:20px;display:inline-block}@media print,screen and (min-width:25em){#coin-container .coin{max-width:25px}}@media print,screen and (min-width:40em){#coin-container .coin{max-width:30px}}@-webkit-keyframes rotate-90{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@keyframes rotate-90{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@-webkit-keyframes rotate-reverse-90{0%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}to{-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@keyframes rotate-reverse-90{0%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}to{-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@-webkit-keyframes rotate-180{0%{-webkit-transform:rotate(90deg);transform:rotate(90deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@keyframes rotate-180{0%{-webkit-transform:rotate(90deg);transform:rotate(90deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@-webkit-keyframes rotate-reverse-180{0%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@keyframes rotate-reverse-180{0%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@-webkit-keyframes rotate-270{0%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}to{-webkit-transform:rotate(270deg);transform:rotate(270deg)}}@keyframes rotate-270{0%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}to{-webkit-transform:rotate(270deg);transform:rotate(270deg)}}@-webkit-keyframes rotate-reverse-270{0%{-webkit-transform:rotate(1turn);transform:rotate(1turn)}to{-webkit-transform:rotate(270deg);transform:rotate(270deg)}}@keyframes rotate-reverse-270{0%{-webkit-transform:rotate(1turn);transform:rotate(1turn)}to{-webkit-transform:rotate(270deg);transform:rotate(270deg)}}@-webkit-keyframes rotate-360{0%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes rotate-360{0%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@-webkit-keyframes rotate-reverse-360{0%{-webkit-transform:rotate(450deg);transform:rotate(450deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes rotate-reverse-360{0%{-webkit-transform:rotate(450deg);transform:rotate(450deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.segment:not(.segment-row):not(.segment-triangle).rotating{z-index:10!important;overflow:hidden}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;animation-direction:reverse;-webkit-animation-direction:reverse;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-90;animation-name:rotate-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-180;animation-name:rotate-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-270;animation-name:rotate-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-360;animation-name:rotate-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;animation-direction:reverse;-webkit-animation-direction:reverse;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-360;animation-name:rotate-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-90;animation-name:rotate-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-180;animation-name:rotate-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-270;animation-name:rotate-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;animation-direction:reverse;-webkit-animation-direction:reverse;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-270;animation-name:rotate-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-360;animation-name:rotate-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-90;animation-name:rotate-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-180;animation-name:rotate-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;animation-direction:reverse;-webkit-animation-direction:reverse;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-180;animation-name:rotate-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-270;animation-name:rotate-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-360;animation-name:rotate-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-90;animation-name:rotate-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-90{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-90.rotating{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-90.rotating.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-180{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-180.rotating{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-180.rotating.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-270{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-270.rotating{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-270.rotating.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-360{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-360.rotating{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-360.rotating.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180,.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-90{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-90.rotating{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-90.rotating.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-180{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-180.rotating{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-180.rotating.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-270{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-270.rotating{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-270.rotating.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-360{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-360.rotating{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-360.rotating.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-90{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-90.rotating{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-90.rotating.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-180{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-180.rotating{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-180.rotating.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-270{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-270.rotating{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-270.rotating.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-360{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-360.rotating{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-360.rotating.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment{-webkit-transform:rotate(0deg);transform:rotate(0deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-90.rotating{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-90.rotating.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-180{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-180.rotating{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-180.rotating.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-270.rotating{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-270.rotating.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-360{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-360.rotating{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-360.rotating.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}#level{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;white-space:nowrap;max-width:100%;-webkit-tap-highlight-color:rgba(255,255,255,0);overflow-y:visible}#level,#level *,.segment{-webkit-transition:none;transition:none}.segment{vertical-align:top;white-space:normal;cursor:pointer;display:inline-block;text-align:center;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:1;background-color:inherit;line-height:0}.segment.segment-row{-webkit-animation:none!important;animation:none!important;white-space:nowrap}.segment.segment-column>.child-container>.segment,.segment.segment-row{display:block;width:100%}.segment.segment-leaf{background-color:transparent!important;min-width:1em;padding:.8em}.segment.segment-leaf:before{content:" ";display:block;padding-top:100%}.segment.segment-leaf .leaf-element{position:absolute;width:100%;height:100%;line-height:1.5em;top:0;left:0}.segment.segment-parent{border:1px solid #a9a9a9;border-radius:3px;padding:1px}.segment.segment-parent.layer-2{border:3px solid #000}#site-content>:not(.won) .show-when-won{display:none}.level-container{-webkit-transition:none;transition:none}.won .show-while-playing{display:none}.text-right{text-align:right}#continue-button{margin-bottom:2px}@media screen and (max-width:24.9375em){#continue-button{margin-bottom:0;padding:.3em .6em}}@media screen and (max-width:24.9375em){#play-button{margin-bottom:2px}}#help-button{margin:0;padding:.4em;max-width:3em}@media screen and (max-width:39.9375em){#help-button{padding:.2em;max-width:2em}}.line-height-1{line-height:1}body{overscroll-behavior:contain;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#site-content{overflow:visible}div.mainContainer{overflow-x:hidden}.clickable{cursor:pointer}#share-button{overflow:hidden}#share-button svg{cursor:pointer;max-width:1.5rem} \ No newline at end of file +.top-bar-title{white-space:nowrap}#action-bar .close-listener{position:fixed;top:0;left:0;right:0;bottom:0;background:transparent;z-index:9000}#action-bar #responsive-menu .top-bar-right{position:relative;text-align:right;width:100%}#action-bar .top-bar-right{width:auto}#action-bar .top-bar-right .menu.action-bar a img+span{display:none}#action-bar .top-bar-right .menu.action-bar .action{position:relative;z-index:9000}#action-bar .top-bar-right .menu.action-bar .action.is-dropdown-submenu-parent{z-index:9001}#action-bar .top-bar-right .menu.action-bar .action.hidden{display:none}@media screen and (max-width:24.9375em){#action-bar .top-bar-right .menu.action-bar .action.smedium{display:none}}@media screen and (max-width:39.9375em){#action-bar .top-bar-right .menu.action-bar .action li{display:table-cell}#action-bar .top-bar-right .menu.action-bar .action.medium{display:none}}@media screen and (max-width:63.9375em){#action-bar .top-bar-right .menu.action-bar .action.large{display:none}}#action-bar .top-bar-right .menu.action-bar .action.never{display:none}#action-bar .top-bar-right .menu.action-bar.hidden{display:inline-block;position:absolute;z-index:9000;border:1px solid #cacaca;padding:.2rem;-webkit-transform:translateX(-100%);transform:translateX(-100%);text-align:left}#action-bar .top-bar-right .menu.action-bar.hidden .action.hidden{display:none}#action-bar .top-bar-right .menu.action-bar.hidden .action.is-dropdown-submenu-parent{z-index:9001}#action-bar .top-bar-right .menu.action-bar.hidden .action.is-dropdown-submenu-parent ul.is-dropdown-submenu{top:auto}#action-bar .top-bar-right .menu.action-bar.hidden .action.is-dropdown-submenu-parent ul.is-dropdown-submenu>.close-listener,#action-bar .top-bar-right .menu.action-bar.hidden .action.is-dropdown-submenu-parent ul.is-dropdown-submenu>li.action{z-index:9001}#action-bar .top-bar-right .menu.action-bar.hidden .action.is-dropdown-submenu-parent>a:after{display:block;width:0;height:0;border:6px inset;content:"";border-bottom-width:0;border-top-style:solid;border-color:#fff transparent transparent;right:5px;left:auto;margin-top:-3px}#action-bar .top-bar-right .menu.action-bar.hidden .action a{white-space:nowrap}#action-bar .top-bar-right .menu.action-bar.hidden .action a img{display:none}#action-bar .top-bar-right .menu.action-bar.hidden .action a img+span{display:inherit}@media print,screen and (min-width:40em){#action-bar .top-bar-right .menu.action-bar.hidden .action.medium{display:none}}@media print,screen and (min-width:25em){#action-bar .top-bar-right .menu.action-bar.hidden .action.smedium{display:none}}@media print,screen and (min-width:64em){#action-bar .top-bar-right .menu.action-bar.hidden .action.large{display:none}}@media screen and (max-width:24.9375em){#action-bar .top-bar-right .menu.action-bar.hidden .action.smedium{display:block}#action-bar .top-bar-right .menu.action-bar.hidden .action.smedium.hidden{display:none}}@media screen and (max-width:39.9375em){#action-bar .top-bar-right .menu.action-bar.hidden .action.medium{display:block}#action-bar .top-bar-right .menu.action-bar.hidden .action.medium.hidden{display:none}}@media screen and (max-width:63.9375em){#action-bar .top-bar-right .menu.action-bar.hidden .action.large{display:block}#action-bar .top-bar-right .menu.action-bar.hidden .action.large.hidden{display:none}}#action-bar .top-bar-right .menu.action-bar.hidden .action.never{display:block}#action-bar .top-bar-right .menu.action-bar.hidden .action.always,#action-bar .top-bar-right .menu.action-bar.hidden .action.never.hidden{display:none}#action-bar .top-bar-right .menu .action{z-index:100}@media screen and (max-width:39.9375em){#action-bar .top-bar-right .menu .action a{width:100%;padding-left:.68rem}}@media screen and (max-width:24.9375em){#action-bar .top-bar-right .menu .action a{padding-left:.236rem}}@media screen and (max-width:39.9375em){#action-bar .top-bar-right .menu .action:not(.is-dropdown-submenu-parent) a{padding-right:.68rem}}@media screen and (max-width:24.9375em){#action-bar .top-bar-right .menu .action:not(.is-dropdown-submenu-parent) a{padding-right:.236rem}}#action-bar .top-bar-right .menu .action.img a{padding-top:0}#action-bar .top-bar-right .menu .action.img a img{vertical-align:inherit;max-height:1.4rem}#action-bar .top-bar-right .menu>li>ul.is-dropdown-submenu{min-width:0}#action-bar .top-bar-right .menu>li>ul.is-dropdown-submenu .action{display:inherit}#action-bar .top-bar-right .menu>li.opens-right>ul.is-dropdown-submenu{right:auto;left:auto}#action-bar .top-bar-right .menu>li.opens-right>ul.is-dropdown-submenu a{text-align:left}.dropdown.menu>li.is-dropdown-submenu-parent>a:after{border-color:#fff transparent transparent}form{position:relative}.sending .sending-loader{position:absolute;background-color:hsla(0,0%,49%,.3);display:block;pointer-events:all;width:100%;height:100%;top:0;left:0;bottom:0;right:0;z-index:10;border-radius:2px}.sending .sending-loader .loader{position:absolute}.sending-loader{display:none}label{position:relative}label [type=color],label [type=date],label [type=datetime-local],label [type=datetime],label [type=email],label [type=month],label [type=number],label [type=password],label [type=search],label [type=tel],label [type=text],label [type=time],label [type=url],label [type=week],label input:not([type]),label input[type=text],label textarea{display:block;width:100%;height:2.4375rem;padding:.5rem;-webkit-box-shadow:none!important;box-shadow:none!important;font-size:1rem;font-weight:400;line-height:1.5;border:none;outline:0;margin:0 0 15px}label [type=color]:focus,label [type=date]:focus,label [type=datetime-local]:focus,label [type=datetime]:focus,label [type=email]:focus,label [type=month]:focus,label [type=number]:focus,label [type=password]:focus,label [type=search]:focus,label [type=tel]:focus,label [type=text]:focus,label [type=time]:focus,label [type=url]:focus,label [type=week]:focus,label input:not([type]):focus,label input[type=text]:focus,label textarea:focus{border:none;-webkit-box-shadow:none!important;box-shadow:none!important}label [type=color].notEmpty:not(:focus)~span,label [type=color]:focus~span,label [type=date].notEmpty:not(:focus)~span,label [type=date]:focus~span,label [type=datetime-local].notEmpty:not(:focus)~span,label [type=datetime-local]:focus~span,label [type=datetime].notEmpty:not(:focus)~span,label [type=datetime]:focus~span,label [type=email].notEmpty:not(:focus)~span,label [type=email]:focus~span,label [type=month].notEmpty:not(:focus)~span,label [type=month]:focus~span,label [type=number].notEmpty:not(:focus)~span,label [type=number]:focus~span,label [type=password].notEmpty:not(:focus)~span,label [type=password]:focus~span,label [type=search].notEmpty:not(:focus)~span,label [type=search]:focus~span,label [type=tel].notEmpty:not(:focus)~span,label [type=tel]:focus~span,label [type=text].notEmpty:not(:focus)~span,label [type=text]:focus~span,label [type=time].notEmpty:not(:focus)~span,label [type=time]:focus~span,label [type=url].notEmpty:not(:focus)~span,label [type=url]:focus~span,label [type=week].notEmpty:not(:focus)~span,label [type=week]:focus~span,label input:not([type]).notEmpty:not(:focus)~span,label input:not([type]):focus~span,label input[type=text].notEmpty:not(:focus)~span,label input[type=text]:focus~span,label textarea.notEmpty:not(:focus)~span,label textarea:focus~span{top:-11px;left:0;bottom:0;font-size:11px;opacity:1}label [type=color]~span,label [type=date]~span,label [type=datetime-local]~span,label [type=datetime]~span,label [type=email]~span,label [type=month]~span,label [type=number]~span,label [type=password]~span,label [type=search]~span,label [type=tel]~span,label [type=text]~span,label [type=time]~span,label [type=url]~span,label [type=week]~span,label input:not([type])~span,label input[type=text]~span,label textarea~span{position:absolute;pointer-events:none;left:10px;bottom:10px;top:7px;-webkit-transition:all .2s ease;transition:all .2s ease}label textarea{height:10rem;border-top-right-radius:3px;border-top-left-radius:3px}label [type=checkbox].before-text{margin-bottom:0}.listjs{position:relative}.listjs label{display:inline-block}.listjs label input{margin-bottom:0}.listjs table{border-collapse:collapse}.listjs table tfoot tr th,.listjs table thead tr th{text-align:left}.listjs table tfoot tr th.sort,.listjs table thead tr th.sort{cursor:pointer}.listjs table tbody.list tr:first-child td{border-top:1px solid #696969}.listjs table tbody.list tr:last-child td{border-bottom:1px solid #696969}.listjs table tbody.list tr td{border-top:1px solid #c8c8c8;padding:.3rem}.listjs ul.pagination{float:right;display:inline-block;margin:0}.listjs ul.pagination li{display:inline-block;padding-left:5px;padding-right:5px;text-decoration:underline}.listjs ul.pagination li.active,.listjs ul.pagination li.disabled{text-decoration:none}.background{position:fixed;z-index:1000000;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgba(55,55,55,.6)}.background .modal{position:relative;top:50%;margin:auto;width:80%;-webkit-transform:translateY(-50%);transform:translateY(-50%);padding:.5rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;max-height:80%;max-width:1024px}@media screen and (max-width:63.9375em){.background .modal.small-margin{width:90%}}@media screen and (max-width:24.9375em){.background .modal.small-margin{width:95%}}.background .modal.max-small{max-width:0}.background .modal.max-smedium{max-width:400px}.background .modal.max-medium{max-width:640px}.background .modal.max-large{max-width:1024px}.background .modal.max-xlarge{max-width:1200px}.background .modal.max-xxlarge{max-width:1440px}.background .modal .title{font-weight:700;padding-bottom:.5rem}.background .modal .content-container{overflow-y:auto;max-height:100%}.background .modal .content-container .loader{position:static;-webkit-transform:none;transform:none}.background .modal .close{text-align:right;float:right;font-size:28px;font-weight:700;line-height:1}.background .modal .close:focus,.background .modal .close:hover{text-decoration:none;cursor:pointer}.background .modal .modal-button-container{padding-top:.5rem}.background .modal .modal-button-container .button{margin-left:.2rem;margin-bottom:0!important;padding:.6em .8em}@media screen and (max-width:24.9375em){.background .modal .modal-button-container .button{margin-left:.1rem;padding:.3em .5em}}.rotated{-webkit-transform-origin:bottom center;transform-origin:bottom center;height:50%;position:absolute;top:0;bottom:0;left:0;right:0}.share-icon{margin:.1rem}.share-icon,.share-icon svg{width:1.5rem;max-width:1.5rem}.tab-header-container .tab-header{display:inline-block;background-color:#eee;border:1px solid #b0b0b0;border-top-left-radius:4px;border-top-right-radius:4px;padding:0 5px}.tab-header-container .tab-header.active{border-bottom:0;background-color:#fff}*,:after,:before{-webkit-box-sizing:inherit;box-sizing:inherit}html{width:100%;font-size:18px;letter-spacing:1px}.max-height,html{min-height:100%;height:100%}body{margin:0;padding:0;height:100%;width:100%;font-family:Helvetica Neue,Helvetica,Roboto,Arial,sans-serif;font-weight:400;line-height:1.5;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;background:#fefefe;color:#0a0a0a}footer{border-top:1px solid #d8d8d8;text-align:center}.top-bar .top-bar-title strong{vertical-align:middle;display:inline-block}nav.top-bar{color:#fff;font-size:20px;-webkit-box-shadow:0 4px 5px 0 rgba(0,0,0,.14),0 2px 9px 1px rgba(0,0,0,.12),0 4px 2px -2px rgba(0,0,0,.2);box-shadow:0 4px 5px 0 rgba(0,0,0,.14),0 2px 9px 1px rgba(0,0,0,.12),0 4px 2px -2px rgba(0,0,0,.2);padding:.6rem;display:block}a.button,button.button{border-radius:2px}.fill-me{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-ms-flex-direction:column;flex-direction:column}.fill-me,.fill-me.vertical{-webkit-box-direction:normal}.fill-me.vertical{-webkit-box-orient:horizontal;-ms-flex-direction:row;flex-direction:row}.fill-me .grow{-webkit-box-flex:1;-ms-flex:1;flex:1}.flex-center{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.flex-center>*{max-height:100%}.dropdown.menu a,.menu a{padding:.4rem .5rem}svg path{fill:currentColor}div.mainContainer{position:relative;max-height:100%;max-width:100%;overflow:auto;-webkit-box-flex:1;-ms-flex:1;flex:1;margin:.5rem}div.mainContainer #main-content,div.mainContainer #site-content,div.mainContainer>.row{position:absolute;width:100%;height:100%;top:0;bottom:0;left:0;right:0}.inline-block{display:inline-block}.right{float:right}#logo-img{max-height:2.2rem}a{cursor:pointer}a,a.hidden-link{text-decoration:none;color:inherit}label{cursor:pointer}.align-right{text-align:right}.view-panel{display:none}.loader{left:50%;top:50%;position:fixed;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);text-align:center}.loader.inline{left:auto;top:auto;position:static;-webkit-transform:initial;transform:none;text-align:center;display:inline}.loader.small #spinner{-webkit-transform:scale(.5);transform:scale(.5)}.loader #spinner{-webkit-box-sizing:border-box;box-sizing:border-box;stroke:#b71c1a;stroke-width:3px;-webkit-transform-origin:50%;transform-origin:50%;-webkit-animation:line 1.6s cubic-bezier(.4,0,.2,1) infinite,rotate 1.6s linear infinite;animation:line 1.6s cubic-bezier(.4,0,.2,1) infinite,rotate 1.6s linear infinite}@-webkit-keyframes rotate{0%{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(450deg);transform:rotate(450deg)}}@keyframes rotate{0%{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(450deg);transform:rotate(450deg)}}@-webkit-keyframes line{0%{stroke-dasharray:2,85.964;-webkit-transform:rotate(0);transform:rotate(0)}50%{stroke-dasharray:65.973,21.9911;stroke-dashoffset:0}to{stroke-dasharray:2,85.964;stroke-dashoffset:-65.973;-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@keyframes line{0%{stroke-dasharray:2,85.964;-webkit-transform:rotate(0);transform:rotate(0)}50%{stroke-dasharray:65.973,21.9911;stroke-dashoffset:0}to{stroke-dasharray:2,85.964;stroke-dashoffset:-65.973;-webkit-transform:rotate(90deg);transform:rotate(90deg)}}#print-content{display:none}.action-button{max-height:1.7rem;margin-left:.4rem;margin-right:.4rem}.action-button:hover{background:#e8e8e8}.vcenter-container{width:100%;height:100%;display:table}.vcenter-container .vcenter{vertical-align:middle;display:table-cell;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.max-width{width:100%}button,input{letter-spacing:1px!important}.no-padding{padding:0;border:0}.center{text-align:center}@media print{#styles,.mainContainer,footer,nav{display:none!important}#print-content{display:block!important}}.overflow-y-auto{overflow-y:auto!important}.row.no-after:after{content:normal}.margin-bottom{margin-bottom:1rem}@media print,screen and (min-width:25em){.margin-bottom{margin-bottom:2rem}}@media print,screen and (min-width:40em){.margin-bottom{margin-bottom:3rem}}@media print,screen and (min-width:64em){.margin-bottom{margin-bottom:4rem}}@media screen and (min-width:75em){.margin-bottom{margin-bottom:5rem}}.font-small{font-size:.7em}.border-bottom{border-bottom:1px solid #cacaca}.border-right{border-right:1px solid #cacaca}.border-left{border-left:1px solid #cacaca}img.logo{vertical-align:inherit;display:inline-block;height:auto;max-width:1.1rem;margin-right:2px}.align-center{text-align:center}hr.separator{margin:1rem 0}.button-line{display:-webkit-box;display:-ms-flexbox;display:flex}.button-line .button{-webkit-box-flex:1;-ms-flex:1;flex:1;margin-left:1px;margin-right:1px;padding:.5rem .77rem}@media screen and (max-width:24.9375em){.small-small{font-size:small}}select{border:0;padding:.3rem}.hidden{display:none}img.action-image{max-height:1.4rem;cursor:pointer}img.back-button{max-height:.6rem;margin-right:.2rem;cursor:pointer;vertical-align:inherit}.no-margin-bottom{margin-bottom:0}div.flashMessage{font-size:.8rem;border-radius:25px;letter-spacing:0;z-index:1001;max-width:100%;display:inline-block;position:relative;-webkit-box-shadow:2px 2px 10px rgba(0,0,0,.28);box-shadow:2px 2px 10px rgba(0,0,0,.28);border:1px solid #626262;background-color:#6b6b6b;padding:.3em .6em;text-align:center;color:#fff}div.flashMessage:hover{opacity:.4;cursor:pointer}div.flashMessage:after,div.flashMessage:before{display:block;content:""}span.flashMessage{float:right;cursor:pointer}div.default{background-color:#1a9cc8}#flashMessageContainer{text-align:center;position:absolute}#flashMessageContainer,#flashMessageContainerAbsoulte{height:0!important;width:100%;overflow:visible!important}#flashMessageContainerAbsoulte{margin:5px 0;position:relative}.relative{position:relative}.no-transition,.no-transition *{-webkit-transition:none!important;transition:none!important}.settings-container{border:1px solid #000;border-radius:2px;padding:.3rem}@media print,screen and (min-width:40em){.settings-container #settings-fragments-container{border-left:1px solid #cacaca}}.settings-container #settings-fragments-container #settings-fragments>*{display:none}.settings-container #settings-fragments-container #settings-fragments>.active{display:block}.switch{position:relative;display:inline-block}@media screen and (max-width:24.9375em){.switch{font-size:.6em}}@media screen and (max-width:39.9375em){.switch{font-size:.7em}}.switch input{display:none}.switch input:checked+.slider:before{-webkit-transform:translateX(1.5em);transform:translateX(1.5em)}.switch .slider{display:inline-block;position:relative;cursor:pointer;width:3em;height:1.5em;border-radius:1.5em;background-color:#ccc;-webkit-transition:.4s;transition:.4s}.switch .slider:before{position:absolute;content:"";height:1.1em;width:1.1em;left:.15em;bottom:.15em;background-color:#fff;-webkit-transition:.4s;transition:.4s;border-radius:50%}.switch img,.switch svg{width:1.4em;display:inline;vertical-align:initial}.switch img path,.switch svg path{stroke-color:inherit}.zf-green{color:#68b604}.column:last-child:not(:first-child),.columns:last-child:not(:first-child){float:left}input[type=checkBox].form-control{height:24px;height:1.5rem;width:100%}[type=submit]{display:block;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;height:39px;height:2.4375rem;padding:8px;padding:.5rem;border:1px solid #cacaca;margin:0 0 16px;margin:0 0 1rem;font-family:inherit;font-size:16px;font-size:1rem;color:#0a0a0a;background-color:#fefefe;-webkit-box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);box-shadow:inset 0 1px 2px hsla(0,0%,4%,.1);border-radius:0;-webkit-transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:border-color .25s ease-in-out,-webkit-box-shadow .5s;transition:box-shadow .5s,border-color .25s ease-in-out;transition:box-shadow .5s,border-color .25s ease-in-out,-webkit-box-shadow .5s;-webkit-appearance:none;-moz-appearance:none}form ul li{color:red;font-size:12.8px;font-size:.8rem}.button-dropdown:after{border-color:#000 transparent transparent;border-width:.4em;border-style:solid;content:"";position:absolute;top:.4em;display:block;height:0;width:0;right:1em}.button-dropdown{position:relative;display:block;padding-right:2em}.button-dropdown.open:after{border-color:transparent transparent #000;top:0}a.ui-datepicker-next,a.ui-datepicker-prev{height:100%!important}div.container a.navbar-brand>img{display:inline;margin-right:4px}ul.menu.plain li.active a{background-color:#ededed;color:#000}ul.menu.plain li a{color:#000}ul.menu.plain li a:hover{color:#525252}ul.submenu{border-top:1px solid #bcbcbc;border-bottom:1px solid #bcbcbc;margin-left:10px}#cookie-compliance{line-height:1.2;font-size:.8rem;width:100%;margin:0;padding:.3rem 0}#cookie-compliance #close-cookie-msg{float:right;margin-bottom:0;margin-right:3px;padding:.4rem .8rem}.menu-container .button{text-align:center;width:100%}.height-5{height:5%}.max-height-5{max-height:5%}.width-5{width:5%}.max-width-5{max-width:5%}.height-10{height:10%}.max-height-10{max-height:10%}.width-10{width:10%}.max-width-10{max-width:10%}.height-15{height:15%}.max-height-15{max-height:15%}.width-15{width:15%}.max-width-15{max-width:15%}.height-20{height:20%}.max-height-20{max-height:20%}.width-20{width:20%}.max-width-20{max-width:20%}.height-25{height:25%}.max-height-25{max-height:25%}.width-25{width:25%}.max-width-25{max-width:25%}.height-30{height:30%}.max-height-30{max-height:30%}.width-30{width:30%}.max-width-30{max-width:30%}.height-35{height:35%}.max-height-35{max-height:35%}.width-35{width:35%}.max-width-35{max-width:35%}.height-40{height:40%}.max-height-40{max-height:40%}.width-40{width:40%}.max-width-40{max-width:40%}.height-45{height:45%}.max-height-45{max-height:45%}.width-45{width:45%}.max-width-45{max-width:45%}.height-50{height:50%}.max-height-50{max-height:50%}.width-50{width:50%}.max-width-50{max-width:50%}.height-55{height:55%}.max-height-55{max-height:55%}.width-55{width:55%}.max-width-55{max-width:55%}.height-60{height:60%}.max-height-60{max-height:60%}.width-60{width:60%}.max-width-60{max-width:60%}.height-65{height:65%}.max-height-65{max-height:65%}.width-65{width:65%}.max-width-65{max-width:65%}.height-70{height:70%}.max-height-70{max-height:70%}.width-70{width:70%}.max-width-70{max-width:70%}.height-75{height:75%}.max-height-75{max-height:75%}.width-75{width:75%}.max-width-75{max-width:75%}.height-80{height:80%}.max-height-80{max-height:80%}.width-80{width:80%}.max-width-80{max-width:80%}.height-85{height:85%}.max-height-85{max-height:85%}.width-85{width:85%}.max-width-85{max-width:85%}.height-90{height:90%}.max-height-90{max-height:90%}.width-90{width:90%}.max-width-90{max-width:90%}.height-95{height:95%}.max-height-95{max-height:95%}.width-95{width:95%}.max-width-95{max-width:95%}.height-100{height:100%}.max-height-100{max-height:100%}.width-100{width:100%}.max-width-100{max-width:100%}*{-webkit-transition:.25s ease-out,color .25s ease-out;transition:.25s ease-out,color .25s ease-out}body.red{background:#fff;color:#000}body.red #cookie-compliance{background-color:#870015;color:#fff}body.red #cookie-compliance a.link,body.red #cookie-compliance a.link:hover{color:#ff3d00;border-bottom-color:#ff3d00}body.red a.link{text-decoration:none;color:#ff3d00;border-bottom:none}body.red a.link:hover{color:#ff3d00;border-bottom-color:#ff3d00}body.red .loader #spinner{stroke:#b71c1a}body.red nav.top-bar{color:#fff;background:red}body.red .top-bar ul{background:red!important}body.red .top-bar ul a{color:#fff}body.red .switch input:checked+.slider,body.red a.button,body.red a.button.disabled,body.red a.button.disabled:focus,body.red a.button.disabled:hover,body.red a.button:hover,body.red button.button,body.red button.button.disabled,body.red button.button.disabled:focus,body.red button.button.disabled:hover,body.red button.button:hover{background-color:red}body.red .switch input:focus+.slider{-webkit-box-shadow:0 0 1px red;box-shadow:0 0 1px red}body.red label{color:#000}body.red .background .modal{background-color:#fff}body.red svg.fill-color,body.red svg .fill-color{fill:currentColor}body.red svg.fill-background,body.red svg .fill-background{fill:#fff}body.red label [type=color],body.red label [type=date],body.red label [type=datetime-local],body.red label [type=datetime],body.red label [type=email],body.red label [type=month],body.red label [type=number],body.red label [type=password],body.red label [type=search],body.red label [type=tel],body.red label [type=text],body.red label [type=time],body.red label [type=url],body.red label [type=week],body.red label input:not([type]),body.red label input[type=text],body.red label textarea{border-bottom:solid #000;background:#fff;color:#000}body.red label [type=color]:focus,body.red label [type=date]:focus,body.red label [type=datetime-local]:focus,body.red label [type=datetime]:focus,body.red label [type=email]:focus,body.red label [type=month]:focus,body.red label [type=number]:focus,body.red label [type=password]:focus,body.red label [type=search]:focus,body.red label [type=tel]:focus,body.red label [type=text]:focus,body.red label [type=time]:focus,body.red label [type=url]:focus,body.red label [type=week]:focus,body.red label input:not([type]):focus,body.red label input[type=text]:focus,body.red label textarea:focus{border-bottom:solid #000}body.red label [type=color].notEmpty:not(:focus)~span,body.red label [type=color]:focus~span,body.red label [type=date].notEmpty:not(:focus)~span,body.red label [type=date]:focus~span,body.red label [type=datetime-local].notEmpty:not(:focus)~span,body.red label [type=datetime-local]:focus~span,body.red label [type=datetime].notEmpty:not(:focus)~span,body.red label [type=datetime]:focus~span,body.red label [type=email].notEmpty:not(:focus)~span,body.red label [type=email]:focus~span,body.red label [type=month].notEmpty:not(:focus)~span,body.red label [type=month]:focus~span,body.red label [type=number].notEmpty:not(:focus)~span,body.red label [type=number]:focus~span,body.red label [type=password].notEmpty:not(:focus)~span,body.red label [type=password]:focus~span,body.red label [type=search].notEmpty:not(:focus)~span,body.red label [type=search]:focus~span,body.red label [type=tel].notEmpty:not(:focus)~span,body.red label [type=tel]:focus~span,body.red label [type=text].notEmpty:not(:focus)~span,body.red label [type=text]:focus~span,body.red label [type=time].notEmpty:not(:focus)~span,body.red label [type=time]:focus~span,body.red label [type=url].notEmpty:not(:focus)~span,body.red label [type=url]:focus~span,body.red label [type=week].notEmpty:not(:focus)~span,body.red label [type=week]:focus~span,body.red label input:not([type]).notEmpty:not(:focus)~span,body.red label input:not([type]):focus~span,body.red label input[type=text].notEmpty:not(:focus)~span,body.red label input[type=text]:focus~span,body.red label textarea.notEmpty:not(:focus)~span,body.red label textarea:focus~span{color:#000}body.red label [type=color]~span,body.red label [type=date]~span,body.red label [type=datetime-local]~span,body.red label [type=datetime]~span,body.red label [type=email]~span,body.red label [type=month]~span,body.red label [type=number]~span,body.red label [type=password]~span,body.red label [type=search]~span,body.red label [type=tel]~span,body.red label [type=text]~span,body.red label [type=time]~span,body.red label [type=url]~span,body.red label [type=week]~span,body.red label input:not([type])~span,body.red label input[type=text]~span,body.red label textarea~span{color:rgba(0,0,0,.65)}body.red label textarea{-webkit-box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important;box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important}body.red input.notEmpty:invalid{background-color:rgba(255,0,0,.65)}body.blue{background:#fff;color:#000}body.blue #cookie-compliance{background-color:#1a3062;color:#fff}body.blue #cookie-compliance a.link,body.blue #cookie-compliance a.link:hover{color:#546cfe;border-bottom-color:#546cfe}body.blue a.link{text-decoration:none;color:#546cfe;border-bottom:none}body.blue a.link:hover{color:#546cfe;border-bottom-color:#546cfe}body.blue .loader #spinner{stroke:#673ab7}body.blue nav.top-bar{color:#fff;background:#2c58ae}body.blue .top-bar ul{background:#2c58ae!important}body.blue .top-bar ul a{color:#fff}body.blue .switch input:checked+.slider,body.blue a.button,body.blue a.button.disabled,body.blue a.button.disabled:focus,body.blue a.button.disabled:hover,body.blue a.button:hover,body.blue button.button,body.blue button.button.disabled,body.blue button.button.disabled:focus,body.blue button.button.disabled:hover,body.blue button.button:hover{background-color:#2c58ae}body.blue .switch input:focus+.slider{-webkit-box-shadow:0 0 1px #2c58ae;box-shadow:0 0 1px #2c58ae}body.blue label{color:#000}body.blue .background .modal{background-color:#fff}body.blue svg.fill-color,body.blue svg .fill-color{fill:currentColor}body.blue svg.fill-background,body.blue svg .fill-background{fill:#fff}body.blue label [type=color],body.blue label [type=date],body.blue label [type=datetime-local],body.blue label [type=datetime],body.blue label [type=email],body.blue label [type=month],body.blue label [type=number],body.blue label [type=password],body.blue label [type=search],body.blue label [type=tel],body.blue label [type=text],body.blue label [type=time],body.blue label [type=url],body.blue label [type=week],body.blue label input:not([type]),body.blue label input[type=text],body.blue label textarea{border-bottom:solid #000;background:#fff;color:#000}body.blue label [type=color]:focus,body.blue label [type=date]:focus,body.blue label [type=datetime-local]:focus,body.blue label [type=datetime]:focus,body.blue label [type=email]:focus,body.blue label [type=month]:focus,body.blue label [type=number]:focus,body.blue label [type=password]:focus,body.blue label [type=search]:focus,body.blue label [type=tel]:focus,body.blue label [type=text]:focus,body.blue label [type=time]:focus,body.blue label [type=url]:focus,body.blue label [type=week]:focus,body.blue label input:not([type]):focus,body.blue label input[type=text]:focus,body.blue label textarea:focus{border-bottom:solid #000}body.blue label [type=color].notEmpty:not(:focus)~span,body.blue label [type=color]:focus~span,body.blue label [type=date].notEmpty:not(:focus)~span,body.blue label [type=date]:focus~span,body.blue label [type=datetime-local].notEmpty:not(:focus)~span,body.blue label [type=datetime-local]:focus~span,body.blue label [type=datetime].notEmpty:not(:focus)~span,body.blue label [type=datetime]:focus~span,body.blue label [type=email].notEmpty:not(:focus)~span,body.blue label [type=email]:focus~span,body.blue label [type=month].notEmpty:not(:focus)~span,body.blue label [type=month]:focus~span,body.blue label [type=number].notEmpty:not(:focus)~span,body.blue label [type=number]:focus~span,body.blue label [type=password].notEmpty:not(:focus)~span,body.blue label [type=password]:focus~span,body.blue label [type=search].notEmpty:not(:focus)~span,body.blue label [type=search]:focus~span,body.blue label [type=tel].notEmpty:not(:focus)~span,body.blue label [type=tel]:focus~span,body.blue label [type=text].notEmpty:not(:focus)~span,body.blue label [type=text]:focus~span,body.blue label [type=time].notEmpty:not(:focus)~span,body.blue label [type=time]:focus~span,body.blue label [type=url].notEmpty:not(:focus)~span,body.blue label [type=url]:focus~span,body.blue label [type=week].notEmpty:not(:focus)~span,body.blue label [type=week]:focus~span,body.blue label input:not([type]).notEmpty:not(:focus)~span,body.blue label input:not([type]):focus~span,body.blue label input[type=text].notEmpty:not(:focus)~span,body.blue label input[type=text]:focus~span,body.blue label textarea.notEmpty:not(:focus)~span,body.blue label textarea:focus~span{color:#000}body.blue label [type=color]~span,body.blue label [type=date]~span,body.blue label [type=datetime-local]~span,body.blue label [type=datetime]~span,body.blue label [type=email]~span,body.blue label [type=month]~span,body.blue label [type=number]~span,body.blue label [type=password]~span,body.blue label [type=search]~span,body.blue label [type=tel]~span,body.blue label [type=text]~span,body.blue label [type=time]~span,body.blue label [type=url]~span,body.blue label [type=week]~span,body.blue label input:not([type])~span,body.blue label input[type=text]~span,body.blue label textarea~span{color:rgba(0,0,0,.65)}body.blue label textarea{-webkit-box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important;box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important}body.blue input.notEmpty:invalid{background-color:rgba(44,88,174,.65)}body.green{background:#fff;color:#000}body.green #cookie-compliance{background-color:#003613;color:#fff}body.green #cookie-compliance a.link,body.green #cookie-compliance a.link:hover{color:#009829;border-bottom-color:#009829}body.green a.link{text-decoration:none;color:#009829;border-bottom:none}body.green a.link:hover{color:#009829;border-bottom-color:#009829}body.green .loader #spinner{stroke:green}body.green nav.top-bar{color:#fff;background:green}body.green .top-bar ul{background:green!important}body.green .top-bar ul a{color:#fff}body.green .switch input:checked+.slider,body.green a.button,body.green a.button.disabled,body.green a.button.disabled:focus,body.green a.button.disabled:hover,body.green a.button:hover,body.green button.button,body.green button.button.disabled,body.green button.button.disabled:focus,body.green button.button.disabled:hover,body.green button.button:hover{background-color:green}body.green .switch input:focus+.slider{-webkit-box-shadow:0 0 1px green;box-shadow:0 0 1px green}body.green label{color:#000}body.green .background .modal{background-color:#fff}body.green svg.fill-color,body.green svg .fill-color{fill:currentColor}body.green svg.fill-background,body.green svg .fill-background{fill:#fff}body.green label [type=color],body.green label [type=date],body.green label [type=datetime-local],body.green label [type=datetime],body.green label [type=email],body.green label [type=month],body.green label [type=number],body.green label [type=password],body.green label [type=search],body.green label [type=tel],body.green label [type=text],body.green label [type=time],body.green label [type=url],body.green label [type=week],body.green label input:not([type]),body.green label input[type=text],body.green label textarea{border-bottom:solid #000;background:#fff;color:#000}body.green label [type=color]:focus,body.green label [type=date]:focus,body.green label [type=datetime-local]:focus,body.green label [type=datetime]:focus,body.green label [type=email]:focus,body.green label [type=month]:focus,body.green label [type=number]:focus,body.green label [type=password]:focus,body.green label [type=search]:focus,body.green label [type=tel]:focus,body.green label [type=text]:focus,body.green label [type=time]:focus,body.green label [type=url]:focus,body.green label [type=week]:focus,body.green label input:not([type]):focus,body.green label input[type=text]:focus,body.green label textarea:focus{border-bottom:solid #000}body.green label [type=color].notEmpty:not(:focus)~span,body.green label [type=color]:focus~span,body.green label [type=date].notEmpty:not(:focus)~span,body.green label [type=date]:focus~span,body.green label [type=datetime-local].notEmpty:not(:focus)~span,body.green label [type=datetime-local]:focus~span,body.green label [type=datetime].notEmpty:not(:focus)~span,body.green label [type=datetime]:focus~span,body.green label [type=email].notEmpty:not(:focus)~span,body.green label [type=email]:focus~span,body.green label [type=month].notEmpty:not(:focus)~span,body.green label [type=month]:focus~span,body.green label [type=number].notEmpty:not(:focus)~span,body.green label [type=number]:focus~span,body.green label [type=password].notEmpty:not(:focus)~span,body.green label [type=password]:focus~span,body.green label [type=search].notEmpty:not(:focus)~span,body.green label [type=search]:focus~span,body.green label [type=tel].notEmpty:not(:focus)~span,body.green label [type=tel]:focus~span,body.green label [type=text].notEmpty:not(:focus)~span,body.green label [type=text]:focus~span,body.green label [type=time].notEmpty:not(:focus)~span,body.green label [type=time]:focus~span,body.green label [type=url].notEmpty:not(:focus)~span,body.green label [type=url]:focus~span,body.green label [type=week].notEmpty:not(:focus)~span,body.green label [type=week]:focus~span,body.green label input:not([type]).notEmpty:not(:focus)~span,body.green label input:not([type]):focus~span,body.green label input[type=text].notEmpty:not(:focus)~span,body.green label input[type=text]:focus~span,body.green label textarea.notEmpty:not(:focus)~span,body.green label textarea:focus~span{color:#000}body.green label [type=color]~span,body.green label [type=date]~span,body.green label [type=datetime-local]~span,body.green label [type=datetime]~span,body.green label [type=email]~span,body.green label [type=month]~span,body.green label [type=number]~span,body.green label [type=password]~span,body.green label [type=search]~span,body.green label [type=tel]~span,body.green label [type=text]~span,body.green label [type=time]~span,body.green label [type=url]~span,body.green label [type=week]~span,body.green label input:not([type])~span,body.green label input[type=text]~span,body.green label textarea~span{color:rgba(0,0,0,.65)}body.green label textarea{-webkit-box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important;box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important}body.green input.notEmpty:invalid{background-color:rgba(0,128,0,.65)}body.pink{background:#fff;color:#000}body.pink #cookie-compliance{background-color:#70374a;color:#fff}body.pink #cookie-compliance a.link,body.pink #cookie-compliance a.link:hover{color:#fe64af;border-bottom-color:#fe64af}body.pink a.link{text-decoration:none;color:#fe64af;border-bottom:none}body.pink a.link:hover{color:#fe64af;border-bottom-color:#fe64af}body.pink .loader #spinner{stroke:#ff69b4}body.pink nav.top-bar{color:#fff;background:#ff69b4}body.pink .top-bar ul{background:#ff69b4!important}body.pink .top-bar ul a{color:#fff}body.pink .switch input:checked+.slider,body.pink a.button,body.pink a.button.disabled,body.pink a.button.disabled:focus,body.pink a.button.disabled:hover,body.pink a.button:hover,body.pink button.button,body.pink button.button.disabled,body.pink button.button.disabled:focus,body.pink button.button.disabled:hover,body.pink button.button:hover{background-color:#ff69b4}body.pink .switch input:focus+.slider{-webkit-box-shadow:0 0 1px #ff69b4;box-shadow:0 0 1px #ff69b4}body.pink label{color:#000}body.pink .background .modal{background-color:#fff}body.pink svg.fill-color,body.pink svg .fill-color{fill:currentColor}body.pink svg.fill-background,body.pink svg .fill-background{fill:#fff}body.pink label [type=color],body.pink label [type=date],body.pink label [type=datetime-local],body.pink label [type=datetime],body.pink label [type=email],body.pink label [type=month],body.pink label [type=number],body.pink label [type=password],body.pink label [type=search],body.pink label [type=tel],body.pink label [type=text],body.pink label [type=time],body.pink label [type=url],body.pink label [type=week],body.pink label input:not([type]),body.pink label input[type=text],body.pink label textarea{border-bottom:solid #000;background:#fff;color:#000}body.pink label [type=color]:focus,body.pink label [type=date]:focus,body.pink label [type=datetime-local]:focus,body.pink label [type=datetime]:focus,body.pink label [type=email]:focus,body.pink label [type=month]:focus,body.pink label [type=number]:focus,body.pink label [type=password]:focus,body.pink label [type=search]:focus,body.pink label [type=tel]:focus,body.pink label [type=text]:focus,body.pink label [type=time]:focus,body.pink label [type=url]:focus,body.pink label [type=week]:focus,body.pink label input:not([type]):focus,body.pink label input[type=text]:focus,body.pink label textarea:focus{border-bottom:solid #000}body.pink label [type=color].notEmpty:not(:focus)~span,body.pink label [type=color]:focus~span,body.pink label [type=date].notEmpty:not(:focus)~span,body.pink label [type=date]:focus~span,body.pink label [type=datetime-local].notEmpty:not(:focus)~span,body.pink label [type=datetime-local]:focus~span,body.pink label [type=datetime].notEmpty:not(:focus)~span,body.pink label [type=datetime]:focus~span,body.pink label [type=email].notEmpty:not(:focus)~span,body.pink label [type=email]:focus~span,body.pink label [type=month].notEmpty:not(:focus)~span,body.pink label [type=month]:focus~span,body.pink label [type=number].notEmpty:not(:focus)~span,body.pink label [type=number]:focus~span,body.pink label [type=password].notEmpty:not(:focus)~span,body.pink label [type=password]:focus~span,body.pink label [type=search].notEmpty:not(:focus)~span,body.pink label [type=search]:focus~span,body.pink label [type=tel].notEmpty:not(:focus)~span,body.pink label [type=tel]:focus~span,body.pink label [type=text].notEmpty:not(:focus)~span,body.pink label [type=text]:focus~span,body.pink label [type=time].notEmpty:not(:focus)~span,body.pink label [type=time]:focus~span,body.pink label [type=url].notEmpty:not(:focus)~span,body.pink label [type=url]:focus~span,body.pink label [type=week].notEmpty:not(:focus)~span,body.pink label [type=week]:focus~span,body.pink label input:not([type]).notEmpty:not(:focus)~span,body.pink label input:not([type]):focus~span,body.pink label input[type=text].notEmpty:not(:focus)~span,body.pink label input[type=text]:focus~span,body.pink label textarea.notEmpty:not(:focus)~span,body.pink label textarea:focus~span{color:#000}body.pink label [type=color]~span,body.pink label [type=date]~span,body.pink label [type=datetime-local]~span,body.pink label [type=datetime]~span,body.pink label [type=email]~span,body.pink label [type=month]~span,body.pink label [type=number]~span,body.pink label [type=password]~span,body.pink label [type=search]~span,body.pink label [type=tel]~span,body.pink label [type=text]~span,body.pink label [type=time]~span,body.pink label [type=url]~span,body.pink label [type=week]~span,body.pink label input:not([type])~span,body.pink label input[type=text]~span,body.pink label textarea~span{color:rgba(0,0,0,.65)}body.pink label textarea{-webkit-box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important;box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important}body.pink input.notEmpty:invalid{background-color:rgba(255,105,180,.65)}body.black{background:#fff;color:#000}body.black #cookie-compliance{background-color:#353535;color:#fff}body.black #cookie-compliance a.link{color:#fff;border-bottom-color:#fff}body.black #cookie-compliance a.link:hover{color:#cacaca;border-bottom-color:#cacaca}body.black a.link{text-decoration:none;color:#000;border-bottom:1px solid #000}body.black a.link:hover{color:#4e4e4e;border-bottom-color:#4e4e4e}body.black .loader #spinner{stroke:#000}body.black nav.top-bar{color:#fff;background:#000}body.black .top-bar ul{background:#000!important}body.black .top-bar ul a{color:#fff}body.black .switch input:checked+.slider,body.black a.button,body.black a.button.disabled,body.black a.button.disabled:focus,body.black a.button.disabled:hover,body.black a.button:hover,body.black button.button,body.black button.button.disabled,body.black button.button.disabled:focus,body.black button.button.disabled:hover,body.black button.button:hover{background-color:#000}body.black .switch input:focus+.slider{-webkit-box-shadow:0 0 1px #000;box-shadow:0 0 1px #000}body.black label{color:#000}body.black .background .modal{background-color:#fff}body.black svg.fill-color,body.black svg .fill-color{fill:currentColor}body.black svg.fill-background,body.black svg .fill-background{fill:#fff}body.black label [type=color],body.black label [type=date],body.black label [type=datetime-local],body.black label [type=datetime],body.black label [type=email],body.black label [type=month],body.black label [type=number],body.black label [type=password],body.black label [type=search],body.black label [type=tel],body.black label [type=text],body.black label [type=time],body.black label [type=url],body.black label [type=week],body.black label input:not([type]),body.black label input[type=text],body.black label textarea{border-bottom:solid #000;background:#fff;color:#000}body.black label [type=color]:focus,body.black label [type=date]:focus,body.black label [type=datetime-local]:focus,body.black label [type=datetime]:focus,body.black label [type=email]:focus,body.black label [type=month]:focus,body.black label [type=number]:focus,body.black label [type=password]:focus,body.black label [type=search]:focus,body.black label [type=tel]:focus,body.black label [type=text]:focus,body.black label [type=time]:focus,body.black label [type=url]:focus,body.black label [type=week]:focus,body.black label input:not([type]):focus,body.black label input[type=text]:focus,body.black label textarea:focus{border-bottom:solid #000}body.black label [type=color].notEmpty:not(:focus)~span,body.black label [type=color]:focus~span,body.black label [type=date].notEmpty:not(:focus)~span,body.black label [type=date]:focus~span,body.black label [type=datetime-local].notEmpty:not(:focus)~span,body.black label [type=datetime-local]:focus~span,body.black label [type=datetime].notEmpty:not(:focus)~span,body.black label [type=datetime]:focus~span,body.black label [type=email].notEmpty:not(:focus)~span,body.black label [type=email]:focus~span,body.black label [type=month].notEmpty:not(:focus)~span,body.black label [type=month]:focus~span,body.black label [type=number].notEmpty:not(:focus)~span,body.black label [type=number]:focus~span,body.black label [type=password].notEmpty:not(:focus)~span,body.black label [type=password]:focus~span,body.black label [type=search].notEmpty:not(:focus)~span,body.black label [type=search]:focus~span,body.black label [type=tel].notEmpty:not(:focus)~span,body.black label [type=tel]:focus~span,body.black label [type=text].notEmpty:not(:focus)~span,body.black label [type=text]:focus~span,body.black label [type=time].notEmpty:not(:focus)~span,body.black label [type=time]:focus~span,body.black label [type=url].notEmpty:not(:focus)~span,body.black label [type=url]:focus~span,body.black label [type=week].notEmpty:not(:focus)~span,body.black label [type=week]:focus~span,body.black label input:not([type]).notEmpty:not(:focus)~span,body.black label input:not([type]):focus~span,body.black label input[type=text].notEmpty:not(:focus)~span,body.black label input[type=text]:focus~span,body.black label textarea.notEmpty:not(:focus)~span,body.black label textarea:focus~span{color:#000}body.black label [type=color]~span,body.black label [type=date]~span,body.black label [type=datetime-local]~span,body.black label [type=datetime]~span,body.black label [type=email]~span,body.black label [type=month]~span,body.black label [type=number]~span,body.black label [type=password]~span,body.black label [type=search]~span,body.black label [type=tel]~span,body.black label [type=text]~span,body.black label [type=time]~span,body.black label [type=url]~span,body.black label [type=week]~span,body.black label input:not([type])~span,body.black label input[type=text]~span,body.black label textarea~span{color:rgba(0,0,0,.65)}body.black label textarea{-webkit-box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important;box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important}body.black input.notEmpty:invalid{background-color:rgba(0,0,0,.65)}body.dark{background:#000;color:#fff}body.dark #cookie-compliance{background-color:#4b4b4b;color:#fff}body.dark #cookie-compliance a.link,body.dark #cookie-compliance a.link:hover{color:#fff;border-bottom-color:#fff}body.dark a.link{text-decoration:none;color:#fff;border-bottom:1px solid #fff}body.dark a.link:hover{color:#fff;border-bottom-color:#fff}body.dark .loader #spinner{stroke:#fff}body.dark nav.top-bar{color:#fff;background:#373737}body.dark .top-bar ul{background:#373737!important}body.dark .top-bar ul a{color:#fff}body.dark .switch input:checked+.slider,body.dark a.button,body.dark a.button.disabled,body.dark a.button.disabled:focus,body.dark a.button.disabled:hover,body.dark a.button:hover,body.dark button.button,body.dark button.button.disabled,body.dark button.button.disabled:focus,body.dark button.button.disabled:hover,body.dark button.button:hover{background-color:#373737}body.dark .switch input:focus+.slider{-webkit-box-shadow:0 0 1px #373737;box-shadow:0 0 1px #373737}body.dark label{color:#fff}body.dark .background .modal{background-color:#000}body.dark svg.fill-color,body.dark svg .fill-color{fill:currentColor}body.dark svg.fill-background,body.dark svg .fill-background{fill:#000}body.dark label [type=color],body.dark label [type=date],body.dark label [type=datetime-local],body.dark label [type=datetime],body.dark label [type=email],body.dark label [type=month],body.dark label [type=number],body.dark label [type=password],body.dark label [type=search],body.dark label [type=tel],body.dark label [type=text],body.dark label [type=time],body.dark label [type=url],body.dark label [type=week],body.dark label input:not([type]),body.dark label input[type=text],body.dark label textarea{border-bottom:solid #fff;background:#000;color:#fff}body.dark label [type=color]:focus,body.dark label [type=date]:focus,body.dark label [type=datetime-local]:focus,body.dark label [type=datetime]:focus,body.dark label [type=email]:focus,body.dark label [type=month]:focus,body.dark label [type=number]:focus,body.dark label [type=password]:focus,body.dark label [type=search]:focus,body.dark label [type=tel]:focus,body.dark label [type=text]:focus,body.dark label [type=time]:focus,body.dark label [type=url]:focus,body.dark label [type=week]:focus,body.dark label input:not([type]):focus,body.dark label input[type=text]:focus,body.dark label textarea:focus{border-bottom:solid #fff}body.dark label [type=color].notEmpty:not(:focus)~span,body.dark label [type=color]:focus~span,body.dark label [type=date].notEmpty:not(:focus)~span,body.dark label [type=date]:focus~span,body.dark label [type=datetime-local].notEmpty:not(:focus)~span,body.dark label [type=datetime-local]:focus~span,body.dark label [type=datetime].notEmpty:not(:focus)~span,body.dark label [type=datetime]:focus~span,body.dark label [type=email].notEmpty:not(:focus)~span,body.dark label [type=email]:focus~span,body.dark label [type=month].notEmpty:not(:focus)~span,body.dark label [type=month]:focus~span,body.dark label [type=number].notEmpty:not(:focus)~span,body.dark label [type=number]:focus~span,body.dark label [type=password].notEmpty:not(:focus)~span,body.dark label [type=password]:focus~span,body.dark label [type=search].notEmpty:not(:focus)~span,body.dark label [type=search]:focus~span,body.dark label [type=tel].notEmpty:not(:focus)~span,body.dark label [type=tel]:focus~span,body.dark label [type=text].notEmpty:not(:focus)~span,body.dark label [type=text]:focus~span,body.dark label [type=time].notEmpty:not(:focus)~span,body.dark label [type=time]:focus~span,body.dark label [type=url].notEmpty:not(:focus)~span,body.dark label [type=url]:focus~span,body.dark label [type=week].notEmpty:not(:focus)~span,body.dark label [type=week]:focus~span,body.dark label input:not([type]).notEmpty:not(:focus)~span,body.dark label input:not([type]):focus~span,body.dark label input[type=text].notEmpty:not(:focus)~span,body.dark label input[type=text]:focus~span,body.dark label textarea.notEmpty:not(:focus)~span,body.dark label textarea:focus~span{color:#fff}body.dark label [type=color]~span,body.dark label [type=date]~span,body.dark label [type=datetime-local]~span,body.dark label [type=datetime]~span,body.dark label [type=email]~span,body.dark label [type=month]~span,body.dark label [type=number]~span,body.dark label [type=password]~span,body.dark label [type=search]~span,body.dark label [type=tel]~span,body.dark label [type=text]~span,body.dark label [type=time]~span,body.dark label [type=url]~span,body.dark label [type=week]~span,body.dark label input:not([type])~span,body.dark label input[type=text]~span,body.dark label textarea~span{color:hsla(0,0%,100%,.65)}body.dark label textarea{-webkit-box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important;box-shadow:0 0 3px 2px hsla(0,0%,53%,.31)!important}body.dark input.notEmpty:invalid{background-color:rgba(55,55,55,.65)}@-webkit-keyframes tutorialPointer{0%{top:25%}to{top:75%}}@keyframes tutorialPointer{0%{top:25%}to{top:75%}}.tutorial-blanket{display:none;position:fixed;top:0;bottom:0;left:0;right:0;z-index:9001;background:rgba(98,98,98,.51)}.tutorial .tutorial-blanket{display:block}.tutorial .tutorial-text{color:#fff;font-size:1.5rem;display:-webkit-box;display:-ms-flexbox;display:flex}.tutorial .tutorial-text,.tutorial .tutorial-text *{-webkit-transition:none!important;transition:none!important}.tutorial.step-1 #level .segment-row{position:inherit}.tutorial.step-1 #level .segment-parent:nth-child(3),.tutorial.step-1 #level .segment-parent:nth-child(3).rotating{z-index:9900!important}.tutorial.step-1 .tutorial-text .step-1{display:initial;z-index:9900!important;position:relative}.tutorial.step-2 #level{z-index:9900!important}.tutorial.step-2 .tutorial-text .step-2,.tutorial.step-3 .tutorial-text .step-3{display:initial;z-index:9900!important;position:relative}.tutorial.step-3 #help-button{position:relative;z-index:9900!important;overflow:visible;margin-right:10px;margin-top:10px;-webkit-box-shadow:0 0 10px 5px #fff;box-shadow:0 0 10px 5px #fff}.tutorial.step-4 .tutorial-text .step-4{display:initial;z-index:9900!important;position:relative}.tutorial.step-4 #level .segment-row{position:inherit}.tutorial.step-4 #level .segment-row>.child-container .segment-parent.layer-2,.tutorial.step-4 #level .segment-row>.child-container>.segment-parent.layer-2.rotating{z-index:9900!important}.tutorial.step-4 #level .segment-row>.child-container .segment-parent.layer-2 #tutorial-pointer,.tutorial.step-4 #level .segment-row>.child-container>.segment-parent.layer-2.rotating #tutorial-pointer{width:.6em;height:.6em;border-radius:50%;left:75%;position:absolute;top:75%;z-index:1;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);-webkit-animation:tutorialPointer 2s infinite;animation:tutorialPointer 2s infinite;pointer-events:none}body.red #tutorial-pointer{background:red}body.red #level-number-container.in-main-menu{background:#fff;border-color:#000}body.red .segment.segment-parent{border-color:#555}body.red .segment.segment-parent.layer-2{border-color:#000}body.red #site-content>:not(.won) .segment.locked{border-color:#870015;background-color:red!important}body.red .segment:not(.segment-row):not(.segment-triangle).rotate-90,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-90,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-180,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-270,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-360,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-180,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-90,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-180,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-270,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-360,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-270,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-90,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-180,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-270,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-360,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-360,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-90,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-180,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-270,body.red .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-360{background-color:#fff}body.blue #tutorial-pointer{background:#2c58ae}body.blue #level-number-container.in-main-menu{background:#fff;border-color:#000}body.blue .segment.segment-parent{border-color:#555}body.blue .segment.segment-parent.layer-2{border-color:#000}body.blue #site-content>:not(.won) .segment.locked{border-color:#1a3062;background-color:#2c58ae!important}body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-90,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-90,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-180,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-270,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-360,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-180,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-90,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-180,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-270,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-360,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-270,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-90,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-180,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-270,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-360,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-360,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-90,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-180,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-270,body.blue .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-360{background-color:#fff}body.green #tutorial-pointer{background:green}body.green #level-number-container.in-main-menu{background:#fff;border-color:#000}body.green .segment.segment-parent{border-color:#555}body.green .segment.segment-parent.layer-2{border-color:#000}body.green #site-content>:not(.won) .segment.locked{border-color:#003613;background-color:green!important}body.green .segment:not(.segment-row):not(.segment-triangle).rotate-90,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-90,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-180,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-270,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-360,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-180,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-90,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-180,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-270,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-360,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-270,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-90,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-180,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-270,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-360,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-360,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-90,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-180,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-270,body.green .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-360{background-color:#fff}body.pink #tutorial-pointer{background:#ff69b4}body.pink #level-number-container.in-main-menu{background:#fff;border-color:#000}body.pink .segment.segment-parent{border-color:#555}body.pink .segment.segment-parent.layer-2{border-color:#000}body.pink #site-content>:not(.won) .segment.locked{border-color:#70374a;background-color:#ff69b4!important}body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-90,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-90,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-180,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-270,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-360,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-180,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-90,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-180,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-270,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-360,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-270,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-90,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-180,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-270,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-360,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-360,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-90,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-180,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-270,body.pink .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-360{background-color:#fff}body.black #tutorial-pointer{background:#000}body.black #level-number-container.in-main-menu{background:#fff;border-color:#000}body.black .segment.segment-parent{border-color:#555}body.black .segment.segment-parent.layer-2{border-color:#000}body.black #site-content>:not(.won) .segment.locked{border-color:#353535;background-color:#000!important}body.black .segment:not(.segment-row):not(.segment-triangle).rotate-90,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-90,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-180,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-270,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-360,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-180,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-90,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-180,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-270,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-360,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-270,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-90,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-180,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-270,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-360,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-360,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-90,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-180,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-270,body.black .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-360{background-color:#fff}body.dark #tutorial-pointer{background:#373737}body.dark #level-number-container.in-main-menu{background:#000;border-color:#fff}body.dark .segment.segment-parent{border-color:#9b9b9b}body.dark .segment.segment-parent.layer-2{border-color:#fff}body.dark #site-content>:not(.won) .segment.locked{border-color:#4b4b4b;background-color:#373737!important}body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-90,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-90,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-180,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-270,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-90>.child-container>.segment.rotate-360,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-180,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-90,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-180,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-270,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-180>.child-container>.segment.rotate-360,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-270,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-90,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-180,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-270,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-270>.child-container>.segment.rotate-360,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-360,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-90,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-180,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-270,body.dark .segment:not(.segment-row):not(.segment-triangle).rotate-360>.child-container>.segment.rotate-360{background-color:#000}body.dark .switch input:checked+.slider{border-color:#000}body.dark .switch .slider{border:1px solid #fff;background-color:inherit;padding:1px}body.dark #site-content>:not(.won) .segment.locked.layer-2{border-color:#565656}body.dark .modal{border:1px solid #fff;border-radius:2px}body.black #site-content>:not(.won) .segment.locked{background-color:#9d9d9d!important;border-color:#6e6e6e!important}body.black #site-content>:not(.won) .segment.locked>.child-container>.segment-leaf{background-color:transparent!important}body.black #logo{border:1px solid grey;border-radius:50%}body label{font-size:1em!important}body .setting-row:not(.hidden){line-height:1;padding-top:.5em;padding-bottom:.5em;width:100%;cursor:pointer;background:hsla(0,0%,76%,.13);display:inline-block}nav.top-bar.title-bar{padding:.3rem .6rem 0}#logo{max-width:2rem;-webkit-transition:none;transition:none}#action-bar .top-bar-right .menu .action.img a{padding-bottom:0}#action-bar .top-bar-right .menu .action.img a img{max-height:1.8rem}.dropdown.menu a,.menu a{padding:.2rem .5rem}.relative-level-number{position:relative}.relative-level-number #level-number-container{top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}#level-number-container{z-index:1;-webkit-transition:none;transition:none;position:absolute;left:50%;-webkit-transform:translate(-50%);transform:translate(-50%);border:3px solid #fff;border-radius:50%;visibility:hidden;display:table-cell;height:35px;width:35px;text-align:center;vertical-align:middle}#level-number-container.visible{visibility:visible}#level-number-container.in-main-menu{background:#fff;border-color:#000;height:1em;width:1em;min-height:1em;min-width:1em;max-height:1em;max-width:1em}#level-number-container #level-number{-webkit-transition:none;transition:none;position:absolute;left:50%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);font-weight:700}.coin-counter{display:inline-block;position:relative;font-size:1.6rem}@media screen and (max-width:24.9375em){.coin-counter{font-size:1rem}}.coin-counter :after{background-image:url(../img/coinTower.png);background-size:28px 28px;width:28px;height:28px;display:inline-block;content:""}#coin-container{line-height:1}#coin-container .coin{margin-left:3px;margin-right:3px;max-width:20px;display:inline-block}@media print,screen and (min-width:25em){#coin-container .coin{max-width:25px}}@media print,screen and (min-width:40em){#coin-container .coin{max-width:30px}}@-webkit-keyframes rotate-90{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@keyframes rotate-90{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@-webkit-keyframes rotate-reverse-90{0%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}to{-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@keyframes rotate-reverse-90{0%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}to{-webkit-transform:rotate(90deg);transform:rotate(90deg)}}@-webkit-keyframes rotate-180{0%{-webkit-transform:rotate(90deg);transform:rotate(90deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@keyframes rotate-180{0%{-webkit-transform:rotate(90deg);transform:rotate(90deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@-webkit-keyframes rotate-reverse-180{0%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@keyframes rotate-reverse-180{0%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@-webkit-keyframes rotate-270{0%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}to{-webkit-transform:rotate(270deg);transform:rotate(270deg)}}@keyframes rotate-270{0%{-webkit-transform:rotate(180deg);transform:rotate(180deg)}to{-webkit-transform:rotate(270deg);transform:rotate(270deg)}}@-webkit-keyframes rotate-reverse-270{0%{-webkit-transform:rotate(1turn);transform:rotate(1turn)}to{-webkit-transform:rotate(270deg);transform:rotate(270deg)}}@keyframes rotate-reverse-270{0%{-webkit-transform:rotate(1turn);transform:rotate(1turn)}to{-webkit-transform:rotate(270deg);transform:rotate(270deg)}}@-webkit-keyframes rotate-360{0%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes rotate-360{0%{-webkit-transform:rotate(270deg);transform:rotate(270deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@-webkit-keyframes rotate-reverse-360{0%{-webkit-transform:rotate(450deg);transform:rotate(450deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes rotate-reverse-360{0%{-webkit-transform:rotate(450deg);transform:rotate(450deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.segment:not(.segment-row):not(.segment-triangle).rotating{z-index:10!important;overflow:hidden}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;animation-direction:reverse;-webkit-animation-direction:reverse;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-90;animation-name:rotate-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-180;animation-name:rotate-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-270;animation-name:rotate-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-360;animation-name:rotate-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-90.reverse>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;animation-direction:reverse;-webkit-animation-direction:reverse;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-360;animation-name:rotate-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-90;animation-name:rotate-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-180;animation-name:rotate-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-270;animation-name:rotate-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-180.reverse>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;animation-direction:reverse;-webkit-animation-direction:reverse;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-270;animation-name:rotate-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-360;animation-name:rotate-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-90;animation-name:rotate-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-180;animation-name:rotate-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-270.reverse>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;animation-direction:reverse;-webkit-animation-direction:reverse;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-180;animation-name:rotate-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-270;animation-name:rotate-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-360;animation-name:rotate-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-90;animation-name:rotate-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment.rotate-90{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment.rotate-180{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment.rotate-270{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle).rotating.rotate-360.reverse>.child-container>.segment.rotate-360{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-90{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-90.rotating{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-90.rotating.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-180{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-180.rotating{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-180.rotating.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-270{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-270.rotating{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-270.rotating.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-360{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-360.rotating{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-90>.child-container>.segment.rotate-360.rotating.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180,.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-90{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-90.rotating{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-90.rotating.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-180{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-180.rotating{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-180.rotating.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-270{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-270.rotating{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-270.rotating.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-360{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-360.rotating{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-180>.child-container>.segment.rotate-360.rotating.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-90{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-90.rotating{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-90.rotating.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-180{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-180.rotating{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-180.rotating.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-270{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-270.rotating{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-270.rotating.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-360{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-360.rotating{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-270>.child-container>.segment.rotate-360.rotating.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment{-webkit-transform:rotate(0deg);transform:rotate(0deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-90.rotating{-webkit-animation-name:rotate-90;animation-name:rotate-90;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-90.rotating.reverse{-webkit-animation-name:rotate-reverse-90;animation-name:rotate-reverse-90}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-180{-webkit-transform:rotate(180deg);transform:rotate(180deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-180.rotating{-webkit-animation-name:rotate-180;animation-name:rotate-180;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-180.rotating.reverse{-webkit-animation-name:rotate-reverse-180;animation-name:rotate-reverse-180}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-270.rotating{-webkit-animation-name:rotate-270;animation-name:rotate-270;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-270.rotating.reverse{-webkit-animation-name:rotate-reverse-270;animation-name:rotate-reverse-270}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-360{-webkit-transform:rotate(1turn);transform:rotate(1turn);background-color:inherit;z-index:1}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-360.rotating{-webkit-animation-name:rotate-360;animation-name:rotate-360;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:linear;animation-timing-function:linear}.segment:not(.segment-row):not(.segment-triangle):not(.rotating).rotate-360>.child-container>.segment.rotate-360.rotating.reverse{-webkit-animation-name:rotate-reverse-360;animation-name:rotate-reverse-360}#level{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;white-space:nowrap;max-width:100%;-webkit-tap-highlight-color:rgba(255,255,255,0);overflow-y:visible}#level,#level *,.segment{-webkit-transition:none;transition:none}.segment{vertical-align:top;white-space:normal;cursor:pointer;display:inline-block;text-align:center;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:1;background-color:inherit;line-height:0}.segment.segment-row{display:block;width:100%;-webkit-animation:none!important;animation:none!important;white-space:nowrap}.segment.segment-column{padding-top:4px}.segment.segment-column>.child-container>.segment{display:block;width:100%}.segment.segment-leaf{background-color:transparent!important;min-width:1em;padding:.8em}.segment.segment-leaf:before{content:" ";display:block;padding-top:100%}.segment.segment-leaf .leaf-element{position:absolute;width:100%;height:100%;line-height:1.5em;top:0;left:0}.segment.segment-parent{border:1px solid #a9a9a9;border-radius:3px;padding:1px}.segment.segment-parent.layer-2{border:3px solid #000}#site-content>:not(.won) .show-when-won{display:none}.level-container{-webkit-transition:none;transition:none}.won .show-while-playing{display:none}.text-right{text-align:right}#continue-button{margin-bottom:2px}@media screen and (max-width:24.9375em){#continue-button{margin-bottom:0;padding:.3em .6em}}@media screen and (max-width:24.9375em){#play-button{margin-bottom:2px}}#help-button{margin:0;padding:.4em;max-width:3em}@media screen and (max-width:39.9375em){#help-button{padding:.2em;max-width:2em}}.line-height-1{line-height:1}body{overscroll-behavior:contain;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#site-content{overflow:visible}div.mainContainer{overflow-x:hidden}.clickable{cursor:pointer}#share-button{overflow:hidden}#share-button svg{cursor:pointer;max-width:1.5rem} \ No newline at end of file diff --git a/public/index.html b/public/index.html index 882e26b..5727992 100755 --- a/public/index.html +++ b/public/index.html @@ -202,7 +202,8 @@ } }); }).then(function () { - if ('serviceWorker' in navigator) { + //No ServiceWorker for android! + if ('serviceWorker' in navigator && !window["android"]) { console.log('sw in nav'); navigator.serviceWorker.register("service-worker.js").then(function (reg) { if (reg.active) { diff --git a/public/js/app.js b/public/js/app.js index 39be52b..0c7dbb0 100755 --- a/public/js/app.js +++ b/public/js/app.js @@ -1,7892 +1 @@ -class InitPromise -{ - static addPromise(promise) - { - if (typeof promise === 'function') - { - let func = promise; - promise = InitPromise.mainPromise.then(function(app){ - return (func(app)); - }); - } - InitPromise.promises.push(promise); - } - - static resolve(app) - { - InitPromise.mainResolver(app); - return InitPromise.mainPromise.then(function(){ - return Promise.all(InitPromise.promises); - }); - } -} - -InitPromise.promises = []; -InitPromise.mainPromise = new Promise(function(resolver){ - InitPromise.mainResolver = resolver; -}); - -class AndroidBridge { - - static addDefinition(definition, object) { - if (typeof definition !== "function") { - if (typeof definition === "string"){ - let parts = definition.split("."); - for (let i = parts.length-1; i >= 1; i--) { - let newObject = {}; - newObject[parts[i]] = object; - object = newObject; - } - definition = parts[0]; - // console.log("parts for", definition, parts, object); - } - let textDefinition = definition; - definition = () => { - // console.log("defining", textDefinition, object); - window[textDefinition] = object; - }; - } - AndroidBridge.definitions.push(definition); - } - - static applyDefinitions() { - for (let i = 0; i < AndroidBridge.definitions.length; i++) { - AndroidBridge.definitions[i](); - } - return Promise.resolve(); - } -} - -AndroidBridge.definitions = []; -AndroidBridge.addDefinition("InitPromise.addPromise", InitPromise.addPromise); - -class MenuAction { - constructor(title, callback, showFor, order) { - this.title = Helper.nonNull(title, null); - this.callback = callback; - this.showFor = Helper.nonNull(showFor, MenuAction.SHOW_FOR_MEDIUM); - this.order = Helper.nonNull(order, 1000); - this._liClass = ""; - - this._menu = null; - this._activated = true; - this._visible = true; - this.id = MenuAction.maxId++; - this._icon = null; - this._shouldTranslate = true; - this._copies = []; - } - - setTitle(title) - { - this.title = title; - } - - setShouldTranslate(shouldTranslate) - { - this._shouldTranslate = shouldTranslate; - } - - getShowFor(){ - return this.showFor; - } - - getTitle() - { - return this.title; - } - - getShouldTranslate() - { - return this._shouldTranslate; - } - - remove(removeCopies) { - removeCopies = Helper.nonNull(removeCopies, false); - if (Helper.isNotNull(this._menu)) { - console.log(this._menu); - this._menu.removeAction(this); - this._menu = null; - } - if (removeCopies) - { - for (let i = 0; i < this._copies.length; i++) { - this._copies[i].remove(); - } - } - } - - getMenu() { - return this._menu; - } - - setMenu(value) { - this._menu = value; - } - - getVisible() { - return this._visible; - } - - setVisible(value) { - if (value !== this._visible) { - this._visible = value; - this.redraw(); - } - } - - getActivated() { - return this._activated; - } - - getIcon() { - return this._icon; - } - - setIcon(value) { - this._icon = value; - } - - getId() - { - return this.id; - } - - redraw() { - if (Helper.isNotNull(this._menu)) { - this._menu.updateAction(this); - } - } - copy(instance){ - let copy = Helper.nonNull(instance, new MenuAction()); - copy.title = this.title; - copy.callback = this.callback; - copy.showFor = this.showFor; - copy.order = this.order; - copy._liClass = this._liClass; - - copy._activated = this._activated; - copy._visible = this._visible; - copy._icon = this._icon; - copy._shouldTranslate = this._shouldTranslate; - - copy._menu = null; - copy.id = MenuAction.maxId++; - this._copies.push(copy); - return copy; - } - - redrawMenu() - { - if (Helper.isNotNull(this._menu)) { - this._menu.redraw(); - } - } -} -MenuAction.maxId = 0; - -MenuAction.SHOW_ALWAYS = "always"; -MenuAction.SHOW_FOR_MEDIUM = "medium"; -MenuAction.SHOW_FOR_LARGE = "large"; -MenuAction.SHOW_NEVER = "never"; - -class OpenSubmenuAction extends MenuAction { - constructor(title, menu, showFor, order) { - super(title, function (action) { - action.getSubmenu().toggle(); - action.redraw(); - }, showFor, order); - - this.submenu = menu; - menu.setParentAction(this); - } - - getSubmenu() { - return this.submenu; - } - - copy(instance) { - instance = super.copy(Helper.nonNull(instance, new OpenSubmenuAction(null, this.submenu.copy()))); - return instance; - } -} - -class Menu { - constructor(parentElementSelector) { - this.actions = []; - this.submenus = []; - if (typeof parentElementSelector === 'string') { - this.parentElements = document.querySelectorAll(parentElementSelector); - } - else if (Array.isArray(parentElementSelector)) { - this.parentElements = parentElementSelector; - } - else { - this.parentElements = [parentElementSelector]; - } - } - - copy(instance) { - instance = Helper.nonNull(instance, new Menu([])); - - instance.actions = []; - for (let i = 0, n = this.actions.length; i < n; i++) { - instance.actions.push(this.actions[i].copy()); - } - - instance.submenus = []; - for (let i = 0, n = this.submenus.length; i < n; i++) { - instance.submenus.push(this.submenus[i].copy()); - } - - return instance; - } - - addAction(action) { - if (Helper.includesNot(this.actions, action)) { - this.actions.push(action); - this.redraw(); - action.setMenu(this); - if (action instanceof OpenSubmenuAction) { - this.submenus.push(action.getSubmenu()); - } - } - } - - draw() { - if (Helper.isNotNull(this.parentElements)) { - this.sortActions(); - - let actionElements = []; - for (let i = 0; i < this.actions.length; i++) { - let element = this.renderAction(this.actions[i]); - this.actions[i]._htmlElement = element; - actionElements.push(element); - } - for (let i = 0, n = this.parentElements.length; i < n; i++) { - this.parentElements[i].removeAllChildren(); - for (let i2 = 0, n2 = actionElements.length; i2 < n2; i2++) { - this.parentElements[i].appendChild(Helper.cloneNode(actionElements[i2])); - } - this.parentElements[i].onclick = this._getOnClickListener(); - } - } - } - - _getOnClickListener() { - let menu = this; - return function (event) { - let _element = event.target; - if (_element.matches('.action') || _element.matches('.action *')) { - // while (!_element.matches('.action > a')) { - // _element = _element.parentNode; - // } - _element = _element.closest(".action"); - let actionId = parseInt(_element.dataset["id"]); - for (let i = 0, n = menu.actions.length; i < n; i++) { - if (menu.actions[i].id === actionId) { - if (typeof menu.actions[i].callback === 'function' && menu.actions[i].getActivated()) { - menu.actions[i].callback(menu.actions[i], event); - } - return menu.actions[i]; - } - } - for (let i = 0, n = menu.submenus.length; i < n; i++) { - if (menu.submenus[i].click(actionId, event)) { - return menu.submenus[i]; - } - } - } - return null; - }; - } - - /** @protected */ - renderAction(action) { - let aElement = document.createElement("a"); - if (typeof action.callback === 'string') { - aElement.href = action.callback; - } - - if (Helper.isNotNull(action.getIcon())) { - let iconElement = document.createElement("img"); - iconElement.src = action.getIcon(); - iconElement.classList.add('action-image'); - if (action.getShouldTranslate()) { - iconElement.dataset["translationTitle"] = action.title; - } - aElement.appendChild(iconElement); - } - let title = action.getTitle(); - if (action.getShouldTranslate()) { - title = Translator.makePersistentTranslation(title); - } - else { - title = document.createTextNode(title); - } - aElement.appendChild(title); - - return this.renderLiElement(aElement, action) - } - - /** @protected */ - renderLiElement(aElement, action) { - let liElement = document.createElement("li"); - liElement.classList.add('action'); - if (action._liClass.trim() !== "") { - liElement.classList.add(action._liClass); - } - liElement.appendChild(aElement); - liElement.dataset["id"] = action.id; - if (Helper.isNotNull(action.getIcon())) { - liElement.classList.add("img"); - } - - if (!action.getVisible()) { - liElement.classList.add("hidden"); - } - - if (action instanceof OpenSubmenuAction) { - action.getSubmenu().draw(); - liElement.appendChild(action.getSubmenu().getParentElement()); - liElement.classList.add("is-dropdown-submenu-parent"); - liElement.classList.add("opens-right"); - } - return liElement; - } - - /** @private */ - sortActions() { - this.actions = this.actions.sort(function (first, second) { - return first.order - second.order; - }); - } - - _getElementsForAction(action) { - let elements = []; - for (let i = 0; i < this.parentElements.length; i++) { - let elem = this.parentElements[i].querySelector("[data-id=\"" + action.getId() + "\"]"); - Helper.isNull(elem) || elements.push(elem); - } - return elements - } - - updateAction(action) { - let oldElements = this._getElementsForAction(action); - if (oldElements.length === 0) { - return; - } - - let element = this.renderAction(action); - action._htmlElement = element; - - for (let i = 0; i < oldElements.length; i++) { - oldElements[i].replaceWith(Helper.cloneNode(element)); - } - } - - removeAction(action) { - let index = this.actions.indexOf(action); - if (index > 0) { - this.actions.splice(index, 1); - let oldElements = this._getElementsForAction(action); - for (let i = 0, n = oldElements.length; i < n; i++) { - oldElements[i].remove(); - } - if (action instanceof OpenSubmenuAction) { - let index = this.submenus.indexOf(action.getSubmenu()); - this.submenus.splice(index, 1); - } - } - } - - redraw() { - this.draw(); - } -} - -Menu.SHOW_ALWAYS = "always"; -Menu.SHOW_FOR_MEDIUM = "medium"; -Menu.SHOW_FOR_SMEDIUM = "smedium"; -Menu.SHOW_FOR_LARGE = "large"; -Menu.SHOW_NEVER = "never"; - -class Submenu extends Menu -{ - constructor() - { - let menuElement = document.createElement("ul"); - menuElement.classList.add("menu"); - menuElement.classList.add("vertical"); - menuElement.classList.add("submenu"); - menuElement.classList.add("is-dropdown-submenu"); - menuElement.classList.add("first-sub"); - super(menuElement); - - this.parentAction = null; - this.isOpen = false; - } - - - - copy(instance) - { - instance = super.copy(Helper.nonNull(instance, new Submenu())); - instance.parentElements = []; - for (let i = 0, n = this.parentElements.length; i < n; i++) { - instance.parentElements.push(Helper.cloneNode(this.parentElements[i])); - } - instance.parentAction = this.parentAction; - instance.isOpen = this.isOpen; - return instance; - } - - setParentAction(action) - { - this.parentAction = action; - } - - draw() - { - super.draw(); - if (Helper.isNotNull(this.parentElements)) - { - let self = this; - for (let i = 0; i < this.parentElements.length; i++) { - let closeListener = document.createElement("div"); - closeListener.classList.add("close-listener"); - closeListener.onclick = function(e){ - console.log(e); - self.close(); - }; - this.parentElements[i].insertBefore(closeListener, this.parentElements[i].firstElementChild); - } - } - } - - getParentElement() - { - return this.parentElements[0]; - } - - _getOnClickListener() - { - return function () {}; - } - - click(actionId, event) - { - for (let i = 0, n = this.actions.length; i < n; i++) { - if (this.actions[i].id === actionId) - { - if (typeof this.actions[i].callback === 'function' && this.actions[i].getActivated()) { - this.actions[i].callback(this.actions[i], event); - } - this.close(); - return true; - } - } - return false; - } - - toggle() - { - if (this.isOpen) - { - this.close(); - } - else - { - this.open(); - } - } - - open() - { - this.isOpen = true; - for (let i = 0, n = this.parentElements.length; i < n; i++) { - this.parentElements[i].classList.add("js-dropdown-active"); - } - if (Helper.isNotNull(this.parentAction)) - { - this.parentAction.redraw(); - } - } - close() - { - this.isOpen = false; - for (let i = 0, n = this.parentElements.length; i < n; i++) { - this.parentElements[i].classList.remove("js-dropdown-active"); - } - if (Helper.isNotNull(this.parentAction)) - { - this.parentAction.redraw(); - } - } -} - -class TranslatorDB { - constructor() { - this._indexedDB = indexedDB || mozIndexedDB || webkitIndexedDB || msIndexedDB; - this._version = 3; - - let self = this; - this._dbPromise = new Promise(function (resolve, reject) { - let request = self._indexedDB.open("Translator", self._version); - request.onupgradeneeded = function (event) { - let db = event.target.result; - self._upgradeDb(db); - }; - request.onsuccess = function (event) { - let db = event.target.result; - resolve(db); - }; - request.onerror = function (event) { - reject(event); - }; - }).catch(function(e){ - console.error(e); - }); - } - - _upgradeDb(db) { - try { - db.deleteObjectStore("currentLang"); - db.deleteObjectStore("translations"); - } - catch (e) { - console.warn(e); - } - let currentLangObjectStore = db.createObjectStore("currentLang", {"keyPath": "id"}); - let translationsObjectStore = db.createObjectStore("translations", {"keyPath": ["lang","key"]}); - translationsObjectStore.createIndex("lang", "lang", {"unique": false}); - } - - setLanguage(lang) { - this._dbPromise.then(function (db) { - let transaction = TranslatorDB._openTransaction(["currentLang"], "readwrite", db); - let currentLangObjectStore = transaction.objectStore("currentLang"); - currentLangObjectStore.put({"id": 1, "lang": lang}); - }).catch(function(e){ - console.error(e); - }); - } - - saveTranslationsForLang(lang, translations) { - return this._dbPromise.then(function (db) { - return new Promise(function (resolve) { - let transaction = TranslatorDB._openTransaction(["translations"], "readwrite", db); - let translationsObjectStore = transaction.objectStore("translations"); - for (let k in translations) { - translationsObjectStore.put({"lang": lang, "key": k, "translation": translations[k]}); - } - transaction.oncomplete = function () { - resolve(); - }; - }); - }).catch(function(e){ - // console.error(e); - }); - } - - loadTranslationsForLang(lang) { - return this._dbPromise.then(function (db) { - return new Promise(function (resolve) { - let transaction = TranslatorDB._openTransaction(["translations"], "readonly", db); - let translationsObjectStore = transaction.objectStore("translations"); - let index = translationsObjectStore.index("lang"); - let request = index.openCursor(IDBKeyRange.only(lang)); - - let translations = {}; - request.onsuccess = function (e) { - let cursor = e.target.result; - if (cursor) { - - let translation = cursor.value; - translations[translation["key"]] = translation["translation"]; - cursor.continue(); - } - }; - transaction.oncomplete = function(){ - resolve(translations); - }; - }); - }).catch(function(e){ - console.error(e); - return {}; - }); - } - - getLanguage() { - return this._dbPromise.then(function (db) { - return new Promise(function (resolve) { - let transaction = TranslatorDB._openTransaction(["currentLang"], "readonly", db); - let currentLangObjectStore = transaction.objectStore("currentLang"); - let req = currentLangObjectStore.get(1); - req.onsuccess = function (e) { - let data = e.currentTarget.result; - if (data) - { - resolve(data["lang"]); - } - else - { - resolve(null); - } - }; - req.onerror = function (e) { - resolve(null); - }; - }); - }).catch(function(e){ - // console.error(e); - }); - } - - static _openTransaction(name, transactionMode, db) { - let transaction = null; - try { - transaction = db.transaction(name, transactionMode); - } - catch (e) { - console.warn(e); - transaction = db.transaction(name); - } - return transaction; - } -} - -class Translator { - constructor() { - this._translations = []; - this._db = new TranslatorDB(); - this._currentLanguage = null; - this._supportedLanguages = Translator.supportedLanguages; - this._baseLanguage = Translator.baseLanguage; - this._languageBasePath = Translator.languageBasePath; - this._markUntranslatedTranslations = Translator.markUntranslatedTranslations; - this._markTranslations = Translator.markTranslations; - - let self = this; - this._initPromise = this.loadBaseLanguage().then(function () { - return self.loadUserLanguage(); - }); - } - - _loadLanguage(language) { - let self = this; - return fetch(Helper.basePath(this._languageBasePath + language + ".json")).then(function (result) { - return result.json(); - }).then(function (res) { - self._translations[language] = Object.assign(res, self._translations[language]); - self._db.saveTranslationsForLang(language, self._translations[language]); - }).catch(function (err) { - console.error("could not load lang " + language + " because of error: ", err); - }); - } - - loadBaseLanguage() { - let self = this; - return this._loadLanguage(this._baseLanguage).then(function () { - self._currentLanguage = self._baseLanguage; - if (typeof document !== 'undefined') { - document.getElementsByTagName("html")[0].setAttribute("lang", self._baseLanguage); - } - }); - }; - - static setLanguage(language) { - let instance = Translator.getInstance(); - if (instance) { - return instance.setLanguage(language); - } - } - - setLanguage(language) { - if (this._currentLanguage === language) { - this.updateTranslations(); - return Promise.resolve(); - } - - if (this._supportedLanguages.indexOf(language) === -1) { - return Promise.resolve(); - } - - this._currentLanguage = language; - if (typeof localStorage !== 'undefined') { - localStorage.setItem("language", language); - } - this._db.setLanguage(language); - - let self = this; - return this._loadLanguage(language).then(function () { - if (typeof document !== 'undefined') { - document.getElementsByTagName("html")[0].setAttribute("lang", language); - } - self.updateTranslations(); - }); - } - - static translate(key, args) { - let instance = Translator.getInstance(); - if (instance) { - return instance.translate(key, args); - } - return ""; - } - - translate(key, args) { - if (typeof key === 'object' && Helper.isNotNull(key)) { - key = this.addDynamicTranslation(key); - } - - let translation = null; - if (Helper.isNotNull(this._translations[this._currentLanguage]) && Helper.isNotNull(this._translations[this._currentLanguage][key])) { - translation = this._translations[this._currentLanguage][key]; - } - - if (Helper.isNull(translation)) { - if (Translator.logMissingTranslations) { - console.warn("missing translation for language " + this._currentLanguage + " and key " + key); - } - if (Helper.isNotNull(this._translations[this._baseLanguage])) { - translation = this._translations[this._baseLanguage][key]; - } - - if (Helper.isNull(translation)) { - if (Translator.logMissingTranslations) { - console.error("missing base translation for key " + key + ". FIX IT"); - } - translation = key; - } - if (this._markUntranslatedTranslations) { - translation = ">>" + translation + "<<"; - } - } - - if (this._markTranslations) { - translation = "$" + translation + "$"; - } - - if (args !== undefined) { - translation = translation.format(args); - } - - return translation; - } - - static addDynamicTranslation(trans) { - let instance = Translator.getInstance(); - if (instance) { - return instance.addDynamicTranslation(trans); - } - } - - addDynamicTranslation(trans) { - let key = trans["key"]; - delete trans["key"]; - for (let lang in trans) { - if (trans.hasOwnProperty(lang)) { - if (Helper.isNull(this._translations[lang])) { - this._translations[lang] = {}; - } - this._translations[lang][key] = trans[lang]; - } - } - return key; - } - - updateTranslations() { - if (typeof document !== 'undefined') { - let elements = document.querySelectorAll("[data-translation]"); - for (let i = 0, max = elements.length; i < max; i++) { - if (elements[i].dataset["translation"] != "") { - try { - elements[i].innerHTML = this.translate(elements[i].dataset["translation"], (elements[i].dataset["translationArgs"] !== undefined) ? JSON.parse(elements[i].dataset["translationArgs"]) : undefined); - } - catch (err) { - console.error("wrong configured translation: " + err); - } - } - for (let k in elements[i].dataset) { - if (k.startsWith("translation") && !k.endsWith("Args")) { - try { - elements[i][k.substr(11).toLowerCase()] = this.translate(elements[i].dataset[k], (elements[i].dataset[k + "Args"] !== undefined) ? JSON.parse(elements[i].dataset[k + "Args"]) : undefined); - } - catch (err) { - console.error("wrong configured translation: " + err); - } - } - } - } - } - } - - loadUserLanguage() { - let userLanguage = localStorage.getItem("language"); - if (Helper.isNull(userLanguage) || this._supportedLanguages.indexOf(userLanguage) === -1) { - let userLanguages = []; - if (Helper.isNotNull(navigator.languages)) { - userLanguages = navigator.languages.slice(0); //.slice(0) klont das Array. Behebt einen Bug in Firefox - } - - if (navigator.language !== undefined) { - userLanguages.push(navigator.language); - } - //sicherstellen, dass überhaupt eine Sprache gefunden wird - userLanguages.push(this._baseLanguage); - - if (userLanguages !== undefined) { - for (let i = 0, numLanguages = userLanguages.length; i < numLanguages; i++) { - if (this._supportedLanguages.indexOf(userLanguages[i]) !== -1) { - userLanguage = userLanguages[i]; - break; - } - } - } - } - return this.setLanguage(userLanguage.toLowerCase()) - } - - static makePersistentTranslation(key, args, tag) { - tag = Helper.nonNull(tag, "span"); - if (typeof key === 'object') { - key = Translator.addDynamicTranslation(key); - } - - if (typeof document !== 'undefined') { - let htmlElem = document.createElement(tag); - htmlElem.dataset["translation"] = key; - if (args !== undefined) { - htmlElem.dataset["translationArgs"] = JSON.stringify(args); - } - htmlElem.innerHTML = Translator.translate(key, args); - return htmlElem; - } - } - - static generateChangeLanguageMenuAction() { - let submenu = new Submenu(); - submenu.addAction(new MenuAction("en", function () { - Translator.getInstance().setLanguage("en"); - })); - submenu.addAction(new MenuAction("de", function () { - Translator.getInstance().setLanguage("de"); - })); - return new OpenSubmenuAction("current-lang", submenu, Menu.SHOW_ALWAYS) - } - - static init() { - Translator.instance = new Translator(); - // Translator.loadBaseLanguage().then(function () { - // Translator.loadUserLanguage(); - // }); - } - - static getInstance() { - return Translator.instance; - } -} -Translator.logMissingTranslations = false; - -Translator.instance = null; - -Translator.baseLanguage = "en"; -Translator.supportedLanguages = [ - "de", - "en" -]; -Translator.markUntranslatedTranslations = true; -Translator.markTranslations = false; -Translator.languageBasePath = "js/lang/"; -Translator.currentLanguage = null; -Translator.translations = {}; - - -AndroidBridge.addDefinition("Translator.setLanguage", Translator.setLanguage); - -class Helper { - static init() { - Helper.heightMmToPxFactor = null; - Helper.widthMmToPxFactor = null; - } - - static includesNot(array, value, fromIndex) { - return -1 === array.indexOf(value, fromIndex); - } - - static includes(array, value, fromIndex) { - return !Helper.includesNot(array, value, fromIndex); - } - - static isSet() { - if (arguments.length > 0) { - const object = arguments[0]; - let keys = Array.prototype.slice.call(arguments, 1); - return (Helper.isNotNull(object) && (keys.length === 0 || Helper.isSet.apply(null, [object[keys[0]]].concat(keys.slice(1))))); - } - return false; - } - - static isNull(variable) { - return (variable === null || variable === undefined); - } - - static isNotNull(variable) { - return !Helper.isNull(variable); - } - - static nonNull(val1, val2) { - for (let i = 0; i < arguments.length; i++) { - if (Helper.isNotNull(arguments[i])) { - return arguments[i]; - } - } - return null; - } - - static notEmpty(value) { - return !Helper.empty(value); - } - - static buildQuery(values) { - let queryStrings = []; - for (let k in values) { - queryStrings.push(encodeURIComponent(k) + "=" + encodeURIComponent(values[k])); - } - return "?" + queryStrings.join("&"); - } - - static empty(value) { - return (Helper.isNull(value) || (typeof value === 'string' && value.trim() === "")) - } - - static inflateElementsFromString(string) { - let template = document.createElement('template'); - template.innerHTML = string; - return template.content.childNodes; - } - - static createLoadingSymbol() { - let svgNS = "http://www.w3.org/2000/svg"; - - let loader = document.createElement("div"); - loader.className = 'loader'; - - let svg = document.createElementNS(svgNS, "svg"); - svg.setAttribute('viewBox', "0 0 32 32"); - svg.setAttribute("widh", "32"); - svg.setAttribute("height", "32"); - - let circle = document.createElementNS(svgNS, "circle"); - circle.setAttribute("id", "spinner"); - circle.setAttribute("cx", "16"); - circle.setAttribute("cy", "16"); - circle.setAttribute("r", "14"); - circle.setAttribute("fill", "none"); - - svg.appendChild(circle); - loader.appendChild(svg); - - return loader; - } - - static basePath(url) { - return SystemSettings.getBasePath() + url; - } - - static isMobileApple() { - return navigator.userAgent.match(/iPhone|iPad|iPod/i); - } - - static isMobile() { - return (navigator.userAgent.match(/Android|BlackBerry|Opera Mini|IEMobile/i) !== null || Helper.isMobileApple() || (typeof window.orientation !== "undefined" || window.orientation === false || window.orientation === null)); - } - - static select(e) { - let range = document.createRange(); - range.selectNodeContents(e); - let sel = window.getSelection(); - sel.removeAllRanges(); - sel.addRange(range); - } - - static format(number, leadingZeros) { - number = "" + number; - while (number.length < leadingZeros) { - number = "0" + number; - } - return number; - } - - static cloneNode(srcNode) { - let destNode = srcNode.cloneNode(true); - destNode.onclick = srcNode.onclick; - return destNode; - } - - static encodeToBase(stringToEncode, base) { - let encodedString = ""; - let charlength = Math.floor(Math.log(265) / Math.log(base)); - for (let i = 0; i < stringToEncode.length; i++) { - let value = stringToEncode.charCodeAt(i).toString(base); - let joinLength = value.length % charlength; - if (joinLength > 0) { - let joinArray = new Array(charlength + 1 - (joinLength)); //+1, da join nur zwischen elemente einfügt - value = joinArray.join("0") + value; - } - encodedString += value; - } - return encodedString; - } - - static decodeToBase(stringToDecode, base) { - let charlength = Math.floor(Math.log(265) / Math.log(base)); - let values = stringToDecode.match(new RegExp(".{1," + charlength + "}", "g")) || []; - let encodedString = ""; - for (let i = 0, n = values.length; i < n; i++) { - encodedString += String.fromCharCode(parseInt(values[i], base)); - } - return encodedString; - } - - static toggleVisibility(elem) { - if (elem.style.display === "none") { - elem.style.display = ""; - return true; - } - else { - elem.style.display = "none"; - return false; - } - } - - static print(content) { - let printContent = document.getElementById("print-content"); - if (content instanceof Element) { - printContent.removeAllChildren(); - printContent.appendChild(content); - } - else { - printContent.innerHTML = content; - } - window.print(); - } - - static strftime(sFormat, date, useUTC) { - if (!(date instanceof Date)) date = new Date(date); - useUTC = Helper.nonNull(useUTC, false); - let nDay = (useUTC) ? date.getUTCDay() : date.getDay(), - nDate = (useUTC) ? date.getUTCDate() : date.getDate(), - nMonth = (useUTC) ? date.getUTCMonth() : date.getMonth(), - nYear = (useUTC) ? date.getUTCFullYear() : date.getFullYear(), - nHour = (useUTC) ? date.getUTCHours() : date.getHours(), - aDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], - aMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], - aDayCount = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334], - isLeapYear = function () { - if ((nYear & 3) !== 0) return false; - return nYear % 100 !== 0 || nYear % 400 === 0; - }, - getThursday = function () { - let target = new Date(date); - target.setDate(nDate - ((nDay + 6) % 7) + 3); - return target; - }, - zeroPad = function (nNum, nPad) { - return ('' + (Math.pow(10, nPad) + nNum)).slice(1); - }; - - return sFormat.replace(/%[a-z]/gi, function (sMatch) { - return { - '%a': Translator.makePersistentTranslation(aDays[nDay].slice(0, 3)).outerHTML, - '%A': Translator.makePersistentTranslation(aDays[nDay]).outerHTML, - '%b': Translator.makePersistentTranslation(aMonths[nMonth].slice(0, 3)).outerHTML, - '%B': Translator.makePersistentTranslation(aMonths[nMonth]).outerHTML, - '%c': date.toUTCString(), - '%C': Math.floor(nYear / 100), - '%d': zeroPad(nDate, 2), - '%e': nDate, - '%f': zeroPad(date.getTime() % 1000, 4), - '%F': date.toISOString().slice(0, 10), - '%G': getThursday().getFullYear(), - '%g': ('' + getThursday().getFullYear()).slice(2), - '%H': zeroPad(nHour, 2), - '%I': zeroPad((nHour + 11) % 12 + 1, 2), - '%j': zeroPad(aDayCount[nMonth] + nDate + ((nMonth > 1 && isLeapYear()) ? 1 : 0), 3), - '%k': '' + nHour, - '%l': (nHour + 11) % 12 + 1, - '%m': zeroPad(nMonth + 1, 2), - '%M': zeroPad(date.getMinutes(), 2), - '%p': (nHour < 12) ? 'AM' : 'PM', - '%P': (nHour < 12) ? 'am' : 'pm', - '%s': Math.round(date.getTime() / 1000), - '%S': zeroPad(date.getSeconds(), 2), - '%u': nDay || 7, - '%V': (function () { - let target = getThursday(), - n1stThu = target.valueOf(); - target.setMonth(0, 1); - let nJan1 = target.getDay(); - if (nJan1 !== 4) target.setMonth(0, 1 + ((4 - nJan1) + 7) % 7); - return zeroPad(1 + Math.ceil((n1stThu - target) / 604800000), 2); - })(), - '%w': '' + nDay, - '%x': date.toLocaleDateString(), - '%X': date.toLocaleTimeString(), - '%y': ('' + nYear).slice(2), - '%Y': nYear, - '%z': date.toTimeString().replace(/.+GMT([+-]\d+).+/, '$1'), - '%Z': date.toTimeString().replace(/.+\((.+?)\)$/, '$1') - }[sMatch] || sMatch; - }); - } - - static cloneJson(obj) { - // https://stackoverflow.com/questions/4120475/how-to-create-and-clone-a-json-object/17502990#17502990 - let i; - - // basic type deep copy - if (Helper.isNull(obj) || typeof obj !== 'object') { - return obj - } - // array deep copy - if (obj instanceof Array) { - let cloneA = []; - for (i = 0; i < obj.length; ++i) { - cloneA[i] = Helper.cloneJson(obj[i]); - } - return cloneA; - } - if (obj instanceof Date) - { - return new Date(obj.getTime()); - } - // object deep copy - let cloneO = {}; - for (i in obj) { - cloneO[i] = Helper.cloneJson(obj[i]); - } - return cloneO; - } - - static htmlspecialcharsDecode(text) { - const map = { - '&': '&', - '&': "&", - '<': '<', - '>': '>', - '"': '"', - ''': "'", - '’': "’", - '‘': "‘", - '–': "–", - '—': "—", - '…': "…", - '”': '”' - }; - - if (Helper.isNotNull(text) && typeof text.replace === "function") { - return text.replace(/\&[\w\d\#]{2,5}\;/g, function (m) { - return map[m]; - }); - } - return text; - } - - static formDataFromObject(obj) { - let formData = new FormData(); - for (let k in obj) { - formData.set(k, obj[k]); - } - return formData; - } - - static scaleContentRecursive(element, content) { - - let elementStyle = window.getComputedStyle(element); - let contentStyle = window.getComputedStyle(content); - - if (contentStyle.height > elementStyle.height || contentStyle.width > elementStyle.width) { - return Helper.scaleDownContentRecursive(element, content); - } - } - - static scaleDownContentRecursive(element, content) { - Helper.convertChildrenToRelativeRecursive(element); - - let elementStyle = window.getComputedStyle(element); - let contentStyle = window.getComputedStyle(content); - - let runs = 0; - let fontSize = parseFloat(contentStyle.getPropertyValue("font-size")); - let width = contentStyle.width; - let height = contentStyle.height; - while (contentStyle.height > elementStyle.height || contentStyle.width > elementStyle.width) { - fontSize *= 0.95; - - if (height > elementStyle.height) { - height *= 0.95; - } - if (width > contentStyle.width) { - width *= 0.95; - } - content.style["font-size"] = fontSize + "px"; - content.style["max-height"] = height + "px"; - content.style["max-width"] = width + "px"; - - runs++; - if (runs > 2000) { - console.log("breaked"); - break; - } - } - Helper.convertToRelative(content); - - contentStyle = window.getComputedStyle(content); - content.style["font-size"] = (parseFloat(contentStyle.getPropertyValue("font-size")) / parseFloat(document.documentElement.clientHeight) * 100) + "vh"; - } - - static convertChildrenToRelativeRecursive(element) { - let children = element.childNodes; - for (let i = 0, n = children.length; i < n; i++) { - if (children[i] instanceof Element) { - Helper.convertToRelative(children[i]); - Helper.convertChildrenToRelativeRecursive(children[i]); - } - } - } - - static convertToRelative(element) { - let hasTransitionClass = (element.classList.contains("no-transtition")); - - element.classList.add("no-transition"); - - let parent = element.parentNode; - - console.log(element); - let elementStyle = window.getComputedStyle(element); - let parentStyle = window.getComputedStyle(parent); - - let fontSize = parseFloat(elementStyle.getPropertyValue("font-size")) / parseFloat(parentStyle.getPropertyValue("font-size")); - - let maxHeight = elementStyle.height; - let maxWidth = elementStyle.width; - - let pHeight = parentStyle.height; - let pWidth = parentStyle.width; - - let relativeAttributes = element.style; - relativeAttributes['max-height'] = Math.floor(maxHeight / pHeight * 100) + "%"; - relativeAttributes['margin-left'] = Math.floor(parseFloat(elementStyle.getPropertyValue('margin-left')) / pWidth * 100) + "%"; - relativeAttributes['margin-right'] = Math.floor(parseFloat(elementStyle.getPropertyValue('margin-right')) / pWidth * 100) + "%"; - relativeAttributes['margin-top'] = Math.floor(parseFloat(elementStyle.getPropertyValue('margin-top')) / pHeight * 100) + "%"; - relativeAttributes['margin-bottom'] = Math.floor(parseFloat(elementStyle.getPropertyValue('margin-bottom')) / pHeight * 100) + "%"; - relativeAttributes['max-width'] = Math.floor(maxWidth / pWidth * 100) + "%"; - relativeAttributes["font-size"] = fontSize + "em"; - // console.log(relativeAttributes); - // element.css(relativeAttributes); - - if (!hasTransitionClass) { - element.classList.remove("no-transition"); - } - } - - static isChrome() { - let isChromium = window.chrome, - winNav = window.navigator, - vendorName = winNav.vendor, - isOpera = winNav.userAgent.indexOf("OPR") > -1, - isIEedge = winNav.userAgent.indexOf("Edge") > -1, - isIOSChrome = winNav.userAgent.match("CriOS"); - - if (isIOSChrome) { - return true; - } else { - return isChromium !== null && - typeof isChromium !== "undefined" && - vendorName === "Google Inc." && - isOpera === false && - isIEedge === false; - } - } - - static getIndexedObject(array, keyValue) { - let obj = {}; - for (let i = 0, n = array.length; i < n; i++) { - obj[array[i][keyValue]] = array[i]; - } - return obj; - } - - static invertKeyValues(obj) { - let new_obj = {}; - - for (let prop in obj) { - if (obj.hasOwnProperty(prop)) { - new_obj[obj[prop]] = prop; - } - } - - return new_obj; - } - - static toArray(object) { - let res = []; - for (let k in object) { - res.push(object[k]); - } - return res; - } -} -Helper.init(); - -class SystemSettings { - static setBasePath(basePath) { - SystemSettings._basePath = basePath; - } - - static getBasePath() { - return SystemSettings._basePath; - } - - static set(key, value) { - SystemSettings._settings[key] = value; - } - - static get(key, defaultValue) { - return Helper.nonNull(SystemSettings._settings[key], defaultValue); - } - - static has(key){ - return Helper.nonNull(SystemSettings._settings[key]); - } -} - -SystemSettings.setBasePath("/"); -SystemSettings._settings = {}; - -class ThemeManager { - static init() { - ThemeManager.loadCurrentTheme(); - } - - static changeCurrentTheme(newTheme) { - let theme = null; - if (typeof newTheme === 'string') { - let themes = ThemeManager.themes.filter(function (theme) { - return theme._name === newTheme; - }); - if (themes.length > 0) { - theme = themes[0]; - } - } - else if (ThemeManager.themes.indexOf(newTheme) !== -1) { - theme = newTheme; - } - if (Helper.isNotNull(theme)) { - localStorage.setItem("currentTheme", theme._name); - let themePromise = new Promise(function (resolve) { - document.querySelector("nav.top-bar").addEventListener("transitionend", function(){ - resolve(); - }); - }); - document.body.className = theme._className; - ThemeManager.currentTheme = theme; - for (let i = 0, n = ThemeManager.changeListeners.length; i < n; i++) { - ThemeManager.changeListeners[i](ThemeManager.currentTheme, themePromise); - } - } - } - - static addTheme(theme) { - ThemeManager.themes.push(theme); - } - - static loadCurrentTheme() { - ThemeManager.changeCurrentTheme(localStorage.getItem("currentTheme")); - if (Helper.isNull(ThemeManager.currentTheme)) { - let className = document.body.className; - let themes = ThemeManager.themes.filter(function (theme) { - return theme._className === className; - }); - if (themes.length > 0) { - ThemeManager.changeCurrentTheme(themes[0]); - } - else if (ThemeManager.themes.length > 0) { - ThemeManager.changeCurrentTheme(ThemeManager.themes[0]); - } - } - } - - static generateChangeThemeMenuAction() { - return new MenuAction(ThemeManager.currentTheme._name, function (action) { - let currentThemeIndex = ThemeManager.themes.indexOf(ThemeManager.currentTheme); - let nextIndex = (currentThemeIndex + 1) % ThemeManager.themes.length; - ThemeManager.changeCurrentTheme(ThemeManager.themes[nextIndex]); - action.title = ThemeManager.currentTheme._name; - action._menu.redraw(); - }, Menu.SHOW_ALWAYS) - } - - static addChangeListener(listener) { - ThemeManager.changeListeners.push(listener); - } - - static getCurrentTheme(){ - return ThemeManager.currentTheme; - } -} - -ThemeManager.currentTheme = null; -ThemeManager.themes = []; -ThemeManager.changeListeners = []; - -AndroidBridge.addDefinition("ThemeManager", { - "addChangeListener": ThemeManager.addChangeListener, - "getCurrentTheme": ThemeManager.getCurrentTheme, -}); - -class CookieCompliance { - - static async showIfNeeded(cookieContainer) { - let cookieCompliance = new CookieCompliance(cookieContainer); - return cookieCompliance.showIfNeeded(); - } - - constructor(cookieContainerId) { - this.cookieContainerId = cookieContainerId; - this.dropCookie = true; - this.cookieDuration = 365 * 10; - this.cookieName = 'complianceCookie'; - this.cookieValue = 'true'; - } - - async showIfNeeded() { - if (CookieCompliance.checkCookie(this.cookieName) !== this.cookieValue) { - return this.show(); - } - return Promise.resolve(); - } - - removeMe() { - this.createCookie(this.cookieName, this.cookieValue, this.cookieDuration); - } - - createCookie(name, value, days) { - let expires; - if (Helper.isNotNull(days)) { - const date = new Date(); - date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); - expires = "; expires=" + date.toGMTString(); - } - else { - expires = ""; - } - if (this.dropCookie) { - document.cookie = name + "=" + value + expires + "; path=/"; - } - } - - eraseCookie(name) { - this.createCookie(name, "", -1); - } - - static checkCookie(name) { - const nameEQ = name + "="; - const cookies = document.cookie.split(';'); - for (let i = 0; i < cookies.length; i++) { - let c = cookies[i]; - while (c.charAt(0) === ' ') { - c = c.substring(1, c.length); - } - if (c.indexOf(nameEQ) === 0) { - return c.substring(nameEQ.length, c.length); - } - } - return null; - } - - show() { - let cookieCompliance = this; - const cookieMessage = document.getElementById(this.cookieContainerId); - cookieMessage.style.display = 'block'; - return new Promise(r => { - cookieMessage.querySelector("#close-cookie-msg").onclick = function () { - cookieCompliance.removeMe(); - cookieMessage.remove(); - r(); - }; - }); - } -} - -class ActionBarMenu extends Menu { - static init() { - function parseStyleToObject(str) { - let styleObject = {}; - - if (typeof str !== 'string') { - return styleObject; - } - - str = str.trim().slice(1, -1); // browsers re-quote string style values - - if (!str) { - return styleObject; - } - - styleObject = str.split('&').reduce(function (ret, param) { - const parts = param.replace(/\+/g, ' ').split('='); - let key = parts[0]; - let val = parts[1]; - key = decodeURIComponent(key); - - // missing `=` should be `null`: - // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters - val = val === undefined ? null : decodeURIComponent(val); - - if (!ret.hasOwnProperty(key)) { - ret[key] = val; - } else if (Array.isArray(ret[key])) { - ret[key].push(val); - } else { - ret[key] = [ret[key], val]; - } - return ret; - }, {}); - - return styleObject; - } - - let cssStyle = document.getElementsByClassName('foundation-mq'); - if (cssStyle.length === 0) { - return; - } - let queries = []; - cssStyle = parseStyleToObject(window.getComputedStyle(cssStyle[0]).getPropertyValue('font-family')); - for (let key in cssStyle) { - if (cssStyle.hasOwnProperty(key)) { - queries.push({ - _name: key, - value: 'only screen and (min-width: ' + cssStyle[key] + ')' - }); - } - } - - window.addEventListener('resize', function () { - if (Helper.isNotNull(ActionBarMenu.currentMenu)) { - ActionBarMenu.currentMenu.updateToggleButton(); - } - }); - let responsiveMenu = document.getElementById("responsive-menu"); - document.getElementById("responsive-menu-toggle").onclick = function () { - if (window.getComputedStyle(responsiveMenu).getPropertyValue('display') === 'none') { - responsiveMenu.style.display = 'block'; - } - else if (Helper.isNotNull(ActionBarMenu.currentMenu)) { - ActionBarMenu.currentMenu.close(); - - } - }; - responsiveMenu.firstElementChild.addEventListener("click", function (e) { - if (e.target === responsiveMenu.firstElementChild && Helper.isNotNull(ActionBarMenu.currentMenu)) { - ActionBarMenu.currentMenu.close(); - } - } - ); - ActionBarMenu.queries = queries; - } - - static _getCurrentSize() { - let matched; - - for (let i = 0; i < ActionBarMenu.queries.length; i++) { - let query = ActionBarMenu.queries[i]; - - if (matchMedia(query.value).matches) { - matched = query; - } - } - - if (typeof matched === 'object') { - return matched._name; - } else { - return matched; - } - } - - static filterVisibleElements(elements) { - let visibleElements = []; - for (let i = 0, n = elements.length; i < n; i++) { - if (!elements[i].classList.contains("hidden")) { - visibleElements.push(elements[i]); - } - } - return visibleElements; - } - - renderLiElement(aElement, action) { - let liElement = super.renderLiElement(aElement, action); - liElement.classList.add(action.getShowFor()); - return liElement; - } - - updateToggleButton() { - let size = ActionBarMenu._getCurrentSize(); - let firstParentElement = this.parentElements[0]; - if ((size === "medium" || size === "smedium" || size === "small") && ActionBarMenu.filterVisibleElements(firstParentElement.getElementsByClassName(Menu.SHOW_FOR_LARGE)).length > 0 || - (size === "smedium" || size === "small") && ActionBarMenu.filterVisibleElements(firstParentElement.getElementsByClassName(Menu.SHOW_FOR_MEDIUM)).length > 0 || - (size === "small") && ActionBarMenu.filterVisibleElements(firstParentElement.getElementsByClassName(Menu.SHOW_FOR_SMEDIUM)).length > 0 || - ActionBarMenu.filterVisibleElements(firstParentElement.getElementsByClassName(Menu.SHOW_NEVER)).length > 0) { - document.getElementById("responsive-menu-toggle").style.display = 'block'; - } else { - document.getElementById("responsive-menu-toggle").style.display = 'none'; - if (Helper.isNotNull(ActionBarMenu.currentMenu)) { - ActionBarMenu.currentMenu.close(); - } - } - } - - _getOnClickListener() { - let superListener = super._getOnClickListener(); - return function (event) { - let action = superListener(event); - if (!(action instanceof OpenSubmenuAction) && Helper.isNotNull(ActionBarMenu.currentMenu)) { - ActionBarMenu.currentMenu.close(); - } - } - } - - draw(parentElement) { - let returnValue = super.draw(parentElement); - this.updateToggleButton(); - - ActionBarMenu.currentMenu = this; - return returnValue; - } - - close() { - document.getElementById("responsive-menu").style.display = 'none'; - for (let i = 0, n = this.submenus.length; i < n; i++) { - this.submenus[i].close(); - } - } - - removeAction(action) { - let res = super.removeAction(action); - this.updateToggleButton(); - return res; - } -} - -ActionBarMenu.queries = []; -ActionBarMenu.currentMenu = null; -ActionBarMenu.init(); - -class ViewInflater { - static inflate(viewUrl, parentUrls) { - parentUrls = Helper.nonNull(parentUrls, []).slice(0); - - let resultPromise = Promise.resolve(); - if (viewUrl instanceof Element) { - resultPromise = Promise.resolve(viewUrl); - } - else { - if (parentUrls.indexOf(viewUrl) !== -1) { - return Promise.reject("views are in a circuit! cannot resolve view for url " + parentUrls[0] + "! url " + viewUrl + " is in stack before!"); - } - parentUrls.push(viewUrl); - resultPromise = fetch(Helper.basePath(viewUrl), {credentials: "same-origin"}).then(function (result) { - return result.text(); - }).then(function (htmlText) { - let doc = (new DOMParser()).parseFromString(htmlText, "text/html"); - if (Helper.isNull(doc)) { - doc = document.implementation.createHTMLDocument(''); - doc.body.innerHTML = htmlText; - } - return doc.body.firstChild - }); - } - - return resultPromise.then(function (parentElement) { - let promises = []; - let childViews = parentElement.querySelectorAll("[data-view]"); - - for (let i = 0, n = childViews.length; i < n; i++) { - promises.push(ViewInflater.inflate(childViews[i].dataset["view"], parentUrls).then(function (element) { - childViews[i].replaceWith(element); - })); - } - return Promise.all(promises).then(function () { - return parentElement; - }); - }); - } -} - -class Context { - constructor(view) { - let self = this; - this._siteContent = null; - this.firstStart = true; - this.inflatePromise = new Promise(function (resolver) { - self.inflatePromiseResolver = resolver; - }); - this.fragments = {}; - - if (Helper.isNotNull(view)) { - this.inflateView(view); - } - } - - onConstruct() { - let results = []; - for (let k in this.fragments) { - results.push(this.fragments[k].onConstruct.apply(this.fragments[k], arguments)); - results.push(this.fragments[k].inflatePromise); - } - return Promise.all(results); - } - - onStart() { - if (this.firstStart) { - this.onFirstStart(); - this.firstStart = false; - } - - for (let k in this.fragments) { - let fragment = this.fragments[k]; - fragment.onStart.apply(this.fragments[k], arguments); - this.fragments[k].inflatePromise.then(function (fragmentView) { - if (fragment.isActive()) { - fragmentView.classList.remove("hidden"); - } - else { - fragmentView.classList.add("hidden"); - } - }); - } - } - - onFirstStart() { - // for (let k in this.fragments) { - // this.fragments[k].onFirstStart.apply(this.fragments[k], arguments); - // } - } - - onPause() { - for (let k in this.fragments) { - this.fragments[k].onPause.apply(this.fragments[k], arguments); - } - } - - onDestroy() { - for (let k in this.fragments) { - this.fragments[k].onDestroy.apply(this.fragments[k], arguments); - } - } - - addFragment(viewQuery, fragment) { - this.fragments[viewQuery] = fragment; - this.inflatePromise = this.inflatePromise.then(function (siteContent) { - return fragment.inflatePromise.then(function (fragmentView) { - siteContent.querySelector(viewQuery).appendChild(fragmentView); - return siteContent; - }); - }); - } - - /** @protected */ - inflateView(link) { - let self = this; - this.inflatePromiseResolver(ViewInflater.inflate(link).then(function (siteContent) { - self._siteContent = siteContent; - return siteContent; - })); - - return this.inflatePromise; - } - - findBy(query, all, asPromise) { - all = Helper.nonNull(all, false); - asPromise = Helper.nonNull(asPromise, false); - - let getVal = function (root) { - let res = null; - if (all) { - res = root.querySelectorAll(query); - if (root.matches(query)) { - res.push(root); - } - } - else { - if (root.matches(query)) { - res = root; - } - else { - res = root.querySelector(query); - } - } - return res; - }; - - if (asPromise) { - return this.inflatePromise.then(function (rootView) { - return getVal(rootView); - }); - } - return getVal(this._siteContent); - } -} - -class AbstractSite extends Context { - constructor(siteManager, view, deepLink) { - super(view); - - this.isVisible = false; - this.siteManager = siteManager; - this.isFinishing = false; - this.actionMenu = null; - this.url = ""; - this.deepLink = deepLink; - this.startArgs = {}; - this.title = siteManager.getDefaultTitle(); - } - - setTitle(titleElement, title) { - if (typeof titleElement === "string") { - title = titleElement; - titleElement = document.createTextNode(titleElement); - } - this.title = { - element: titleElement - }; - this.title["title"] = Helper.nonNull(title, this.title["title"]); - - if (this.isVisible) { - this.siteManager.updateTitle(); - } - } - - startStartsite() { - return this.startSite(this.siteManager.getStartSiteName()); - } - - inflateView(link) { - let self = this; - return super.inflateView(link).then(function (res) { - let promises = []; - for (let i = 0, n = self.fragments.length; i < n; i++) { - promises.push(self.fragments[i].inflatePromise); - } - return Promise.all(promises).then(function () { - return res; - }); - }); - } - - onConstruct(args) { - this.startArgs = args; - if (Helper.isNotNull(this.deepLink)) { - this.setUrlFromParams(args); - } - return super.onConstruct(args); - } - - onStart(args) { - this.isVisible = true; - let res = super.onStart(args); - this.actionMenu.redraw(); - return res; - } - - onPause(args) { - super.onPause(args); - this.isVisible = false; - } - - finish(result) { - if (!this.isFinishing) { - this.isFinishing = true; - this.siteManager.endSite(this, result); - } - } - - startSite(siteName, args) { - return this.siteManager.startSite(siteName, args); - } - - toForeground() { - this.siteManager.toForeground(this); - } - - finishAndStartNext(siteName, startParams, finishResult) { - this.startSite(siteName, startParams); - this.finish(finishResult); - } - - createActionBarMenu(menu) { - let defaultActions = this.siteManager.getDefaultActions(); - for (let i = 0, n = defaultActions.length; i < n; i++) { - menu.addAction(defaultActions[i].copy()); - } - return menu; - } - - setUrl(url) { - this.url = url; - this.siteManager.updateUrl(this); - } - - setUrlFromParams(params) { - this.setUrl(this.deepLink + Helper.buildQuery(params)); - } - - updateUrlParams(params) { - this.startArgs = Object.assign(this.startArgs, params); - this.setUrlFromParams(this.startArgs); - } - - getUrl() { - return this.url; - } - - getFullUrl() { - return Helper.basePath(this.url); - } - - onBackPressed() { - } - - addListener(event, selector, listenerFunction) { - this.siteManager.addListener(this, event, selector, listenerFunction); - } - - addKeyListener(keycode, listenerFunction) - { - this.siteManager.addKeyListener(this, keycode, listenerFunction); - } - - addKeyAndEventListener(keycode, event, selector, listenerFunction) { - this.siteManager.addKeyAndEventListener(this, keycode, event, selector, listenerFunction); - } -} - -class SiteContainer { - constructor(site, finishResolver) { - this._site = site; - this._siteContent = null; - this._pauseParameters = {}; - this._startParameters = {}; - this._finishResolver = finishResolver; - } - getSite() { - return this._site; - } - - setSite(site) { - if (site instanceof AbstractSite) { - this._site = site; - } - } - - getSiteContent() { - return this._siteContent; - } - - setSiteContent(value) { - this._siteContent = value; - } - - getPauseParameters() { - return this._pauseParameters; - } - - setPauseParameters(value) { - this._pauseParameters = value; - } - - getStartParameters() { - return this._startParameters; - } - - setStartParameters(value) { - this._startParameters = value; - } - - getFinishResolver() { - return this._finishResolver; - } - - setFinishResolver(value) { - this._finishResolver = value; - } -} - -class SiteManager { - constructor(siteDivId, actionBarMenuSelector, app) { - this.siteDiv = document.getElementById(siteDivId); - this.siteContainerStack = []; - this.currentSiteContainerToShow = null; - this.actionBarMenuSelector = Helper.nonNull(actionBarMenuSelector, '.action-bar'); - - this.siteStartingPromise = Promise.resolve(); - this.defaultActions = []; - this.startSiteName = null; - this.app = app; - - this.titleElement = document.querySelector(".top-bar-title"); - - const defaultTitleElem = document.createElement("span"); - while (this.titleElement.childNodes.length > 0) { - const child = this.titleElement.firstChild; - child.remove(); - defaultTitleElem.appendChild(child); - } - - this.defaultTitle = { - element: defaultTitleElem, - title: document.title - }; - - let siteManager = this; - window.onpopstate = function (e) { - if (siteManager.siteContainerStack.length >= 1) { - let site = siteManager.siteContainerStack[siteManager.siteContainerStack.length - 1].getSite(); - if (site.onBackPressed() !== false) { - siteManager.endSite(site); - } - } - }; - } - - getDefaultTitle() { - return this.defaultTitle; - } - - setStartSiteName(startSiteName) { - this.startSiteName = startSiteName; - } - - getStartSiteName() { - return this.startSiteName; - } - - addDefaultAction(action) { - this.defaultActions.push(action); - } - - getDefaultActions() { - return this.defaultActions; - } - - getCurrentSite(){ - if (Helper.isNotNull(this.currentSiteContainerToShow)){ - return this.currentSiteContainerToShow.getSite(); - } - return null; - } - - async findSite(filter){ - for (let i = this.siteContainerStack.length-1; i >= 0; i--) { - if (await filter(this.siteContainerStack[i].getSite())){ - return this.siteContainerStack[i].getSite(); - } - } - return null; - } - - async startSite(siteConstructor, paramsPromise) { - if (!(siteConstructor.prototype instanceof AbstractSite)) { - throw { - "error": "wrong class given! Expected AbstractSite, given " + siteConstructor.name - }; - } - - let site = new siteConstructor(this); - let resolver = {}; - let finishPromise = new Promise(function (resolve, reject) { - resolver.resolve = resolve; - resolver.reject = reject; - }); - let siteContainer = new SiteContainer(site, resolver); - this.siteDiv.removeAllChildren().appendChild(Helper.createLoadingSymbol()); - - this.siteStartingPromise = Promise.resolve(paramsPromise).then(async (params) => { - siteContainer.setStartParameters(params); - await Promise.all([site.onConstruct(params), site.inflatePromise]); - - site.actionMenu = site.createActionBarMenu(this.buildActionBarMenu()); - return this.show(siteContainer); - }).catch((e) => { - console.error("site start error for site ", siteConstructor.name, e); - }); - - return finishPromise; - } - - endSite(site, result) { - let manager = this; - this.siteStartingPromise.then(function () { - let index = manager.findContainerIndexBySite(site); - let container = manager.siteContainerStack.splice(index, 1); - container = container[0]; - - let showSiteContainer = null; - if (container === manager.currentSiteContainerToShow) { - manager.currentSiteContainerToShow.getSite().onPause(); - manager.currentSiteContainerToShow = null; - let newSiteContainerIndex = manager.siteContainerStack.length - 1; - if (newSiteContainerIndex < 0) { - - manager.showAppEndedMessage(); - app.endApp(); - // manager.startSite(manager.startSiteName); - return; - } - manager.siteDiv.removeAllChildren().appendChild(Helper.createLoadingSymbol()); - showSiteContainer = manager.siteContainerStack[newSiteContainerIndex]; - } - container.getSite().onDestroy(); - - Promise.resolve(result).then(function (resValue) { - container.getFinishResolver().resolve(resValue); - if (Helper.isNotNull(showSiteContainer)) { - manager.show(showSiteContainer); - } - }); - }); - } - - addListener(site, event, _selector, listener) { - this.siteDiv.addEventListener(event, function (_event) { - let _element = _event.target; - if (site.isVisible && _element.matches(_selector)) { - listener(_element, _event); - } - }); - } - - addKeyAndEventListener(site, keycode, event, selector, listener) { - this.addListener(site, event, selector, listener); - this.addKeyListener(site, keycode, listener); - } - - addKeyListener(site, keycode, listener) { - window.addEventListener("keydown", function (e) { - if (site.isVisible && e.which === keycode) { - listener(this, e); - } - }); - } - - toForeground(site) { - let index = this.findContainerIndexBySite(site); - let container = this.siteContainerStack.splice(index, 1); - container = container[0]; - - this.show(container); - } - - refreshCurrentSite() { - return this.show(this.currentSiteContainerToShow); - } - - /** @private */ - show(siteContainer) { - if (Helper.isNotNull(this.currentSiteContainerToShow)) { - this.currentSiteContainerToShow.setPauseParameters(this.currentSiteContainerToShow.getSite().onPause()); - this.currentSiteContainerToShow.setSiteContent(this.siteDiv.innerHTML); - } - this.siteDiv.removeAllChildren().appendChild(Helper.createLoadingSymbol()); - - let siteManager = this; - this.currentSiteContainerToShow = siteContainer; - if (-1 === this.siteContainerStack.indexOf(siteContainer)) { - this.siteContainerStack.push(siteContainer); - } - - return siteContainer.getSite().inflatePromise.then(function (data) { - siteContainer.getSite().actionMenu.redraw(); - siteManager.siteDiv.removeAllChildren().appendChild(data); - siteManager.updateTitle(); - Translator.getInstance().updateTranslations(); - return data; - }).then(function (data) { - siteContainer.getSite().onStart(siteContainer.getPauseParameters()); - history.pushState({ - 'siteName': siteContainer.getSite().constructor.name, - 'siteData': data.outerHTML, - 'stackPosition': siteManager.siteContainerStack.length - 1 - }, siteContainer.getSite().constructor.name, siteContainer.getSite().getFullUrl()); - }); - } - - updateUrl(site) { - if (Helper.isNotNull(this.currentSiteContainerToShow) && this.currentSiteContainerToShow.getSite() === site) { - let self = this; - history.replaceState({ - 'siteName': site.constructor.name, - 'siteData': site._siteContent.outerHTML, - 'stackPosition': self.siteContainerStack.length - 1 - }, site.constructor.name, site.getFullUrl()); - } - } - - getCurrentSite() { - if (this.currentSiteContainerToShow != null) - return this.currentSiteContainerToShow.getSite(); - } - - redrawCurrentActionBar() { - if (this.currentSiteContainerToShow != null) - this.currentSiteContainerToShow.getSite().actionMenu.redraw(); - } - - updateTitle() { - let title = this.getCurrentSite().title; - this.titleElement.removeAllChildren().appendChild(title.element); - document.title = Helper.nonNull(title.title, this.defaultTitle.title); - } - - /** @private */ - findContainerIndexBySite(site) { - for (let i = 0, n = this.siteContainerStack.length; i < n; i++) { - if (this.siteContainerStack[i].getSite() === site) { - return i; - } - } - return -1; - } - - /** @private */ - findContainerBySite(site) { - let index = this.findContainerIndexBySite(site); - if (index === -1) { - return null; - } - return this.siteContainerStack[index]; - } - - /** @private */ - showAppEndedMessage() { - this.siteDiv.removeAllChildren().appendChild(Translator.makePersistentTranslation("The app has ended! Please close the window.")); - } - - /** @private */ - buildActionBarMenu() { - return new ActionBarMenu(this.actionBarMenuSelector); - } -} - -class PauseSite extends AbstractSite { - onConstruct(args) { - let pausedElement = null; - - if (Helper.isSet(args, "url")) { - pausedElement = args["url"]; - } - else { - pausedElement = document.createElement("div"); - pausedElement.innerHTML = "Paused..."; - } - - this.inflateView(pausedElement); - } - - onPause() { - for (let i = 0; i < PauseSite.onStartListeners.length; i++) { - if (typeof PauseSite.onStartListeners[i] === "function") { - PauseSite.onStartListeners[i](); - } - } - return super.onPause(); - } - - onStart() { - for (let i = 0; i < PauseSite.onPauseListeners.length; i++) { - if (typeof PauseSite.onPauseListeners[i] === "function") { - PauseSite.onPauseListeners[i](); - } - } - return super.onPause(); - } -} - -PauseSite.onPauseListeners = []; -PauseSite.onStartListeners = []; - -class App { - constructor() { - this._siteManager = null; - this._actionBarMenuSelector = '.action-bar'; - this._basePath = SystemSettings.getBasePath(); - this._siteContentId = 'site-content'; - this._deepLinks = new Map(); - this._defaultActions = []; - this._addThemeAction = false; - this._showCookieCompliance = true; - this._startSite = null; - this._appEndListener = () => { - return this.startSite(this._startSite); - }; - } - - getSiteManager() - { - return this._siteManager; - } - - addDefaultAction(action) { - this._defaultActions.push(action); - } - - setAddThemeAction(addThemeAction) { - this._addThemeAction = addThemeAction; - } - - getSiteContentId() { - return this._siteContentId; - } - - setSiteContentId(value) { - this._siteContentId = value; - } - - getActionBarMenuSelector() { - return this._actionBarMenuSelector; - } - - setActionBarMenuSelector(value) { - this._actionBarMenuSelector = value; - } - - getBasePath() { - return this._basePath; - } - - setBasePath(value) { - this._basePath = value; - } - - addDeepLink(alias, site) { - this._deepLinks.set(alias.toLowerCase(), site); - } - - setShowCookieCompliance(cookieCompliance) - { - this._showCookieCompliance = cookieCompliance; - } - - refreshCurrentSite() - { - this._siteManager.refreshCurrentSite(); - } - - pause(elementToShow){ - this.startSite(PauseSite, {"url": elementToShow}); - } - - resume(){ - const currentSite = this._siteManager.getCurrentSite(); - if (currentSite instanceof PauseSite) - { - currentSite.finish(); - } - } - - _resolveDeepLink(deepLink) { - deepLink = deepLink.toLowerCase(); - if (this._deepLinks.has(deepLink)) { - return this._deepLinks.get(deepLink); - } - return null; - } - - _getDeepLink() { - let deepLink = ""; - if (window.location.pathname.search(this._basePath) === 0) { - deepLink = window.location.pathname.substr(this._basePath.length).trim(); - } - if (deepLink.charAt(0) === '/') { - deepLink = deepLink.substr(1).trim(); - } - if (deepLink.charAt(deepLink.length - 1) === '/') { - deepLink = deepLink.substr(0, deepLink.length - 2).trim(); - } - if (deepLink.length === 0 && window.location.hash) { - deepLink = window.location.hash.substr(1).trim(); - } - - return this._resolveDeepLink(deepLink); - } - - _addDeepLinksListener() { - let app = this; - let elements = document.getElementsByClassName("deep-link"); - for (let i = 0, n = elements.length; i < n; i++) { - elements[i].addEventListener("click", function (e) { - e.preventDefault(); - app._siteManager.startSite(Helper.nonNull(app._resolveDeepLink(this.dataset["siteName"]), app._startSite), App._extractParams(this.dataset["siteArgs"])); - return true; - }); - } - } - - removeDefaultAction(action) - { - let index = this._defaultActions.indexOf(action); - if (index >= 0) - { - this._defaultActions[index].remove(true); - this._defaultActions.splice(index, 1); - } - } - - startSite(site, parameter) - { - return this._siteManager.startSite(site, parameter); - } - - start(fallbackStartSite) { - SystemSettings.setBasePath(this._basePath); - let startSite = Helper.nonNull(this._getDeepLink(), fallbackStartSite); - let startParams = App._getStartParams(); - this._startSite = fallbackStartSite; - - Translator.init(); - ThemeManager.init(); - if (this._addThemeAction) { - this.addDefaultAction(ThemeManager.generateChangeThemeMenuAction()); - } - this._siteManager = new SiteManager(this._siteContentId, this._actionBarMenuSelector); - this._siteManager.defaultActions = this._defaultActions; - this._siteManager.setStartSiteName(fallbackStartSite); - this._siteManager.startSite(startSite, startParams); - this._addDeepLinksListener(); - - if (this._showCookieCompliance) - { - this._cookieClosePromise = CookieCompliance.showIfNeeded('cookie-compliance'); - } - } - - getCurrentSite(){ - return this._siteManager.getCurrentSite(); - } - - async endApp(){ - if (typeof this._appEndListener === "function"){ - this._appEndListener(); - } - } - - setAppEndListener(appEndListener){ - this._appEndListener = appEndListener; - } - - async findSite(filter){ - return this._siteManager.findSite(filter); - } - - static _extractParams(paramString) { - if (Helper.isNull(paramString)) { - return null; - } - let result = {}, tmp = []; - let items = paramString.split("&"); - for (let index = 0; index < items.length; index++) { - tmp = items[index].split("="); - if (tmp[0].trim().length > 0) { - result[tmp[0]] = decodeURIComponent(tmp[1]); - } - } - return result; - } - - static _getStartParams() { - return App._extractParams(window.location.search.substr(1)); - } -} - -class Dialog { - constructor(content, title) { - this.resolver = null; - this.content = null; - this.backgroundElement = null; - this.cancelable = true; - this.title = Helper.nonNull(title, ""); - this.translatable = true; - this.additionalClasses = ""; - this.buttons = []; - this.result = null; - - if (Helper.isNotNull(content)) { - this.setContent(content); - } - } - - setTitle(title) { - this.title = title; - return this; - } - - setTranslatable(translatable) { - this.translatable = translatable; - } - - setAdditionalClasses(classes) { - this.additionalClasses = classes; - } - - getTitle() { - return this.title; - } - - setCancelable(cancelable) { - this.cancelable = (cancelable === true); - return this; - } - - async setContent(content) { - this.contentPromise = Promise.resolve(content); - this.content = await this.contentPromise; - return this; - } - - addButton(elementOrText, listenerOrResult, shouldClose) { - shouldClose = Helper.nonNull(shouldClose, true); - - let button = null; - if (typeof elementOrText === "string") { - button = document.createElement("button"); - button.classList.add("button"); - button.classList.add("right"); - button.appendChild(Translator.makePersistentTranslation(elementOrText)); - } - else { - button = elementOrText; - } - - let self = this; - if (typeof listenerOrResult !== "function") { - let result = listenerOrResult; - listenerOrResult = function () { - self.result = result; - }; - } - - let callback = null; - if (shouldClose) { - callback = function (e) { - if (Helper.isNotNull(listenerOrResult)) { - listenerOrResult(e); - } - self.close(); - }; - } - else { - callback = listenerOrResult; - } - - if (Helper.isNotNull(callback)) { - button.addEventListener("click", callback); - } - this.buttons.push(button); - } - - async show() { - - let titleElement = document.createElement("span"); - titleElement.classList.add("title"); - if (this.translatable && this.title !== "") { - titleElement.appendChild(Translator.makePersistentTranslation(this.title)); - } - else { - titleElement.innerHTML = this.title; - } - - let titleBar = document.createElement("div"); - titleBar.appendChild(titleElement); - - let contentContainer = document.createElement("div"); - contentContainer.classList.add("content-container"); - - let modalDialog = document.createElement("div"); - modalDialog.className = this.additionalClasses; - modalDialog.classList.add("modal"); - modalDialog.appendChild(titleBar); - modalDialog.appendChild(contentContainer); - - let buttonBar = document.createElement("div"); - buttonBar.classList.add("modal-button-container"); - - for (let i = 0, n = this.buttons.length; i < n; i++) { - buttonBar.appendChild(this.buttons[i]); - } - - await this.contentPromise; - if (!(this.content instanceof Node)) { - this.content = (this.translatable) ? Translator.makePersistentTranslation(this.content) : document.createTextNode(this.content); - } - contentContainer.appendChild(this.content); - - this.backgroundElement = document.createElement("div"); - this.backgroundElement.classList.add("background"); - this.backgroundElement.appendChild(modalDialog); - - this.backgroundElement.querySelector(".modal").appendChild(buttonBar); - this.backgroundElement.style.display = "block"; - - let self = this; - if (this.cancelable) { - let closeButton = document.createElement("span"); - closeButton.classList.add("close"); - closeButton.innerHTML = "×"; - - titleBar.appendChild(closeButton); - closeButton.addEventListener("click", function () { - self.close(); - }); - window.addEventListener("click", function (e) { - if (e.target === self.backgroundElement) { - self.close(); - } - }); - } - - document.body.appendChild(this.backgroundElement); - Translator.getInstance().updateTranslations(); - - return new Promise(function (resolve) { - self.resolver = resolve; - }); - } - - close() { - if (Helper.isNotNull(this.backgroundElement)) { - this.backgroundElement.style.display = "none"; - this.backgroundElement.remove(); - this.backgroundElement = null; - } - if (Helper.isNotNull(this.resolver)) { - this.resolver(this.result); - } - } - - addDefaultButton(){ - this.addButton("confirm-button"); - } -} - -class ConfirmDialog extends Dialog { - constructor(content, title) { - super(content, title); - } - - async show() { - this.addButton("confirm-button", true); - this.addButton("cancel-button", false); - - return super.show(); - } - - - close() { - if (Helper.isNull(this.result)) - { - this.result = false; - } - return super.close(); - } -} - -class FlashMessenger { - static deleteMessage(_idNumber, _delayInMilliSeconds) { - _delayInMilliSeconds = Helper.nonNull(_delayInMilliSeconds, 0); - setTimeout(function () { - let elem = document.getElementById("flashMessage" + _idNumber); - elem.fadeOut(.2).then(function () { - elem.remove(); - }); - }, _delayInMilliSeconds); - } - - static addMessage(messageType, messageText, timeToShow, translate){ - - let translationArgs = null; - if (Helper.isNull(messageText) || typeof messageText === "object") - { - translationArgs = messageText; - messageText = messageType; - messageType = FlashMessenger.MESSAGE_TYPE_SUCCESS; - translate = true; - } - translate = Helper.nonNull(translate, false); - - let id = FlashMessenger.messageCount; - - let wrapper = document.createElement("div"); - - let _flashMessage = document.createElement("div"); - _flashMessage.className = "flashMessage " + messageType; - _flashMessage.id = "flashMessage" + id; - _flashMessage.style.opacity = '0'; - _flashMessage.addEventListener("click", function () { - FlashMessenger.deleteMessage(id); - }); - _flashMessage.appendChild((translate) ? Translator.makePersistentTranslation(messageText, translationArgs, "span") : document.createTextNode(messageText)); - - wrapper.appendChild(_flashMessage); - document.getElementById("flashMessageContainer").appendChild(wrapper); - _flashMessage.fadeIn(); - timeToShow = Helper.nonNull(timeToShow, FlashMessenger.defaultTimeToShow); - if (timeToShow > 0) { - FlashMessenger.deleteMessage(FlashMessenger.messageCount, timeToShow); - } - FlashMessenger.messageCount++; - } -} - -FlashMessenger.messageCount = 0; -FlashMessenger.defaultTimeToShow = 3500; -FlashMessenger.LENGTH_SHORT= 1000; - -FlashMessenger.MESSAGE_TYPE_SUCCESS = 'success'; -FlashMessenger.MESSAGE_TYPE_ERROR = 'error'; -FlashMessenger.MESSAGE_TYPE_DEFAULT = 'default'; -FlashMessenger.MESSAGE_TYPE_INFO = 'info'; -FlashMessenger.MESSAGE_TYPE_WARNING = 'warning'; - -class MyDb { - constructor(dbName, version) { - this.queryPromise = new Promise(async (resolve, reject) => { - let indexedDB = null; - if (window["sqlite"]){ - indexedDB = new Promise(sqliteResolve => { - function testSqlLiteResolve(){ - if (window["sqliteIndexedDB"]){ - sqliteResolve(window["sqliteIndexedDB"]); - } - else { - setTimeout(testSqlLiteResolve, 200); - } - console.log("t"); - } - testSqlLiteResolve(); - }); - } - else { - indexedDB = Promise.resolve(window["myIndexedDB"] || window["indexedDB"] || window["mozIndexedDB"]|| window["webkitIndexedDB"]|| window["msIndexedDB"] || window["shimIndexedDB"]); - } - console.log("indexeddb 1"); - this.indexeddb = (await indexedDB); - console.log("indexeddb 2"); - this._conn = this.indexeddb.open(dbName, version); - - let myDB = this; - this._conn.onupgradeneeded = function (upgradeEvent) { - try { - myDB.upgrade(myDB._conn.result, upgradeEvent.oldVersion, upgradeEvent.newVersion, upgradeEvent); - } - catch(e){ - reject(e); - throw e; - } - }; - myDB._conn.onsuccess = function (e) { - myDB._db = myDB._conn.result; - resolve(e); - }; - }); - } - - openTransaction(name, transactionMode, callback) { - let myDb = this; - if (typeof transactionMode === 'function' && Helper.isNull(callback)) { - callback = transactionMode; - transactionMode = "read"; - } - - return this.queryPromise.then(function () { - let res = null; - try { - res = myDb._conn.result.transaction(name, transactionMode); - } - catch (e) { - console.warn(e); - res = myDb._conn.result.transaction(name); - } - callback(res); - }); - } - - openStore(name, transactionMode, callback) { - if (typeof transactionMode === 'function' && Helper.isNull(callback)) { - callback = transactionMode; - transactionMode = "readonly"; - } - return this.openTransaction(name, transactionMode, function (t) { - callback(t.objectStore(name)); - }); - } - - saveObj(obj, objectStore) { - let self = this; - return new Promise(function (resolve) { - self.openStore(objectStore, "readwrite", function (store) { - let request = store.put(obj); - request.onsuccess = resolve; - request.onerror = function (e) { - throw { - "type": "indexed-db-error", - "event": e - } - }; - }); - }); - } - - saveMany(manyObj, objectStore) { - let self = this; - return new Promise(function (resolve) { - self.openStore(objectStore, "readwrite", function (store) { - let promises = []; - for (let i = 0, n = manyObj.length; i < n; i++) { - promises.push(new Promise(function (resolveInner) { - let request = store.put(manyObj[i]); - request.onsuccess = resolveInner; - request.onerror = function (e) { - throw { - "type": "indexed-db-error", - "event": e - } - }; - })); - } - resolve(Promise.all(promises)); - }); - }); - } - - load(key, objectStore) { - let self = this; - return new Promise((resolve, reject) => { - self.openStore(objectStore, function (store) { - let request = store.get(key); - request.onsuccess = function (e) { - resolve(e.currentTarget.result); - }; - request.onerror = function (e) { - console.warn(e); - throw { - "type": "indexed-db-load-error", - "event": e - } - }; - }).catch(e => { - console.warn(e); - reject(e); - }); - }); - } - - loadAll(objectStore, query, count) { - let self = this; - return new Promise((resolve, reject) => { - self.openStore(objectStore, function (store) { - let request = store.getAll(query, count); - request.onsuccess = function (e) { - resolve(e.currentTarget.result); - }; - request.onerror = function (e) { - console.warn(e); - throw { - "type": "indexed-db-load-error", - "event": e - } - }; - }).catch(e => { - console.warn(e); - reject(e); - }); - }); - } - - loadMany(index, value, objectStore, limit, direction) { - let self = this; - return new Promise(function (resolve) { - self.openStore(objectStore, function (store) { - let indexRequest = store.index(index); - indexRequest.onerror = function (e) { - throw { - "type": "indexed-db-index-error", - "event": e - } - }; - let request = indexRequest.openCursor(value, direction); - request.onerror = function (e) { - throw { - "type": "indexed-db-index-error", - "event": e - } - }; - let objects = []; - let numberResults = 0; - request.onsuccess = function (e) { - let cursor = e.target.result; - if (cursor) { - objects.push(cursor.value); - numberResults++; - if (Helper.isNull(limit) || numberResults < limit) { - cursor.continue(); - return; - } - } - resolve(objects); - }; - }); - }); - } - - remove(id, objectStore) { - let self = this; - return new Promise(function (resolve) { - self.openStore(objectStore, "readwrite", function (store) { - let deleteRequest = store.delete(id); - deleteRequest.onerror = function (e) { - throw { - "type": "indexed-db-delete-error", - "event": e - } - }; - deleteRequest.onsuccess = function (e) { - resolve(); - }; - }); - }); - } - - removeMany(ids, objectStore) { - let self = this; - return new Promise(function (resolve) { - self.openStore(objectStore, "readwrite", function (store) { - let promises = []; - for (let i = 0, n = ids.length; i < n; i++) { - let deleteRequest = store.delete(ids[i]); - deleteRequest.onerror = function (e) { - throw { - "type": "indexed-db-delete-error", - "event": e - } - }; - promises.push(new Promise(function (resolve) { - deleteRequest.onsuccess = function () { - resolve(); - }; - })); - } - resolve(Promise.all(promises)); - }); - }); - } - - removeWithIndex(index, value, objectStore) { - let self = this; - return new Promise(function (resolve) { - self.openStore(objectStore, "readwrite", function (store) { - let indexRequest = store.index(index); - indexRequest.onerror = function (e) { - throw { - "type": "indexed-db-index-error", - "event": e - } - }; - let request = indexRequest.openCursor(value); - request.onerror = function (e) { - throw { - "type": "indexed-db-index-error", - "event": e - } - }; - request.onsuccess = function (e) { - let cursor = e.target.result; - if (cursor) { - cursor.delete(); - cursor.continue(); - } - else { - resolve(); - } - }; - }); - }); - } - - removeAll(objectStore) { - return new Promise((resolve) => { - this.openStore(objectStore, "readwrite", (store) => { - let req = store.clear(); - req.onerror = (e) => { - throw { - "type": "indexed-db-index-error", - "event": e - } - }; - req.onsuccess = resolve; - }); - }) - } - - upgrade(db) { - }; -} - -class ScriptLoader { - static loadScript(scriptSrc) { - if (Helper.isNotNull(ScriptLoader.scriptPromises[scriptSrc])) { - return ScriptLoader.scriptPromises[scriptSrc]; - } - else { - let scriptPromise = new Promise(function (resolve) { - let script = document.createElement("script"); - script.src = Helper.basePath(scriptSrc); - script.onload = resolve; - - document.body.appendChild(script); - }); - ScriptLoader.scriptPromises[scriptSrc] = scriptPromise; - return scriptPromise; - } - } - static loadCss(cssFile, media){ - if (Helper.isNotNull(ScriptLoader.cssPromises[cssFile])) { - return ScriptLoader.cssPromises[cssFile]; - } - else { - media = Helper.nonNull(media, "all"); - let cssPromise = new Promise(function (resolve) { - let link = document.createElement("link"); - link.rel='stylesheet'; - link.type="text/css"; - link.href = Helper.basePath(cssFile); - link.media = media; - link.onload = resolve; - - document.head.appendChild(link); - }); - ScriptLoader.cssPromises[cssFile] = cssPromise; - return cssPromise; - } - } -} - -ScriptLoader.scriptPromises = {}; -ScriptLoader.cssPromises = {}; - -class ShareButton { - constructor(deviceType, icon, callback, shouldLoadImg) - { - this._deviceType = deviceType; - this._icon = icon; - this._callback = callback; - - if (Helper.nonNull(shouldLoadImg, false)){ - this._icon = ViewInflater.inflate(this._icon); - } - } - - shouldShowFor(deviceType) - { - return (deviceType === (deviceType & this._deviceType)) - } - - getIcon() - { - return this._icon; - } - - getCallback() - { - return this._callback; - } -} -ShareButton.TYPE_DESKTOP = 1; -ShareButton.TYPE_MOBILE_APPLE = 2; -ShareButton.TYPE_MOBILE_LEFTOVER = 4; -ShareButton.TYPE_MOBILE = ShareButton.TYPE_MOBILE_APPLE+ShareButton.TYPE_MOBILE_LEFTOVER; -ShareButton.TYPE_ALL = ShareButton.TYPE_DESKTOP+ShareButton.TYPE_MOBILE; - -AndroidBridge.addDefinition(() => { - window["ShareButton"] = ShareButton; - window["ShareButton"]["TYPE_ALL"] = ShareButton.TYPE_ALL; - -}); - -class MultipleShareButton extends ShareButton{ - constructor(deviceType, icon, callbacks, shouldLoadImg) - { - if (Array.isArray(deviceType) && deviceType[0] instanceof ShareButton){ - let btn = deviceType[0]; - callbacks = deviceType; - deviceType = btn._deviceType; - icon = btn._icon; - shouldLoadImg = Helper.nonNull(shouldLoadImg, icon); - } - - super(deviceType, icon, function (link, element, event) { - if (!Array.isArray(callbacks)){ - callbacks = [callbacks]; - } - for (let i = 0; i < callbacks.length; i++) { - if (callbacks[i] instanceof ShareButton){ - callbacks[i].getCallback()(link, element, event); - } - else { - console.log(callbacks, i); - callbacks[i](link, element, event); - } - } - }, shouldLoadImg); - } -} - -class ShareManager { - static init() { - ShareManager.shareButtons = []; - } - - static addShareButton(shareButton) { - ShareManager.shareButtons.push(shareButton); - } - - static generateDefaultShareElement(shareUrl) { - return ShareManager.generateShareElement(shareUrl, ShareManager.getDefaultGenerateCallback()); - } - - static generateDefaultShareElementForButtons(shareUrl, buttons) { - return ShareManager.generateShareElementForButtons(shareUrl, buttons, ShareManager.getDefaultGenerateCallback()); - } - - static generateShareElement(shareUrl, generateCallback) { - return ShareManager.generateShareElementForButtons(shareUrl, ShareManager.shareButtons, generateCallback); - } - - static generateShareElementForButtons(shareUrl, buttons, generateCallback) { - let shareButtonElement = document.createElement("div"); - let currentDeviceType = ShareManager.getCurrentDeviceType(); - for (let i = 0, n = buttons.length; i < n; i++) { - if (buttons[i].shouldShowFor(currentDeviceType)) { - let elem = generateCallback(buttons[i], shareUrl); - elem.onclick = function (event) { - buttons[i].getCallback()(shareUrl, this, event); - }; - shareButtonElement.appendChild(elem); - } - } - return shareButtonElement; - } - - static getCurrentDeviceType() { - if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) { - return ShareButton.TYPE_MOBILE_APPLE; - } - else if ((navigator.userAgent.match(/Android|BlackBerry|Opera Mini|IEMobile/i) !== null || (typeof window.orientation !== "undefined"))) { - return ShareButton.TYPE_MOBILE_LEFTOVER; - } - else { - return ShareButton.TYPE_DESKTOP; - } - } - - static getDefaultGenerateCallback() { - return function (button) { - let linkElement = document.createElement("a"); - linkElement.classList.add("share-icon"); - let iconUrl = button.getIcon(); - if (typeof iconUrl === "string") { - let iconElement = document.createElement("img"); - iconElement.src = Helper.basePath(button.getIcon()); - iconElement.classList.add("share-icon"); - linkElement.appendChild(iconElement); - } - else { - Promise.resolve(iconUrl).then(elem => { - linkElement.appendChild(elem); - }); - } - - return linkElement; - } - } -} - -ShareManager.init(); - -AndroidBridge.addDefinition("ShareManager.addShareButton", ShareManager.addShareButton); - -class SmsShareButton extends ShareButton -{ - constructor(icon, shouldLoadImg) { - super(ShareButton.TYPE_MOBILE, icon, function (link) { - let linkToOpen = ""; - if (ShareManager.getCurrentDeviceType() === ShareButton.TYPE_MOBILE_APPLE) { - linkToOpen = "sms:&body="+encodeURIComponent(link); - } - else { - linkToOpen = "sms:?&body=" + encodeURIComponent(link); - } - window.open(linkToOpen, '_blank', "noopener"); - }, shouldLoadImg); - } -} - -class TelegramShareButton extends ShareButton { - constructor(icon, shouldLoadImg) { - super(ShareButton.TYPE_ALL, icon, function (link) { - let linkToOpen = "https://t.me/share/url?url="+encodeURIComponent(link); - window.open(linkToOpen, '_blank', "noopener"); - }, shouldLoadImg); - } -} - -class WhatsappShareButton extends ShareButton { - constructor(icon, shouldLoadImg) { - super(ShareButton.TYPE_ALL, icon, function (link) { - let linkToOpen = ""; - if (ShareManager.getCurrentDeviceType() === ShareButton.TYPE_DESKTOP) { - linkToOpen = "https://web.whatsapp.com/send?text="+encodeURIComponent(link); - } - else { - linkToOpen = "whatsapp://send?text=" + encodeURIComponent(link); - } - window.open(linkToOpen, '_blank', "noopener"); - }, shouldLoadImg); - } -} - -class Fragment extends Context -{ - constructor(site, view) - { - super(view); - this.site = site; - this.active = true; - } - - getSite() - { - return this.site; - } - - isActive() - { - return this.active; - } -} - -class Theme -{ - constructor(name, className, icon) - { - this._name = name; - this._className = className; - this._icon = icon; - } -} - -function applyPolyfills() { - if (!String.prototype.format) { - String.prototype["format"] = function (args) { - return this.replace(/{(\d+)}/g, function (match, number) { - return args[number] !== undefined - ? args[number] - : match - ; - }); - }; - } - Object["assign"] = Helper.nonNull(Object["assign"], function (base, obj) { - base = Helper.nonNull(base, {}); - if (obj === null || typeof(obj) !== 'object' || 'isActiveClone' in obj) - return base; - - // if (obj instanceof Date) { - // temp = new obj.constructor(); //or new Date(obj); - // } - // else { - // temp = obj.constructor(); - // } - - for (let key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key)) { - obj['isActiveClone'] = null; - base[key] = obj[key]; - delete obj['isActiveClone']; - } - } - - return base; - }); - - if (typeof window !== 'undefined') { - if (Helper.isNotNull(window["Node"]) && !window["Node"]["prototype"]["removeAllChildren"]) { - Node.prototype["removeAllChildren"] = function () { - while (this.firstChild) { - this.removeChild(this.firstChild); - } - return this; - }; - } - - if (HTMLElement) { - HTMLElement.prototype["fadeOut"] = Helper.nonNull(HTMLElement.prototype["fadeOut"], - function (time, effect, delay) { - time = Helper.nonNull(time, 0.5); - effect = Helper.nonNull(effect, "ease-in-out"); - delay = Helper.nonNull(delay, 0); - this.style.transition = "opacity " + time + "s " + effect + " " + delay + "s"; - let elem = this; - let animPromise = new Promise(function (resolve) { - let transEndLis = function (e) { - elem.removeEventListener("transitionend", transEndLis); - elem.removeEventListener("transitioncancel", transCancelledLis); - elem.style.opacity = null; - elem.style.transition = null; - resolve(true, e); - }; - - let transCancelledLis = function (e) { - elem.removeEventListener("transitionend", transEndLis); - elem.removeEventListener("transitioncancel", transCancelledLis); - elem.style.opacity = null; - elem.style.transition = null; - resolve(false, e); - }; - elem.addEventListener("transitionend", transEndLis); - elem.addEventListener("transitioncancel", transCancelledLis); - //Fallback - setTimeout(() => { - resolve(false); - }, (time + delay) * 1000); - }); - - //Nach Seitenneuzeichnen, damit chrome das immer macht (und FF auch) - requestAnimationFrame(function () { - requestAnimationFrame(function () { - elem.style.opacity = 0; - }); - }); - return animPromise - }); - - HTMLElement.prototype["fadeIn"] = Helper.nonNull(HTMLElement.prototype["fadeIn"], function (time, effect, delay) { - time = Helper.nonNull(time, 0.5); - effect = Helper.nonNull(effect, "ease-in-out"); - delay = Helper.nonNull(delay, 0); - this.style.transition = "opacity " + time + "s " + effect + " " + delay + "s"; - - let elem = this; - let animPromise = new Promise(function (resolve) { - let transEndLis = function (e) { - elem.removeEventListener("transitionend", transEndLis); - elem.removeEventListener("transitioncancel", transCancelledLis); - elem.style.opacity = null; - elem.style.transition = null; - resolve(true, e); - }; - - let transCancelledLis = function (e) { - elem.removeEventListener("transitionend", transEndLis); - elem.removeEventListener("transitioncancel", transCancelledLis); - elem.style.opacity = null; - elem.style.transition = null; - resolve(false, e); - }; - elem.addEventListener("transitionend", transEndLis); - elem.addEventListener("transitioncancel", transCancelledLis); - - if (getComputedStyle(elem).getPropertyValue("opacity") === "1") { - resolve(false); - } - //Fallback - setTimeout(() => { - resolve(false); - }, (time + delay) * 1000); - - //Nach Seitenneuzeichnen, damit chrome das immer macht (und FF auch) - requestAnimationFrame(function () { - requestAnimationFrame(function () { - elem.style.opacity = 1; - }); - }); - }); - return animPromise; - }); - } - - if (Node) { - Node.prototype["replaceWith"] = Helper.nonNull(Node.prototype["replaceWith"], function (elem) { - this.parentElement.replaceChild(elem, this); - }); - Node.prototype["remove"] = Helper.nonNull(Node.prototype["remove"], function () { - this.parentElement.removeChild(this); - }); - } - - if (Element) { - Element.prototype.matches = Helper.nonNull(Element.prototype.matches, Helper.nonNull(Element.prototype["matchesSelector"], Element.prototype["webkitMatchesSelector"])); - - window["Element"]["prototype"]["closest"] = Helper.nonNull(window["Element"]["prototype"]["getAll"], function (s) { - // if (!Element.prototype.matches) - // Element.prototype.matches = Element.prototype.msMatchesSelector || - // Element.prototype.webkitMatchesSelector; - // - // if (!Element.prototype.closest) - // Element.prototype.closest = function(s) { - let el = this; - if (!document.documentElement.contains(el)) return null; - do { - if (el.matches(s)) return el; - el = el.parentElement; - } while (el !== null); - return null; - // }; - }); - } - - window["IDBObjectStore"]["prototype"]["getAll"] = Helper.nonNull(window["IDBObjectStore"]["prototype"]["getAll"], function () { - let res = {}; - let items = []; - this.openCursor().onsuccess = function (e) { - let cursor = e.target.result; - if (Helper.isNotNull(cursor)) { - items.push(cursor.value); - cursor.continue(); - } - else if (Helper.isNotNull(res.onsuccess)) { - res.onsuccess({currentTarget: {result: items}}); - } - }; - return res; - }); - } - - String.prototype.startsWith = Helper.nonNull(String.prototype.startsWith, function (searchString, position) { - position = position || 0; - return this.indexOf(searchString, position) === position; - }); - - String.prototype.includes = Helper.nonNull(String.prototype.includes, function (searchString) { - return this.indexOf(searchString) >= 0; - }); - - String.prototype.endsWith = Helper.nonNull(String.prototype.endsWith, function (searchString, position) { - var subjectString = this.toString(); - if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) { - position = subjectString.length; - } - position -= searchString.length; - var lastIndex = subjectString.indexOf(searchString, position); - return lastIndex !== -1 && lastIndex === position; - }); - - - window["fetch"] = Helper.nonNull(window["fetch"], function (url, params) { - console.log("customFetch", url); - let request = null; - if (window.XMLHttpRequest) { // Mozilla, Safari, ... - request = new XMLHttpRequest(); - } else if (window.ActiveXObject) { // IE - try { - request = new ActiveXObject('Msxml2.XMLHTTP'); - } - catch (e) { - try { - request = new ActiveXObject('Microsoft.XMLHTTP'); - } - catch (e) { - } - } - } - - let onloadPromise = new Promise((r) => { - // this.result - request.onload = r; - request.onerror = function (err) { - r(Promise.reject(err)); - }; - }); - - let resultPromise = new Promise(function (resolve) { - - let response = { - "json": function () { - request.send(); - - return onloadPromise.then(() => { - return JSON.parse(request.responseText) - }); - }, - "text": function () { - request.send(); - return onloadPromise.then(() => request.responseText); - }, - "arrayBuffer": () => { - request.responseType = "arraybuffer"; - request.send(); - return onloadPromise.then(() => request.response); - } - }; - resolve(response); - }); - - - request.open('get', url, true); - // request.send(); - return resultPromise; - }); -} - -class Constants{} -Constants.SCRIPTS = { - CKEDITOR:"version/2/ckeditor/ckeditor.js", - LIST_JS: "version/1/listjs/list.min.js" -}; - -class DataManager { - static async load(url, isCachable, raw) { - isCachable = Helper.nonNull(isCachable, false); - raw = Helper.nonNull(raw, false); - let fullUrl = (isCachable) ? Helper.basePath(DataManager.cachePath + url) : Helper.basePath(DataManager.dataPath + url); - - return this._load(fullUrl, raw); - } - - static async _load(url, raw) { - return fetch(url, {"credentials": "same-origin"}).then(function (res) { - if (raw) { - return res.text(); - } - return res.json(); - }).catch(function (e) { - if (!raw) { - return { - "success": false, - "errors": [ - "not-online" - ] - } - } - }); - } - - static async loadStatic(url, raw) { - raw = Helper.nonNull(raw, false); - let fullUrl = Helper.basePath(url); - - return this._load(fullUrl, raw); - } - - static async send(url, params) { - let fullUrl = Helper.basePath(DataManager.dataPath + url); - - if (!(params instanceof FormData)) { - let newParams = new FormData(); - for (let k in params) { - newParams.append(k, params[k]); - } - params = newParams; - } - - return fetch(fullUrl, { - "credentials": "same-origin", - "method": "POST", - "body": params - }).then(function (res) { - return res.json(); - }).catch(function (e) { - console.error("error", e); - return { - "success": false, - "errors": [ - "not-online" - ] - } - }); - } - - static buildQuery(values) { - return Helper.buildQuery(values); - } -} - -DataManager.dataPath = "data/"; -DataManager.cachePath = "cached/"; - -class Form { - constructor(formElem, url, method, isCachable) { - this.formElem = formElem; - this.method = Helper.nonNull(method, Helper.nonNull(formElem["method"], "POST")); - this.isCachable = (Helper.nonNull(isCachable, this.method.toLowerCase() === "get") === true); - - this.isBusy = false; - - if (typeof url === "string") - { - this.submitHandler = function(values){ - if (self.method.toLowerCase() === "get") { - return (DataManager.load(url + DataManager.buildQuery(values), self.isCachable)); - } - else { - return (DataManager.send(url, values)); - } - }; - } - else { - this.submitHandler = url; - } - - let self = this; - - this.submitCallback = null; - this.errorCallback = async function (errors) { - await self.setErrors(errors); - }; - - formElem.addEventListener("submit", async function (e) { - console.log("submitting!", e); - e.preventDefault(); - await self.doSubmit(e); - }); - - for (let i = 0, n = formElem.elements.length; i < n; i++) { - let elem = formElem.elements[i]; - elem.addEventListener("change", function () { - if (this.value.trim() !== "") { - this.classList.add("notEmpty"); - } - else { - this.classList.remove("notEmpty"); - } - this.setCustomValidity(""); - }); - elem.addEventListener("keydown", function () { - this.setCustomValidity(""); - }); - } - } - - onError(errorHandler, ownHandlerForOptimisticLocking){ - ownHandlerForOptimisticLocking = Helper.nonNull(ownHandlerForOptimisticLocking, true); - let callback = null; - - if (ownHandlerForOptimisticLocking){ - callback = function(errors){ - if (Array.isArray(errors) && errors.indexOf("optimistic-locking-exception") >= 0){ - let dialog = new Dialog("optimistic-locking-dialog", "optimistic-locking-dialog-title"); - dialog.addDefaultButton(); - dialog.show(); - } - else - { - errorHandler(errors); - } - }; - } - else - { - callback = errorHandler; - } - this.errorCallback = callback; - } - - doSubmit() { - if (!this.isBusy) { - let self = this; - return this.submit().then(function (res) { - if (res["success"]) { - if (self.submitCallback !== null) { - return self.submitCallback(res["result"]); - } - } - else if (Helper.isNotNull(self.errorCallback)) { - return self.errorCallback(res["errors"]); - } - }); - } - } - - load(url, isCached) { - this.setValues(DataManager.load(url, isCached).then(function (values) { - if (values["success"]) { - return values["result"]; - } - return {}; - })); - return this; - } - - setValues(valuePromise) { - this.setIsBusy(true); - - let self = this; - return Promise.resolve(valuePromise).then(function (values) { - self.setIsBusy(false); - for (let k in values) { - if (Helper.isNotNull(self.formElem.elements[k])) { - if (Helper.isNotNull(self.formElem.elements[k].options) && Helper.isNotNull(values[k+"Options"])) - { - let options = self.formElem.elements[k].options; - for (let val in values[k+"Options"]) - { - let option = document.createElement("option"); - option.value = val; - option.innerText = values[k+"Options"][val]; - options.add(option); - } - } - - self.formElem.elements[k].value = Helper.htmlspecialcharsDecode(values[k]); - if (Helper.isNotNull(values[k]) && (""+values[k]).trim() !== "") { - self.formElem.elements[k].classList.add("notEmpty"); - } - else { - self.formElem.elements[k].classList.remove("notEmpty"); - } - } - } - return self; - }); - } - - async setErrors(errors) { - let hasElem = false; - let firstError = null; - - for (let k in errors) { - if (Helper.isNotNull(this.formElem.elements[k]) && this.formElem.elements[k].type !== "hidden" - && Helper.isNull(this.formElem.elements[k].readonly) && ( - Helper.isNull(this.formElem.elements[k].disabled) || !this.formElem.elements[k].disabled) - ) { - this.formElem.elements[k].setCustomValidity(Translator.translate(Helper.nonNull(errors[k], "form-default-error"))); - hasElem = true; - } - if (Helper.isNull(firstError)) { - firstError = Helper.nonNull(errors[k], "form-default-error"); - } - } - if (!hasElem && Helper.isNotNull(firstError)) { - for (let k in this.formElem.elements) { - if (this.formElem.elements[k].type !== "hidden") { - this.formElem.elements[k].setCustomValidity(Translator.translate(firstError)); - hasElem = true; - break; - } - } - } - - if (hasElem) { - this.formElem.querySelector("input[type=submit]").click(); - } - } - - setIsBusy(isBusy) { - this.isBusy = isBusy; - if (this.isBusy) { - this.formElem.classList.add("sending"); - } - else { - this.formElem.classList.remove("sending"); - } - } - - submit() { - let self = this; - return new Promise(function (resolve) { - self.setIsBusy(true); - let values = new FormData(self.formElem); - resolve(self.submitHandler(values)); - }).then(function (data) { - self.setIsBusy(false); - return data; - }); - } - - onSubmit(callback) { - this.submitCallback = callback; - } -} - -class SettingsManager { - static getInstance() { - if (SettingsManager._instance === null) { - SettingsManager._instance = new SettingsManager(); - } - return SettingsManager._instance; - } - - constructor() { - this._settings = null; - this._localStorageKey = "settings"; - } - - getSettings() { - if (Helper.isNull(this._settings)) { - this._loadSettings(); - } - return this._settings; - } - - getSetting(name, defaultValue) { - const settings = this.getSettings(); - - if (Helper.isNotNull(settings[name])) { - return settings[name].value; - } - else { - return defaultValue; - } - } - - deleteSetting(name) { - this.getSettings(); - delete this._settings[name]; - this._saveSettings(); - } - - setSetting(name, value) { - this.getSettings(); - this._settings[name] = { - date: new Date().getTime(), - value: value - }; - this._saveSettings(); - } - - setSettings(settingsObject) { - this.getSettings(); - for (const k in settingsObject) { - this._settings[k] = settingsObject[k]; - } - this._saveSettings(); - } - - hasSetting(name) - { - return Helper.nonNull(this._settings[name]); - } - - _loadSettings() { - this._settings = localStorage.getItem(this._localStorageKey); - if (this._settings === null) { - this._settings = {}; - } - else { - this._settings = JSON.parse(this._settings); - } - } - - _saveSettings() { - if (this._settings !== null) { - localStorage.setItem(this._localStorageKey, JSON.stringify(this._settings)); - } - } -} - -SettingsManager._instance = null; - -class LocalStorageSettingsFragment extends Fragment { - onFirstStart() { - let res = super.onFirstStart(); - let settings = this.findBy(".setting", true); - const settingsManager = SettingsManager.getInstance(); - - for (let i = 0; i < settings.length; i++) { - let setting = settings[i]; - const name = setting.name; - let value; - if (!setting["dataset"]["raw"]) { - value = settingsManager.getSetting(name); - } else { - value = localStorage.getItem(name); - } - - let isCheckable = false; - if (setting instanceof HTMLInputElement && (setting.type === 'checkbox' || setting.type === 'radio')) { - isCheckable = true; - } - if (((!setting["dataset"]["raw"] && !settingsManager.hasSetting(name)) || (setting["dataset"]["raw"] && value === null)) - && Helper.isNotNull(settings[i]["dataset"]["default"])) { - value = setting["dataset"]["default"]; - if (Helper.isNotNull(setting["dataset"]["defaultTranslateable"])) { - - setting["dataset"]["translation"] = ""; - setting["dataset"]["translationValue"] = value; - value = Translator.translate(value); - } - } - - if (Helper.isNotNull(value)) { - if (isCheckable) { - setting.checked = (value === setting.value); - } - else { - setting.value = value; - } - if (value !== "") { - setting.classList.add("notEmpty"); - } - } - - setting.addEventListener("change", function () { - let value = this.value; - if (isCheckable && !this.checked) { - value = null; - } - if (!setting["dataset"]["raw"]) { - settingsManager.setSetting(name, value); - } else { - localStorage.setItem(name, value); - } - delete setting["dataset"]["translationValue"]; - delete setting["dataset"]["translation"]; - }); - } - return res; - } - - onStart() { - let res = super.onStart(); - let settings = this.findBy(".setting", true); - const settingsManager = SettingsManager.getInstance(); - - for (let i = 0; i < settings.length; i++) { - let setting = settings[i]; - const name = setting.name; - let value; - if (!setting["dataset"]["raw"]) { - value = settingsManager.getSetting(name); - } else { - value = localStorage.getItem(name); - } - - let isCheckable = false; - if (setting instanceof HTMLInputElement && (setting.type === 'checkbox' || setting.type === 'radio')) { - isCheckable = true; - } - - if (Helper.isNotNull(value)) { - if (isCheckable) { - setting.checked = (value === setting.value); - } - else { - setting.value = value; - } - if (value !== "") { - setting.classList.add("notEmpty"); - } - } - } - return res; - } -} - -class SmartColumn{ - constructor(name, label, translateable){ - this._name = name; - this._label = label; - this._translateable = Helper.nonNull(translateable, true); - this._sortable = true; - - this._index = -1; - - this._clickListener = null; - } - - setClickListener(listener) - { - this._clickListener = listener; - return this; - } - - setIndex(index) - { - this._index = index; - } - - getName() - { - return this._name; - } - - getLabel() - { - return this._label; - } - - getHeadElement() - { - const headElement = document.createElement("th"); - headElement.appendChild((this._translateable)?Translator.makePersistentTranslation(this._label):document.createTextNode(this._label)); - - if (this._sortable) - { - headElement.classList.add("sort"); - headElement["dataset"]["sort"] = this._name; - } - - headElement["dataset"]["column"] = this._index; - - this._headElement = headElement; - return this._headElement; - } - - getValueName(){ - return this._name; - } - - prepareData(myData, rowData) - { - return myData; - } - - getItemElement(){ - const element = document.createElement("td"); - element.classList.add(this._name); - element["dataset"]["column"] = this._index; - - if (Helper.isNotNull(this._clickListener)) - { - element.classList.add("clickable"); - } - - return element; - } - - click(tableCell, table, event){ - if (Helper.isNotNull(this._clickListener)) - { - this._clickListener(tableCell, table, event); - } - } -} - -class ConstSmartColumn extends SmartColumn{ - constructor(name, label, translatable, valueTranslatable) { - super(name, label, translatable); - this._sortable = false; - this._valueTranslatable = Helper.nonNull(valueTranslatable, false); - } - - getValueName() { - return null; - } - - getItemElement(){ - const element = super.getItemElement(); - element.classList.remove(this._name); - element.appendChild((this._valueTranslatable)?Translator.makePersistentTranslation(this._name):document.createTextNode(this._name)); - return element; - } -} - -class DataSmartColumn extends SmartColumn{ - constructor(name, label, translateable) { - translateable = Helper.nonNull(translateable, false); - super(name, label, translateable); - } - - getHeadElement() { - return document.createTextNode(""); - } - - getValueName() { - return { - "data":[this._name] - }; - } - - getItemElement() { - return document.createTextNode(""); - } -} - -class ImgConstSmartColumn extends ConstSmartColumn{ - constructor(name, label, translateable) { - super(name, label, translateable); - this._valueTranslatable = false; - } - - getItemElement() { - const element = super.getItemElement(); - const imgElement = document.createElement("img"); - imgElement["src"] = this._name; - - element.removeAllChildren().appendChild(imgElement); - return element; - } -} - -class ListHelper { - constructor(id, options, values) { - this._tableElement = id; - this._options = Helper.nonNull(options, {}); - this._values = values; - - if (typeof this._tableElement === "string") { - this._tableElement = document.getElementById(this._tableElement); - } - - this._columns = []; - if (Array.isArray(options)) { - this._columns = options; - } - else if (Helper.isNotNull(options["columns"])) { - this._columns = options["columns"]; - } - } - - prepareData(data) { - console.log("prepareData", data); - if (Helper.isNotNull(data)) { - for (let i = 0, n = data.length; i < n; i++) { - data[i] = this.prepareDataset(data[i]); - } - } - return data; - } - - prepareDataset(dataset) { - console.log("prepareDataset", dataset); - for (let i = 0, n = this._columns.length; i < n; i++) { - if (Helper.isNotNull(dataset[this._columns[i].getName()])) { - dataset[this._columns[i].getName()] = this._columns[i].prepareData(dataset[this._columns[i].getName()], dataset); - } - } - return dataset; - } - - createTable() { - if (Helper.isNotNull(this._columns)) { - this.updateColumns(); - } - - let id = this._tableElement; - let options = this._options; - let values = this._values; - - options["item"] = Helper.nonNull(options["item"], id["id"] + "-template-item"); - options["page"] = Helper.nonNull(options["page"], 5); - options["pagination"] = Helper.nonNull(options["pagination"], { - "outerWindow": 1, - "innerWindow": 1 - }); - - let template = document.getElementById(options["item"]); - if (template) { - options["item"] = template.outerHTML; - template.remove(); - } - - values = this.prepareData(values); - - const list = new List(id, options, values); - let self = this; - id.querySelector("." + Helper.nonNull(options["listClass"], "list")).addEventListener("click", function (e) { - let columnElem = e.target.closest("td[data-column]"); - const column = parseInt(columnElem["dataset"]["column"]); - if (self._columns.length > column) { - self._columns[column].click(columnElem, list, e); - } - }); - this.list = list; - - return list; - } - - updateColumns() { - const head = document.createElement("tr"); - const item = document.createElement("tr"); - const valueNames = []; - - for (let i = 0, n = this._columns.length; i < n; i++) { - this._columns[i].setIndex(i); - - head.appendChild(this._columns[i].getHeadElement()); - item.appendChild(this._columns[i].getItemElement()); - - const valueName = this._columns[i].getValueName(); - if (Helper.isNotNull(valueName)) { - valueNames.push(valueName); - } - } - const header = this._tableElement.querySelector("thead"); - const footer = this._tableElement.querySelector("tfoot"); - - if (Helper.isNotNull(header)) { - header.removeAllChildren().appendChild(head); - } - if (Helper.isNotNull(footer)) { - footer.removeAllChildren().appendChild(Helper.cloneNode(head)); - } - - - this._options["item"] = item.outerHTML; - this._options["valueNames"] = valueNames; - } - - getList() { - return this.list; - } - - updateItem(valueName, value, newValues) { - const items = this.list.get(valueName, value); - if (Helper.isNotNull(items) && items.length >= 1) { - newValues = this.prepareDataset(newValues); - items[0].values(newValues); - } - } - - setBusy(isBusy) { - if (isBusy) { - this._tableElement.classList.add("sending"); - } - else { - this._tableElement.classList.remove("sending"); - } - } -} - -class SettingsSite extends AbstractSite { - constructor(siteManager) { - super(siteManager, SettingsSite.template, "settings"); - for (let k in SettingsSite.settingsFragments) { - this.addSettingsFragment(k, new SettingsSite.settingsFragments[k](this)); - } - this.active = null; - } - - addSettingsFragment(name, settingsFragment) { - this.addFragment("#settings-fragments", settingsFragment); - delete this.fragments["#settings-fragments"]; - this.fragments[name] = settingsFragment; - } - - onStart() { - let res = super.onStart(); - if (Helper.isNotNull(this.active) && !this.fragments[this.active].isActive()) { - this.setActive(null); - } - - this.buildList(); - return res; - } - - setActive(name) { - if (Helper.isNotNull(this.active)) { - this.fragments[this.active].inflatePromise.then(function (view) { - view.classList.remove("active"); - }); - this.findBy("#show-fragment-" + this.active).classList.remove("active"); - } - this.active = name; - if (Helper.isNotNull(this.active)) { - this.fragments[this.active].inflatePromise.then(function (view) { - view.classList.add("active"); - }); - this.findBy("#show-fragment-" + this.active).classList.add("active"); - } - } - - buildList() { - let listNameElem = this.findBy("#settings-fragment-list"); - listNameElem.removeAllChildren(); - - let self = this; - for (let k in this.fragments) { - if (this.fragments[k].isActive()) { - - let liElement = document.createElement("li"); - liElement.id = "show-fragment-" + k; - liElement.appendChild(Translator.makePersistentTranslation(k, null, "a")); - liElement.addEventListener("click", function () { - self.setActive(k); - }); - listNameElem.appendChild(liElement); - - if (Helper.isNull(this.active)) { - this.setActive(k); - } - } - } - } - - static addSettingsFragment(name, settingsFragment) { - SettingsSite.settingsFragments[name] = settingsFragment; - } - - static setAddSettingsSite(addLink) { - SettingsSite.shouldAddSettingsSite = addLink; - } - - static setTemplate(template) { - SettingsSite.template = template; - } -} - -SettingsSite.template = 'core/html/settings.html'; -SettingsSite.settingsFragments = {}; -SettingsSite.shouldAddSettingsSite = true; -SettingsSite.settingsAction = null; -SettingsSite.shouldAddSettingsAction = true; - -InitPromise.addPromise(function (app) { - if (SettingsSite.shouldAddSettingsSite) { - app.addDeepLink("settings", SettingsSite); - - if (Helper.isNull(SettingsSite.settingsAction)) { - let settingsAction = new MenuAction("settings", async () => { - let currentSite = app.getCurrentSite(); - if (currentSite instanceof SettingsSite) { - currentSite.finish(); - } - else { - let settingsSite = await app.findSite((site) => { - return (site instanceof SettingsSite); - }); - if (Helper.isNotNull(settingsSite)) { - settingsSite.toForeground(); - } - else { - app.startSite(SettingsSite); - } - } - }, MenuAction.SHOW_FOR_LARGE, 10000); - settingsAction.setIcon("img/settings.png"); - SettingsSite.settingsAction = settingsAction; - } - if (SettingsSite.shouldAddSettingsAction) { - app.addDefaultAction(SettingsSite.settingsAction); - } - } -}); - -class UserManager { - static init(app) { - UserManager.getMeUrl = null; - UserManager.userData = { - online: false, - id: null, - accesses: ["default"] - }; - UserManager.app = app; - - UserManager.fetchMePromise = new Promise(function (resolve) { - UserManager.fetchMePromiseResolver = resolve; - }); - } - - static setData(data) { - UserManager.userData = Object.assign(UserManager.userData, data); - let siteManager = UserManager.app.getSiteManager(); - - if (siteManager) - siteManager.redrawCurrentActionBar(); - } - - static fetchMe(url) { - UserManager.getMeUrl = Helper.nonNull(url, UserManager.getMeUrl); - return DataManager.load(UserManager.getMeUrl).then(function (result) { - if (result["success"]) { - UserManager.setData(result["result"]); - } - UserManager.fetchMePromiseResolver(); - }); - } - - static logOut() { - return DataManager.load("u/logout").then(function (data) { - if (data["success"]) { - UserManager.setData(data["result"]); - let siteManager = UserManager.app.getSiteManager(); - - if (siteManager) - siteManager.refreshCurrentSite(); - FlashMessenger.addMessage(FlashMessenger.MESSAGE_TYPE_SUCCESS, Translator.translate("logged-out-successfully")); - } - }); - } - - static hasAccess(access) { - // console.log("Has access", access, UserManager.userData["accesses"].indexOf(access), UserManager.userData); - return (UserManager.userData["accesses"].indexOf(access) >= 0) - } - - static addCurrentUserListener(userId, listener) { - UserManager.addIsLoggedInListener(function (isLoggedIn) { - listener(isLoggedIn && UserManager.isCurrentUser(userId)); - }); - } - - static addIsLoggedInListener(listener) { - this.fetchMePromise.then(function () { - listener(UserManager.isLoggedIn()); - }); - } - - static isCurrentUser(userId) { - return UserManager.userData.id === userId; - } - - static isLoggedIn() { - return Helper.isNotNull(UserManager.userData) && Helper.isNotNull(UserManager.userData.id); - } -} - -InitPromise.addPromise(function(app){ - UserManager.init(app); - return UserManager.fetchMe("u/me").then(function(){ - UserManager.addIsLoggedInListener(function (isLoggedIn) { - if (isLoggedIn) { - const settingsManager = SettingsManager.getInstance(); - const settings = Helper.cloneJson(settingsManager.getSettings()); - for (let k in settings) { - settings[k]["value"] = JSON.stringify(settings[k]["value"]); - } - DataManager.send("u/syncSettings", settings).then(function(res){ - if (res["success"]) - { - for (let k in res["result"]) - { - res["result"][k]["value"] = JSON.parse(res["result"][k]["value"]); - } - settingsManager.setSettings(res["result"]); - } - }); - } - }); - }); -}); - -class UserAction extends MenuAction { - constructor(title, callback, icon, order, access) { - super(title, callback, icon, order); - this._access = Helper.nonNull(access, "default"); - } - - getVisible() { - // console.log("Action-access: ", this._access); - return (super.getVisible() && UserManager.hasAccess(this._access)); - } - - getAccess() { - return this._access; - } - - copy(instance){ - let copy = super.copy(Helper.nonNull(instance, new UserAction())); - copy._access = this._access; - return copy; - } -} - -class NotAllowedSite extends AbstractSite{ - constructor(siteManager) { - super(siteManager, 'userManagement/html/403.html'); - } -} - -class UserSite extends AbstractSite { - - constructor(siteManager, view, deepLink, access) { - super(siteManager, view, deepLink); - this._access = access; - } - - onConstruct(args) { - if (!UserManager.hasAccess(this._access)) - { - this.startSite(NotAllowedSite); - this.finish({ - "error":403 - }); - return; - } - return super.onConstruct(args); - } - - onStart(args) { - if (!UserManager.hasAccess(this._access)) - { - this.startSite(NotAllowedSite); - this.finish({ - "error":403 - }); - return; - } - return super.onStart(args); - } -} - -class LoginForm extends Form { - - constructor(formElem, url, method, isCachable) { - super(formElem, url, method, isCachable); - - let emailElem = formElem.querySelector("#email"); - let passwordElem = formElem.querySelector("#password"); - - let listener = function(){ - emailElem.setCustomValidity(""); - passwordElem.setCustomValidity(""); - }; - - emailElem.addEventListener("keydown", listener); - passwordElem.addEventListener("keydown", listener); - } -} - -class RegistrationForm extends Form { - constructor(formElem, url, method, isCachable) { - super(formElem, url, method, isCachable); - - // this.pw1 = formElem.querySelector("#password1"); - // this.pw2 = formElem.querySelector("#password2"); - - // let self=this; - // this.pw1.addEventListener("change", function(){ - // self.checkPw(); - // }); - // this.pw2.addEventListener("change", function(){ - // self.checkPw(); - // }); - } - - checkPw(){ - // if (this.pw1.value !== this.pw2.value || this.pw1.value.length < 8) - // { - // - // } - } -} - -class UserFragment extends Fragment{ - - constructor(site, view, access) { - super(site, view); - this._access = access; - } - - isActive() { - return super.isActive() && UserManager.hasAccess(this._access); - } -} - -class PasswordSettingsFragment extends UserFragment{ - constructor(site) - { - super(site, "userManagement/html/fragments/passwordSettings.html", "online"); - } - onFirstStart() { - let res = super.onFirstStart(); - let form = new Form(document.getElementById("change-password-form"), "u/passwordSettings/set", "post"); - form.onSubmit(function(res){ - for (let i = 0, n = res.length; i < n; i++) - { - FlashMessenger.addMessage(res[i]); - } - form.setValues({ - "oldPassword":"", - "newPassword1":"", - "newPassword2":"" - }); - }); - return res; - } -} -InitPromise.addPromise(function(){ - SettingsSite.addSettingsFragment("password-settings", PasswordSettingsFragment); -}); - -class UserSettingsFragment extends UserFragment{ - constructor(site) - { - super(site, "userManagement/html/fragments/userSettings.html", "online"); - } - - onFirstStart() { - let res = super.onFirstStart(); - (new Form(document.getElementById("user-settings-form"), "u/userSettings/set", "post")).load('u/userSettings').onSubmit(function(res){ - for (let i = 0, n = res.length; i < n; i++) - { - FlashMessenger.addMessage(res[i]); - } - }); - return res; - } -} -InitPromise.addPromise(function(){ - SettingsSite.addSettingsFragment("user-settings", UserSettingsFragment); -}); - -class EditUserRolesSite extends UserSite { - constructor(siteManager) { - super(siteManager, 'userManagement/html/editUserRoles.html', "userRoles", "admin"); - } - - onConstruct(args) { - let res = super.onConstruct(args); - this.userId = args["id"]; - - let self = this; - return Promise.all([ - ScriptLoader.loadScript(Constants.SCRIPTS.LIST_JS), - DataManager.load("u/userRoles" + DataManager.buildQuery({"id": self.userId})).then(function (res) { - if (!res["success"]) { - FlashMessenger.addMessage(res["errors"][0]); - self.finish(); - } - else { - self.setUserRoles(res["result"]["userRoles"]); - self.setAvailableRoles(res["result"]["availableRoles"]); - self.setUsername(res["result"]["username"]); - } - }) - ]).then(function () { - return res; - }); - } - - onFirstStart() { - this.findBy("#username").innerHTML = this.username; - - const userRolesElement = this.findBy("#userRoles"); - const availableRolesElement = this.findBy("#availableRoles"); - - const imgColumnUserRoles = new ImgConstSmartColumn("img/minus.png", "", false); - const imgColumnAvailableRoles = new ImgConstSmartColumn("img/plus.png", "", false); - - const userRolesColumns = [ - new DataSmartColumn("id"), - new SmartColumn("name", "name"), - new SmartColumn("description", "description"), - imgColumnUserRoles, - ]; - - const availableRolesColumns = [ - new DataSmartColumn("id"), - new SmartColumn("name", "name"), - new SmartColumn("description", "description"), - imgColumnAvailableRoles, - ]; - - const userRolesListHelper = new ListHelper(userRolesElement, userRolesColumns, this.userRoles); - const availableRolesListHelper = new ListHelper(availableRolesElement, availableRolesColumns, this.availableRoles); - - const userRolesTable = userRolesListHelper.createTable(); - const availableRolesTable = availableRolesListHelper.createTable(); - - let self = this; - const changeRoleFunction = function (roleId, addRole) { - userRolesListHelper.setBusy(true); - availableRolesListHelper.setBusy(true); - - return DataManager.send("u/changeUserRole", { - "id": roleId, - "userId": self.userId, - "add": addRole - }).then(function (res) { - userRolesListHelper.setBusy(false); - availableRolesListHelper.setBusy(false); - - if (!res["success"]) { - FlashMessenger.addMessage(res["errors"][0]); - return res; - } - - let removingTable = null; - let addingTable = null; - if (res["result"]["hasRole"]) { - removingTable = availableRolesTable; - addingTable = userRolesTable; - } - else { - addingTable = availableRolesTable; - removingTable = userRolesTable; - } - - const rowData = removingTable.get("id", roleId); - if (rowData.length === 1) { - addingTable.add(rowData[0].values()); - removingTable.remove("id", roleId); - } - - return res; - }); - }; - - imgColumnUserRoles.setClickListener(function (cell) { - let userRoleId = cell.closest("tr")["dataset"]["id"]; - changeRoleFunction(userRoleId, false); - }); - - imgColumnAvailableRoles.setClickListener(function (cell) { - let availableRoleId = cell.closest("tr")["dataset"]["id"]; - changeRoleFunction(availableRoleId, true); - }); - - } - - setUserRoles(userRoles) { - this.userRoles = userRoles; - } - - setAvailableRoles(availableRoles) { - this.availableRoles = availableRoles; - } - - setUsername(username) { - this.username = username; - } -} - -InitPromise.addPromise(function (app) { - app.addDeepLink("userRoles", EditUserRolesSite); - app.addDefaultAction(new UserAction('userRoles', function(){ - app.startSite(EditUserRolesSite); - }, null, 1100, "admin")); -}); - -class ForgotPasswordSite extends UserSite{ - - constructor(siteManager) { - super(siteManager, 'userManagement/html/forgotPassword.html', "forgotPassword", "offline"); - } - - onFirstStart() { - let self = this; - (new Form(document.getElementById("forgot-password-form"), "u/newPassword", "post")).onSubmit(function(res){ - // UserManager.setData(res); - // self.startStartsite(); - FlashMessenger.addMessage(FlashMessenger.MESSAGE_TYPE_SUCCESS, Translator.translate("new-password-code-send")); - self.finish(); - }); - } -} -InitPromise.addPromise(function(app){ - app.addDeepLink("forgotPassword", ForgotPasswordSite); -}); - -class LoginSite extends UserSite { - constructor(siteManager) { - super(siteManager, 'userManagement/html/login.html', "login", "offline"); - } - - onFirstStart() { - let self = this; - (new LoginForm(document.getElementById("login-form"), "u/login", "post")).onSubmit(function (res) { - UserManager.setData(res); - self.startStartsite(); - FlashMessenger.addMessage(FlashMessenger.MESSAGE_TYPE_SUCCESS, Translator.translate("login-success")); - self.finish(); - }); - - this.findBy("#forgot-password-link").addEventListener("click", function () { - self.startSite(ForgotPasswordSite); - self.finish(); - }); - } -} - -LoginSite.loginAction = null; -LoginSite.logoutAction = null; -LoginSite.addLoginAction = true; -LoginSite.addLogoutAction = true; - -InitPromise.addPromise(function (app) { - app.addDeepLink("login", LoginSite); - - if (Helper.isNull(LoginSite.loginAction)) { - LoginSite.loginAction = new UserAction('login', function () { - app.startSite(LoginSite); - }, Menu.SHOW_NEVER, 1100, "offline"); - } - if (Helper.isNull(LoginSite.logoutAction)) { - LoginSite.logoutAction = new UserAction('logout', function () { - UserManager.logOut(); - }, Menu.SHOW_NEVER, 1100, "online"); - } - if (LoginSite.addLoginAction){ - app.addDefaultAction(LoginSite.loginAction); - } - if (LoginSite.addLogoutAction){ - app.addDefaultAction(LoginSite.logoutAction); - } -}); - -class RegistrationSite extends UserSite { - constructor(siteManager) { - super(siteManager, 'userManagement/html/registration.html', "registration", "offline"); - } - - onFirstStart() { - (new RegistrationForm(document.getElementById("registration-form"), "u/registration", "post")).onSubmit(function (res) { - FlashMessenger.addMessage(FlashMessenger.MESSAGE_TYPE_SUCCESS, Translator.translate("registration-success")); - }); - } -} - -RegistrationSite.action = null; -RegistrationSite.addAction = true; - -InitPromise.addPromise(function (app) { - app.addDeepLink("registration", RegistrationSite); - - if (Helper.isNull(RegistrationSite.action)) { - RegistrationSite.action = new UserAction('registration', function () { - app.startSite(RegistrationSite); - }, null, 1100, "offline"); - } - if (RegistrationSite.addAction) { - app.addDefaultAction(RegistrationSite.action); - } -}); - -class SetNewPasswordSite extends UserSite { - constructor(siteManager) { - super(siteManager, 'userManagement/html/setNewPassword.html', "newPassword", "offline"); - } - - onConstruct(args) { - this.code = args["code"]; - return super.onConstruct(args); - } - - onFirstStart() { - let formElem = document.getElementById("new-password-form"); - document.getElementById("code").value = this.code; - - let self = this; - (new Form(formElem, "c/code", "post")).onSubmit(function(res){ - FlashMessenger.addMessage(FlashMessenger.MESSAGE_TYPE_SUCCESS, Translator.translate("password-updated")); - self.startSite(LoginSite); - self.finish(); - }); - } -} -InitPromise.addPromise(function(app){ - app.addDeepLink("newPassword", SetNewPasswordSite); -}); - -class MyStorageManager { - static getInstance() { - if (Helper.isNull(MyStorageManager.instance)) { - MyStorageManager.instance = new MyStorageManager(); - } - return MyStorageManager.instance; - } - - async estimate() { - if ('storage' in navigator && 'estimate' in navigator["storage"]) { - // We've got the real thing! Return its response. - return navigator["storage"]["estimate"](); - } - - if ('webkitTemporaryStorage' in navigator && - 'queryUsageAndQuota' in navigator["webkitTemporaryStorage"]) { - // Return a promise-based wrapper that will follow the expected interface. - return new Promise(function (resolve, reject) { - navigator["webkitTemporaryStorage"]["queryUsageAndQuota"]( - function (usage, quota) { - resolve({"usage": usage, "quota": quota}); - }, - ); - }); - } - // If we can't estimate the values, return a Promise that resolves with NaN. - return Promise.resolve({"usage": NaN, "quota": NaN}); - } - - async isPersistent(){ - if (this.canPersist()){ - return navigator["storage"]["persisted"](); - } - return Promise.resolve(false); - } - - canEstimateStorage() { - return ('storage' in navigator && 'estimate' in navigator["storage"]|| 'webkitTemporaryStorage' in navigator && - 'queryUsageAndQuota' in navigator["webkitTemporaryStorage"]); - } - - canPersist() { - return (navigator["storage"] && navigator["storage"]["persist"]); - } - - persist(){ - if (this.canPersist()){ - return navigator["storage"]["persist"](); - } - return Promise.resolve(false); - } -} - -MyStorageManager.instance = null; - -class InstallManager { - static init() { - window.addEventListener('beforeinstallprompt', e => { - e.preventDefault(); - this.setDeferredPrompt(e); - }); - } - - static setDeferredPrompt(e){ - this.deferredPromt = e; - if (this.canInstallListener) { - this.canInstallListener(this.deferredPromt); - } - } - - static async prompt(){ - if (Helper.isNotNull(this.deferredPromt)){ - this.deferredPromt["prompt"](); - return this.deferredPromt["userChoice"].then(r => { - MyStorageManager.getInstance().persist(); - return r; - }); - } - return Promise.resolve({ - "outcome":"dismissed", - "platform":"" - }); - } - - static isInstalled(){ - return matchMedia("(display-mode: standalone)").matches; - } - - static setCanInstallListener(listener, callIfCanInstall) { - this.canInstallListener = listener; - callIfCanInstall = Helper.nonNull(callIfCanInstall, true); - - if (callIfCanInstall && Helper.nonNull(this.deferredPromt)) { - this.canInstallListener(this.deferredPromt); - } - } -} - -InstallManager.init(); - -class Matomo { - - static init() { - Matomo.isTrackingPromise = new Promise(async (resolve) => { - let shouldTrack = Helper.nonNull(localStorage.getItem(Matomo.LOCAL_STORAGE_KEY), "1"); - if (Helper.isNull(shouldTrack)) { - shouldTrack = await Matomo._askIsTracking(); - localStorage.setItem(Matomo.LOCAL_STORAGE_KEY, shouldTrack); - } - else { - shouldTrack = (shouldTrack === "1"); - Matomo.setTrack(shouldTrack); - } - resolve(shouldTrack); - }); - Matomo.isTrackingPromise.then(() => { - Matomo.push(['trackPageView'], true); - Matomo.push(['enableLinkTracking'], true); - Matomo.push(['setTrackerUrl', Matomo.TRACK_SITE + '/piwik.php'], true); - Matomo.push(['setSiteId', Matomo.SIDE_ID + ""], true); - - let d = document, g = d.createElement('script'), s = d.getElementsByTagName('head')[0]; - g.type = 'text/javascript'; - g.async = true; - g.defer = true; - g.src = Matomo.TRACK_SITE + '/piwik.js'; - s.appendChild(g); - }); - } - - static update(title) { - if (Helper.nonNull(Matomo.currentUrl)) { - Matomo.push(['setReferrerUrl', Matomo.currentUrl]); - } - Matomo.currentUrl = window.location.pathname + window.location.search; - Matomo.push(['setCustomUrl', Matomo.currentUrl]); - Matomo.push(['setDocumentTitle', title]); - - // remove all previously assigned custom variables, requires Matomo (formerly Piwik) 3.0.2 - Matomo.push(['deleteCustomVariables', 'page']); - Matomo.push(['setGenerationTimeMs', 0]); - Matomo.push(['trackPageView']); - - // make Matomo aware of newly added content - var content = document.getElementById('site-content'); - Matomo.push(['MediaAnalytics::scanForMedia', content]); - Matomo.push(['FormAnalytics::scanForForms', content]); - Matomo.push(['trackContentImpressionsWithinNode', content]); - Matomo.push(['enableLinkTracking']); - } - - static async _askIsTracking() { - Matomo.isTrackingPromise = new Promise(resolve => { - Matomo.push([function () { - resolve(!this["isUserOptedOut"]()); - }]); - Matomo.push([function () { - resolve(!this["isUserOptedOut"]()); - }]); - }); - return Matomo.isTrackingPromise; - } - - static async query(method) { - return fetch(Matomo.TRACK_SITE + Matomo.BASE_PATH + method, { - "mode": "cors", - "credentials": "include", - }).then(res => res.text()).then(text => (new window.DOMParser()).parseFromString(text, "text/xml")); - } - - static getTrackingPromise() { - return Matomo.isTrackingPromise; - } - - static async setTrack(shouldTrack) { - Matomo.isTrackingPromise = Promise.resolve(shouldTrack); - localStorage.setItem(Matomo.LOCAL_STORAGE_KEY, (shouldTrack === true) ? "1" : "0"); - - if (shouldTrack) { - Matomo.push(["forgetUserOptOut"], true); - } - else { - Matomo.push(["optUserOut"], true); - } - } - - static async trackEvent(event, name, label, value){ - let ev = ["trackEvent", event, name]; - if (Helper.isNotNull(label)){ - ev.push(label); - } - if (Helper.isNotNull(value) && !isNaN(parseFloat(value)) && isFinite(value)){ - ev.push(value); - } - - return this.push(ev); - } - - static async push(arr, force) { - - if (!Array.isArray(arr)) { - arr = [arr]; - } - window["_paq"].push(arr); - } -} - -Matomo.currentUrl = null; - -Matomo.LOCAL_STORAGE_KEY = "matomoShouldTrack"; -Matomo.TRACK_SITE = "//matomo.silas.link"; -Matomo.BASE_PATH = "/index.php?module=API&method=AjaxOptOut."; -Matomo.SIDE_ID = "1"; - -InitPromise.addPromise(() => { - window["_paq"] = window["_paq"] || []; - Matomo.init(); -}); - -class MatomoShareButton extends MultipleShareButton{ - - constructor(baseButton, platform, shouldLoadImg) { - super([baseButton, (url) => { - Matomo.trackEvent("shared", url, platform); - }], shouldLoadImg); - } -} - -AndroidBridge.addDefinition("MatomoShareButton", MatomoShareButton); - -class ScaleHelper { - async scaleTo(scale, fontElement, container, ignoreHeight, ignoreWidth, margin, fontWeight, animationDelay, addListener) { - - addListener = Helper.nonNull(addListener, true); - animationDelay = Helper.nonNull(animationDelay, 0); - - let newFontSize = await this._getNewFontSize(scale, fontElement, container, ignoreHeight, ignoreWidth, margin, fontWeight, animationDelay === 0); - - if (animationDelay > 0) { - await new Promise(r => { - setTimeout(r, animationDelay); - fontElement.style.fontSize = newFontSize + "px"; - }); - } - - let self = this; - let listener = function () { - return new Promise(resolve => { - let timeout = (typeof addListener === 'number') ? addListener : 255; - setTimeout(() => { - resolve(self.scaleTo(scale, fontElement, container, ignoreHeight, ignoreWidth, margin, fontWeight, animationDelay, false)); - }, timeout); - }); - }; - if (addListener !== false) { - window.addEventListener("resize", listener); - } - return listener; - } - - async scaleToFull(fontElement, container, ignoreHeight, ignoreWidth, margin, fontWeight, animDelay, addListener) { - return this.scaleTo(1, fontElement, container, ignoreHeight, ignoreWidth, margin, fontWeight, animDelay, addListener); - } - - async _getNewFontSize(scale, fontElement, container, ignoreHeight, ignoreWidth, margin, fontWeight, setFontSize) { - margin = Helper.nonNull(margin, 10); - ignoreHeight = Helper.nonNull(ignoreHeight, false); - ignoreWidth = Helper.nonNull(ignoreWidth, false); - fontWeight = Helper.nonNull(fontWeight, fontElement.innerHTML.length); - setFontSize = Helper.nonNull(setFontSize, true); - - let hasNoTransitionClass = container.classList.contains("no-transition"); - - if (!hasNoTransitionClass) { - container.classList.add("no-transition"); - } - - const numChanged = 5; - let oldDiffIndex = 0; - let oldDiff = []; - - for (let i = 0; i < numChanged; i++) { - oldDiff.push(0); - } - - let beforeFontSize = fontElement.style.fontSize; - let currentFontSize = 1; - let widthDiff = 0; - let heightDiff = 0; - let containerWidth = 0; - let containerHeight = 0; - do { - currentFontSize += oldDiff[oldDiffIndex] / (fontWeight + 1); - fontElement.style.fontSize = currentFontSize + 'px'; - - let containerStyle = window.getComputedStyle(container); - - containerWidth = containerStyle.getPropertyValue("width").replace('px', ''); - containerHeight = containerStyle.getPropertyValue("height").replace('px', ''); - - widthDiff = containerWidth - fontElement.offsetWidth; - heightDiff = containerHeight - fontElement.offsetHeight; - - oldDiffIndex = (oldDiffIndex+1)%numChanged; - let newDiff = (ignoreWidth ? heightDiff : (ignoreHeight ? widthDiff : Math.min(widthDiff, heightDiff))); - if (newDiff === oldDiff[(oldDiffIndex+1)%numChanged]) { - break; - } - oldDiff[oldDiffIndex] = newDiff; - } while ((widthDiff > (1 - scale) * containerWidth || ignoreWidth) && (heightDiff > (1 - scale) * containerHeight || ignoreHeight)); - - currentFontSize -= margin; - fontElement.style.fontSize = ((setFontSize) ? currentFontSize + "px" : beforeFontSize); - - if (!hasNoTransitionClass) { - await new Promise((r) => { - setTimeout(r, 50); - }); - container.classList.remove("no-transition"); - } - - return currentFontSize; - } -} - -class AudioChain { - - constructor(context, sourceBuffer, chainFunction) { - this.buffer = sourceBuffer; - this.shouldLoop = false; - this.loopStart = null; - this.loopEnd = null; - this.chainFunction = chainFunction; - this.context = context; - - this.startTime = null; - this.pauseTime = null; - this.source = null; - - this.running = false; - } - - setBuffer(buffer) { - this.buffer = buffer; - } - - setLooping(shouldLoop, loopStart, loopEnd) { - this.shouldLoop = shouldLoop; - - if (Helper.isNotNull(loopStart)) { - this.loopStart = loopStart; - } - if (Helper.isNotNull(loopEnd)) { - this.loopEnd = loopEnd; - } - } - - async start(delay, offset, duration) { - //sind sonst null, schmeißt in Android 5 einen fehler - delay = Helper.nonNull(delay, 0); - offset = Helper.nonNull(offset, 0); - //Duration darf nicht gesetzt werden - // duration = Helper.nonNull(duration, -1); - - let source = this.context.createBufferSource(); - - source.loop = this.shouldLoop; - if (Helper.isNotNull(this.loopStart)) { - source.loopStart = this.loopStart; - } - if (Helper.isNotNull(this.loopEnd)) { - source.loopEnd = this.loopEnd; - } - source.buffer = this.buffer; - await this.chainFunction(source); - - if (Helper.isNull(duration)){ - source.start(delay, offset); - } - else{ - source.start(delay, offset, duration); - } - this.startTime = (new Date()).getTime() - (Helper.nonNull(offset, 0) * 1000); - this.source = source; - this.running = true; - } - - async stop(delay) { - if (Helper.isNotNull(this.source)) { - delay = Helper.nonNull(delay, 0); - - this.pauseTime = ((new Date()).getTime()) - this.startTime; - this.running = false; - return this.source.stop(delay); - } - return null; - } - - async resume() { - - if (!this.running) { - return this.start(null, Helper.nonNull(this.pauseTime, 0) / 1000.0); - } - } -} - -class SoundManager { - static getInstance() { - if (Helper.isNull(SoundManager.instance)) { - SoundManager.instance = new SoundManager(); - } - return SoundManager.instance; - } - - constructor() { - this.channels = {}; - this.context = new AudioContext(); - this.context.onstatechange = function () { - console.log("stateChange from context", arguments); - }; - this.context.oncomplete = function () { - console.log("onComplete from context", arguments); - }; - - window.addEventListener("visibilitychange", () => { - this.handleVisibilityChange(); - }); - } - - isNotSuspended(){ - // return false; - return this.context.state !== "suspended"; - } - - set(options, channel) { - channel = Helper.nonNull(channel, SoundManager.CHANNELS.DEFAULT); - let audioObject = Helper.nonNull(this.channels[channel], {}); - - if (typeof options === "string") { - options = {audio: options}; - } - - let audio = options.audio; - if (Helper.isNotNull(audio)) { - audioObject.loadedPromise = fetch(audio).then(res => res.arrayBuffer()).then(arrayBuffer => { - return new Promise((r) => this.context.decodeAudioData(arrayBuffer, r)); - }).catch(e => console.error(e)); - this.stop(channel); - } - audioObject.muted = Helper.nonNull(options.muted, audioObject.muted, false); - audioObject.volume = Helper.nonNull(options.volume, audioObject.volume, 1); - audioObject.loop = Helper.nonNull(options.loop, audioObject.loop, false); - audioObject.timeOffset = Helper.nonNull(options.timeOffset, audioObject.timeOffset, 0); - this.channels[channel] = audioObject; - - if (audioObject.muted) { - this.stop(channel); - } - - return this.channels[channel]; - } - - async resumeContext(){ - if (typeof this.context.resume === "function") { - return this.context.resume(); - } - } - - async play(channel, audioOrOptions) { - this.resumeContext(); - channel = Helper.nonNull(channel, SoundManager.CHANNELS.DEFAULT); - if (Helper.isNull(audioOrOptions)) { - audioOrOptions = {}; - } else if (!(typeof audioOrOptions === "object")) { - audioOrOptions = { - audio: audioOrOptions - }; - } - audioOrOptions.timeOffset = Helper.nonNull(audioOrOptions.timeOffset, 0); - - this.stop(channel); - this.set(audioOrOptions, channel); - - if (!this.channels[channel].muted) { - let buffer = await this.channels[channel].loadedPromise; - let source = new AudioChain(this.context, buffer, (sourceNode) => { - let gain = this.context.createGain(); - gain.gain.value = this.channels[channel].volume; - - sourceNode.connect(gain); - gain.connect(this.context.destination); - }); - - source.setBuffer(buffer); - - //to prevent gap in mp3-files - source.setLooping(this.channels[channel].loop, 0.3, buffer.duration - 0.3); - - this.channels[channel].source = source; - await source.start(); - } - return this.channels[channel]; - } - - stop(channel) { - channel = Helper.nonNull(channel, SoundManager.CHANNELS.DEFAULT); - - - let oldAudio = this.channels[channel]; - if (Helper.isNotNull(oldAudio) && Helper.isNotNull(oldAudio.source)) { - oldAudio.source.stop(); - } - } - - get(channel) { - channel = Helper.nonNull(channel, SoundManager.CHANNELS.DEFAULT); - return this.channels[channel]; - } - - async resume(channel) { - channel = Helper.nonNull(channel, SoundManager.CHANNELS.DEFAULT); - if (Helper.isNotNull(this.channels[channel]) && !this.channels[channel].muted && Helper.isNotNull(this.channels[channel].source)) { - return this.channels[channel].source.resume(); - } - } - - stopAll(){ - for (let k in this.channels) { - if (Helper.isNotNull(this.channels[k].source)) { - this.channels[k].source.stop(); - } - } - } - - resumeAllIfNotMuted(){ - for (let k in this.channels) { - if (Helper.isNotNull(this.channels[k]) && !this.channels[k].muted && Helper.isNotNull(this.channels[k].source)) { - this.channels[k].source.resume(); - } - } - } - - handleVisibilityChange() { - if (document.hidden) { - this.stopAll(); - } - else { - this.resumeAllIfNotMuted(); - } - } -} - -SoundManager.CHANNELS = { - MUSIC: "music", - SOUND: "sound", - DEFAULT: "default" -}; - -InitPromise.addPromise(() => { - PauseSite.onPauseListeners.push(() => { - SoundManager.getInstance().stopAll(); - }); - PauseSite.onStartListeners.push(() => { - SoundManager.getInstance().resumeAllIfNotMuted(); - }); -}); - -class Code { - constructor(args) { - if (typeof args === "string") { - args = { - "code": args - }; - } - this.args = args; - this.isCacheable = false; - } - - setIsCacheable(isCacheable) { - this.isCacheable = isCacheable; - } - - getIsCacheable() { - return this.isCacheable; - } - - activate() { - return DataManager.send("c/code", this.args); - } -} - -class CodeSite extends AbstractSite { - constructor(siteManager) { - super(siteManager, "core/html/load.html", "code"); - } - - onConstruct(args) { - super.onConstruct(args); - console.log(args); - - let resPromise = Promise.resolve(); - if (Helper.isNotNull(args["code"])) { - let code = args["code"]; - let isCachable = Helper.nonNull(args["cachable"], false); - - let codeObject = new Code(code); - codeObject.setIsCacheable(isCachable); - - let self = this; - resPromise = codeObject.activate().then(function (res) { - if (!res["success"]) { - FlashMessenger.addMessage(FlashMessenger.MESSAGE_TYPE_SUCCESS, Translator.translate(res["errors"][0])); - } - else { - FlashMessenger.addMessage(FlashMessenger.MESSAGE_TYPE_SUCCESS, Translator.translate(Helper.nonNull(res["result"]["successMessage"], "code-activated"))); - } - self.finish(); - }); - } - } -} - -InitPromise.addPromise(function (app) { - app.addDeepLink("code", CodeSite); -}); - -class ContactSite extends AbstractSite{ - constructor(siteManager) { - super(siteManager, 'contact/html/contact.html', ContactSite.DEEP_LINK); - } - - onFirstStart() { - new Form(this.findBy("#contact-form"), "contact", "post").onSubmit((d) => { - FlashMessenger.addMessage("contact-message-sent"); - this.finish(); - }); - - super.onFirstStart(); - } -} -ContactSite.DEEP_LINK = "contactMe"; - -InitPromise.addPromise((app) => { - if (ContactSite.DEEP_LINK){ - app.addDeepLink(ContactSite.DEEP_LINK, ContactSite); - } -}); - -class WordRotatorBaseSite extends AbstractSite { - // createActionBarMenu(menu) { - // menu = super.createActionBarMenu(menu); - // // menu.addAction(SettingsSite.settingsAction.copy()); - // // let actions = menu.actions; - // // for (let i = 0; i < actions.length; i++) { - // // if (actions[i].title === "login" || actions[i].title === "registration"){ - // // actions[i].setVisible(false); - // // } - // // } - // return menu; - // } -} - -class TemplateContainer{ - constructor(leafTemplate, parentTemplate, rowTemplate, triangleTemplate, columnTemplate){ - this.leafTemplate = leafTemplate; - this.parentTemplate = parentTemplate; - this.rowTemplate = rowTemplate; - this.triangleTemplate = triangleTemplate; - this.columnTemplate = columnTemplate; - } - - copyLeafTemplate() - { - return Helper.cloneNode(this.leafTemplate); - } - - copyParentTemplate() - { - return Helper.cloneNode(this.parentTemplate); - } - - copyRowTemplate() - { - return Helper.cloneNode(this.rowTemplate); - } - - copyTriangleTemplate() - { - return Helper.cloneNode(this.triangleTemplate); - } - - copyColumnTemplate(){ - return Helper.cloneNode(this.columnTemplate); - } -} - -class Segment{ - constructor(element){ - this.rotation = 0; - this.element = element; - this.parent = null; - } - - getCurrentRotations(rotations){ - return rotations; - } - - sameAs(otherSegment){ - return false; - } - - setParent(parent) - { - this.parent = parent; - } - - getLevel() - { - if (this.parent!==null) - { - return this.parent.getLevel(); - } - } - - canRotate(){ - return false; - } - - isSolved(){ - return (this.rotation === 0); - } - - async rotate(){ - return Promise.resolve(); - }; - - _updateElement(){}; - - applyRotations(rotations){ - return rotations; - } - - applyLocks(locks) - { - return locks; - } - - getCurrentLocked(lockedArray){ - return lockedArray; - } - - getElement() - { - return this.element; - } -} - -class LeafSegment extends Segment { - - constructor(element, leaf) { - super(element); - this.leaf = 'A'; - if (Helper.isNotNull(leaf)) { - this.setLeaf(leaf); - } - } - - sameAs(otherSegment) { - // debugger; - return (otherSegment instanceof LeafSegment && otherSegment.leaf === this.leaf); - } - - setLeaf(leaf) { - this.leaf = leaf; - } - - _updateElement() { - this.element.querySelector(".leaf-element").removeAllChildren().appendChild(document.createTextNode(this.leaf)); - } -} - -class ParentSegment extends Segment { - static initListener() { - window.addEventListener("mousedown", (e) => { - ParentSegment.mouseDownTarget = e.target; - ParentSegment.clickPosition = {x: e.pageX, y: e.pageY}; - }); - window.addEventListener("mouseup", (e) => { - ParentSegment.mouseDownTarget = null; - ParentSegment.clickPosition = {}; - }); - - window.addEventListener("touchstart", (e) => { - if (e.targetTouches.length === 1) { - ParentSegment.mouseDownTarget = e.targetTouches[0].target; - ParentSegment.clickPosition = {x: e.targetTouches[0].pageX, y: e.targetTouches[0].pageY}; - } - // else if (Array.isArray(e.path) && e.path.length >= 1) { - // ParentSegment.mouseDownTarget = e.path[0]; - // ParentSegment.clickPosition = null; - // } - }); - window.addEventListener("touchend", (e) => { - ParentSegment.mouseDownTarget = null; - ParentSegment.clickPosition = {}; - }); - } - - setIsRotatable(rotatable) { - this.rotatable = rotatable; - this._updateElement(); - } - - constructor(element) { - super(element); - this.children = []; - this.class = "rotate-0"; - this.rotatable = true; - - this.userRotationDelta = 100; - this.lastUserRotation = 0; - - let self = this; - this.touchendListener = function (e) { - let now = new Date().getTime(); - - // console.log("touchendListener", e,now, self.lastUserRotation); - let target = null; - let position = null; - - if (e.changedTouches.length >= 1) { - target = document.elementFromPoint(e.changedTouches[0].pageX, e.changedTouches[0].pageY); - position = {x: e.changedTouches[0].pageX, y: e.changedTouches[0].pageY}; - } - if (target != null && e.targetTouches.length === 0 && self.element.contains(ParentSegment.mouseDownTarget) && self.element.contains(target)) { - e.stopPropagation(); - e.preventDefault(); - if (self.lastUserRotation+self.userRotationDelta > now){ - return; - } - self.getLevel().segmentClickedListener(self); - self.rotate(ParentSegment.mouseDownTarget, target, ParentSegment.clickPosition, position); - // console.log("touchendListener stopped event", e); - - self.lastUserRotation = new Date().getTime(); - } - }; - this.mouseupListener = function (e) { - let now = new Date().getTime(); - // console.log("mouseupListener", e,now, self.lastUserRotation); - - if (ParentSegment.mouseDownTarget !== null && self.element.contains(ParentSegment.mouseDownTarget) && self.element.contains(e.target)) { - let position = {x: e.pageX, y: e.pageY}; - e.stopPropagation(); - e.preventDefault(); - if (self.lastUserRotation+self.userRotationDelta > now){ - return; - } - self.getLevel().segmentClickedListener(self); - self.rotate(ParentSegment.mouseDownTarget, e.target, ParentSegment.clickPosition, position); - // console.log("mouseupListener stopped event", e); - self.lastUserRotation = new Date().getTime(); - } - }; - } - - canRotate() { - return (this.rotatable && !this.getLevel().getHasWon()); - } - - async rotate(firstElem, secondElem, firstPosition, secondPosition) { - const timeout = 250; - const clickTolerance = 5; - - let rotationDirection = 1; - if (Helper.isNotNull(secondElem) && Helper.isNotNull(firstElem) && - (Helper.isNull(firstPosition) || Helper.isNull(secondPosition) || - Math.abs(firstPosition.x - secondPosition.x) > clickTolerance || - Math.abs(firstPosition.y - secondPosition.y) > clickTolerance)) { - - let firstIndex = -1; - let secondIndex = -1; - let rotationIndexes = [0, 1, 3, 2]; - for (let i = 0; i < this.children.length; i++) { - if (this.children[rotationIndexes[i]].element === firstElem || this.children[rotationIndexes[i]].element.contains(firstElem)) { - firstIndex = (i + this.rotation / 90) % 4; - } - if (this.children[rotationIndexes[i]].element === secondElem || this.children[rotationIndexes[i]].element.contains(secondElem)) { - secondIndex = (i + this.rotation / 90) % 4; - } - } - - if (firstIndex >= 0 && secondIndex >= 0) { - if (firstIndex === 2 && (secondIndex === 0 || secondIndex === 1) - || firstIndex === 1 && (secondIndex === 0 || secondIndex === 3) - || (firstIndex === 0 && secondIndex === 3) - || (firstIndex === 3 && secondIndex === 2)) { - rotationDirection = -1; - } - } - } - - if (this.canRotate()) { - this.rotation += 360 + 90 * rotationDirection; - this.rotation %= 360; - - let currentRotation = this.rotation; - - this._updateRotationClass(); - this.element.classList.add("rotating"); - if (rotationDirection === -1) { - this.element.classList.add("reverse"); - } - - let delayPromise = new Promise(function (resolve) { - setTimeout(resolve, timeout); - }).then(() => { - if (this.rotation === currentRotation) { - this.element.classList.remove("rotating"); - this.element.classList.remove("reverse"); - } - }); - this.getLevel().checkHasWon(delayPromise); - return delayPromise; - } - } - - sameAs(otherSegment) { - if (!(otherSegment instanceof ParentSegment) || otherSegment.children.length !== this.children.length) { - return false; - } - for (let i = 0; i < this.children.length; i++) { - if (!this.children[i].sameAs(otherSegment.children[i])) { - return false; - } - } - return true; - } - - applyRotations(rotations) { - this.rotation = rotations[0]; - - if (isNaN(this.rotation)) { - this.rotation = 0; - } - - rotations.splice(0, 1); - for (let i = 0, n = this.children.length; i < n; i++) { - rotations = this.children[i].applyRotations(rotations); - } - return rotations; - } - - applyLocks(locks) { - this.rotatable = (locks[0] !== false); - locks.splice(0, 1); - for (let i = 0, n = this.children.length; i < n; i++) { - locks = this.children[i].applyLocks(locks); - } - return locks; - } - - getCurrentRotations(rotations) { - rotations.push(this.rotation); - for (let i = 0, n = this.children.length; i < n; i++) { - rotations = this.children[i].getCurrentRotations(rotations); - } - return rotations; - } - - getCurrentLocked(locked) { - locked.push(this.rotatable); - for (let i = 0, n = this.children.length; i < n; i++) { - locked = this.children[i].getCurrentLocked(locked); - } - return locked; - } - - isSolved(checkChildren) { - checkChildren = Helper.nonNull(checkChildren, true); - if (checkChildren) { - for (let i = 0, n = this.children.length; i < n; i++) { - if (!this.children[i].isSolved()) { - return false; - } - } - } - return (this.rotation === 0 || ( - this.children[0].sameAs(this.children[3]) && this.children[1].sameAs(this.children[2]) && ( - this.rotation === 180 || this.children[0].sameAs(this.children[1])))) - } - - setChildren(children) { - this.children = []; - for (let i = 0, n = children.length; i < n; i++) { - this.addChild(children[i]); - } - } - - addChild(child) { - this.children.push(child); - child.setParent(this); - this._updateElement(); - } - - _updateRotationClass() { - // this.style.transform = "rotate("+this.rotation+"deg)"; - this.element.classList.remove(this.class); - this.class = "rotate-" + this.rotation; - if (this.class === "rotate-0") { - this.class = "rotate-360"; - } - this.element.classList.add(this.class); - } - - _updateElement() { - let layer = this._getLayer(); - if (layer >= 2) { - this.element.classList.add("layer-" + layer); - } - - if (!this.rotatable) { - this.element.classList.add("locked"); - } - - const childContainer = this.element.querySelector(".child-container"); - childContainer.removeAllChildren(); - - this._updateRotationClass(); - - this.element.removeEventListener("mouseup", this.mouseupListener); - this.element.removeEventListener("touchend", this.touchendListener); - - this.element.addEventListener("mouseup", this.mouseupListener); - this.element.addEventListener("touchend", this.touchendListener); - - for (let i = 0, n = this.children.length; i < n; i++) { - this.children[i]._updateElement(); - childContainer.appendChild(this.children[i].getElement()); - if (i % 2 === 1 && this.children.length - 1 !== i) { - childContainer.appendChild(document.createElement("br")); - } - } - } - - _getLayer() { - if (this.children.length >= 1 && this.children[0] && this.children[0] instanceof ParentSegment) { - return this.children[0]._getLayer() + 1; - } - return 1; - } -} - -ParentSegment.initListener(); - -class Level { - constructor(templateContainer) { - this.rootSegment = null; - this.words = []; - this.startRotations = []; - this.templateContainer = templateContainer; - - this.hasWon = false; - this.id = null; - - this.wonResolver = null; - this.giveUpResolver = null; - - const self = this; - this.wonPromise = new Promise((resolve, reject) => { - self.wonResolver = resolve; - self.giveUpResolver = reject; - }); - - this.segmentClickedListener = () => {}; - } - - saveAsCurrentLevel(){ - let rotations = this.getCurrentRotations(); - let locked = this.getCurrentLocked(); - localStorage.setItem("currentLevel", JSON.stringify({"id": this.id, "rotations": rotations, "locks":locked})); - } - - getCurrentLocked(){ - if (this.rootSegment !== null) - { - return this.rootSegment.getCurrentLocked([]); - } - return []; - } - - getCurrentRotations(){ - if (this.rootSegment !== null) - { - return this.rootSegment.getCurrentRotations([]); - } - return []; - } - - setLocks(locks) - { - if (this.rootSegment !== null){ - this.rootSegment.applyLocks(locks); - } - } - - setId(id) - { - this.id = id; - } - - getId() - { - return this.id; - } - - getLevel() - { - return this; - } - - setRootSegment(rootSegment) - { - this.rootSegment = rootSegment; - this.rootSegment.setParent(this); - if (this.startRotations) - { - this.applyRotations(); - } - } - - setWords(words) - { - this.words = []; - for (let i = 0, n = words.length; i < n; i++) { - this.words.push(words[i].toUpperCase()); - } - } - - setStartRotations(rotations) - { - this.startRotations = rotations; - } - - applyRotations(rotations) - { - if (this.rootSegment) - { - rotations = Helper.nonNull(rotations, this.startRotations); - this.rootSegment.applyRotations(rotations); - } - } - - getHasWon() - { - return this.hasWon; - } - - checkHasWon(delayPromise) { - if (this.rootSegment.isSolved()){ - this.hasWon = true; - const self = this; - Promise.resolve(delayPromise).then(()=>{ - self.wonResolver(true); - }); - return true; - } - this.saveAsCurrentLevel(); - return false; - } - - getWonPromise(){ - return this.wonPromise; - } - - getRootSegment(){ - return this.rootSegment; - } - - createSegments() {}; - - getRotatableSegments(){ - return Level._getRotatableSegmentsFrom(this.rootSegment); - } - - setSegmentClickedListener(listener){ - this.segmentClickedListener = listener; - } - - static _getRotatableSegmentsFrom(segment){ - let rotatable = []; - if (segment.canRotate()) - { - rotatable.push(segment); - } - if (segment instanceof ParentSegment){ - for (let i = 0; i < segment.children.length; i++) { - rotatable.push.apply(rotatable, Level._getRotatableSegmentsFrom(segment.children[i])); - } - } - return rotatable; - } - - static _createLeafsForWord(word, leafSegmentTemplate) - { - let leafSegments = []; - for (let i = 0, n = word.length; i < n; i++) { - leafSegments.push(new LeafSegment(Helper.cloneNode(leafSegmentTemplate), word.charAt(i))); - } - return leafSegments; - } -} - -class RowSegment extends ParentSegment{ - constructor(element) { - super(element); - this.rotatable = false; - } - - applyRotations(rotations) - { - for (let i = 0, n = this.children.length; i < n; i++) { - rotations = this.children[i].applyRotations(rotations); - } - return rotations; - } - - getCurrentRotations(rotations){ - for (let i = 0, n = this.children.length; i < n; i++) { - rotations = this.children[i].getCurrentRotations(rotations); - } - return rotations; - } - - getCurrentLocked(locked) { - for (let i = 0, n = this.children.length; i < n; i++) { - locked = this.children[i].getCurrentLocked(locked); - } - return locked; - } - - applyLocks(locks) { - for (let i = 0, n = this.children.length; i < n; i++) { - locks = this.children[i].applyLocks(locks); - } - return locks; - } - - _updateElement() { - const childContainer = this.element.querySelector(".child-container"); - childContainer.removeAllChildren(); - - this._updateRotationClass(); - - const self = this; - this.element.onclick = function (e) { - self.rotate(); - e.stopPropagation(); - }; - - for (let i = 0, n = this.children.length; i < n; i++) { - this.children[i]._updateElement(); - childContainer.appendChild(this.children[i].getElement()); - } - } -} - -class RowLevel extends Level { - constructor(container, wordLength) { - super(container); - this.wordLength = wordLength; - } - - createSegments() { - if (this.words.length >= 2 && this.words[0].length >= this.wordLength && this.words[1].length >= this.wordLength) { - let leafsWordOne = Level._createLeafsForWord(this.words[0], this.templateContainer.copyLeafTemplate()); - let leafsWordTwo = Level._createLeafsForWord(this.words[1], this.templateContainer.copyLeafTemplate()); - - let rootSegment = new RowSegment(this.templateContainer.copyRowTemplate()); - for (let i = 0, n = this.wordLength / 2; i < n; i++) { - let parent = new ParentSegment(this.templateContainer.copyParentTemplate()); - parent.addChild(leafsWordOne[2 * i]); - parent.addChild(leafsWordOne[2 * i + 1]); - parent.addChild(leafsWordTwo[2 * i]); - parent.addChild(leafsWordTwo[2 * i + 1]); - rootSegment.addChild(parent); - } - // rootSegment.applyRotations(this.startRotations); - this.setRootSegment(rootSegment); - } - } -} - -class SimpleLevel extends RowLevel{ - constructor(container) { - super(container, 6); - } -} - -class RowLevel8 extends RowLevel{ - constructor(container) { - super(container, 8); - } -} - -class RowLevel10 extends RowLevel{ - constructor(container) { - super(container, 10); - } -} - -class TriangleSegment extends RowSegment{ - -} - -class SixWordsRowLevel extends Level { - - constructor(templateContainer, wordLength) { - super(templateContainer); - this.wordLength = wordLength; - } - - createSegments() { - if (this.words.length >= 6 && - this.words[0].length >= this.wordLength && - this.words[1].length >= this.wordLength && - this.words[2].length >= this.wordLength && - this.words[3].length >= this.wordLength && - this.words[4].length >= this.wordLength && - this.words[5].length >= this.wordLength - ) { - let leafsWords = []; - leafsWords[0] = Level._createLeafsForWord(this.words[0], this.templateContainer.copyLeafTemplate()); - leafsWords[1] = Level._createLeafsForWord(this.words[1], this.templateContainer.copyLeafTemplate()); - leafsWords[2] = Level._createLeafsForWord(this.words[2], this.templateContainer.copyLeafTemplate()); - leafsWords[3] = Level._createLeafsForWord(this.words[3], this.templateContainer.copyLeafTemplate()); - leafsWords[4] = Level._createLeafsForWord(this.words[4], this.templateContainer.copyLeafTemplate()); - leafsWords[5] = Level._createLeafsForWord(this.words[5], this.templateContainer.copyLeafTemplate()); - - let rootSegment = new RowSegment(this.templateContainer.copyRowTemplate()); - for (let i = 0; i < this.wordLength / 4; i++) { - - let parents = []; - parents[0] = new ParentSegment(this.templateContainer.copyParentTemplate()); - parents[1] = new ParentSegment(this.templateContainer.copyParentTemplate()); - parents[2] = new ParentSegment(this.templateContainer.copyParentTemplate()); - parents[3] = new ParentSegment(this.templateContainer.copyParentTemplate()); - parents[4] = new ParentSegment(this.templateContainer.copyParentTemplate()); - parents[5] = new ParentSegment(this.templateContainer.copyParentTemplate()); - - parents[0].addChild(leafsWords[0][4*i]); - parents[0].addChild(leafsWords[0][4*i+1]); - parents[0].addChild(leafsWords[1][4*i]); - parents[0].addChild(leafsWords[1][4*i+1]); - - parents[1].addChild(leafsWords[0][4*i+2]); - parents[1].addChild(leafsWords[0][4*i+3]); - parents[1].addChild(leafsWords[1][4*i+2]); - parents[1].addChild(leafsWords[1][4*i+3]); - - parents[2].addChild(leafsWords[2][4*i]); - parents[2].addChild(leafsWords[2][4*i+1]); - parents[2].addChild(leafsWords[3][4*i]); - parents[2].addChild(leafsWords[3][4*i+1]); - - parents[3].addChild(leafsWords[2][4*i+2]); - parents[3].addChild(leafsWords[2][4*i+3]); - parents[3].addChild(leafsWords[3][4*i+2]); - parents[3].addChild(leafsWords[3][4*i+3]); - - parents[4].addChild(leafsWords[4][4*i]); - parents[4].addChild(leafsWords[4][4*i+1]); - parents[4].addChild(leafsWords[5][4*i]); - parents[4].addChild(leafsWords[5][4*i+1]); - - parents[5].addChild(leafsWords[4][4*i+2]); - parents[5].addChild(leafsWords[4][4*i+3]); - parents[5].addChild(leafsWords[5][4*i+2]); - parents[5].addChild(leafsWords[5][4*i+3]); - - let parent = new ParentSegment(this.templateContainer.copyParentTemplate()); - let triangle = new TriangleSegment(this.templateContainer.copyTriangleTemplate()); - if (i % 2 === 0) { - parent.addChild(parents[0]); - parent.addChild(parents[1]); - parent.addChild(parents[2]); - parent.addChild(parents[3]); - - let rowSegment = new RowSegment(this.templateContainer.copyRowTemplate()); - - rowSegment.addChild(parents[4]); - rowSegment.addChild(parents[5]); - - triangle.addChild(parent); - triangle.addChild(rowSegment); - - triangle.getElement().classList.add("type-1"); - } - else { - - let rowSegment = new RowSegment(this.templateContainer.copyRowTemplate()); - - rowSegment.addChild(parents[0]); - rowSegment.addChild(parents[1]); - - triangle.addChild(rowSegment); - triangle.addChild(parent); - - parent.addChild(parents[2]); - parent.addChild(parents[3]); - parent.addChild(parents[4]); - parent.addChild(parents[5]); - - triangle.getElement().classList.add("type-2"); - } - rootSegment.addChild(triangle); - } - this.setRootSegment(rootSegment); - } - } -} - -class SixWordsRowLevel8 extends SixWordsRowLevel { - constructor(templateContainer) { - super(templateContainer, 8); - } -} - -class SixWordsRowLevel12 extends SixWordsRowLevel { - constructor(templateContainer) { - super(templateContainer, 12); - } -} - -class FourWordsLevel extends Level { - - constructor(templateContainer, wordLength) { - super(templateContainer); - this.wordLength = wordLength; - } - - createSegments() { - if (this.words.length >= 4 && - this.words[0].length >= this.wordLength && - this.words[1].length >= this.wordLength && - this.words[2].length >= this.wordLength && - this.words[3].length >= this.wordLength - ) { - let leafsWords = []; - leafsWords[0] = Level._createLeafsForWord(this.words[0], this.templateContainer.copyLeafTemplate()); - leafsWords[1] = Level._createLeafsForWord(this.words[1], this.templateContainer.copyLeafTemplate()); - leafsWords[2] = Level._createLeafsForWord(this.words[2], this.templateContainer.copyLeafTemplate()); - leafsWords[3] = Level._createLeafsForWord(this.words[3], this.templateContainer.copyLeafTemplate()); - - let rootSegment = new RowSegment(this.templateContainer.copyRowTemplate()); - for (let i = 0; i < this.wordLength / 4; i++) { - - let parents = []; - parents[0] = new ParentSegment(this.templateContainer.copyParentTemplate()); - parents[1] = new ParentSegment(this.templateContainer.copyParentTemplate()); - parents[2] = new ParentSegment(this.templateContainer.copyParentTemplate()); - parents[3] = new ParentSegment(this.templateContainer.copyParentTemplate()); - - parents[0].addChild(leafsWords[0][4 * i]); - parents[0].addChild(leafsWords[0][4 * i + 1]); - parents[0].addChild(leafsWords[1][4 * i]); - parents[0].addChild(leafsWords[1][4 * i + 1]); - - parents[1].addChild(leafsWords[0][4 * i + 2]); - parents[1].addChild(leafsWords[0][4 * i + 3]); - parents[1].addChild(leafsWords[1][4 * i + 2]); - parents[1].addChild(leafsWords[1][4 * i + 3]); - - parents[2].addChild(leafsWords[2][4 * i]); - parents[2].addChild(leafsWords[2][4 * i + 1]); - parents[2].addChild(leafsWords[3][4 * i]); - parents[2].addChild(leafsWords[3][4 * i + 1]); - - parents[3].addChild(leafsWords[2][4 * i + 2]); - parents[3].addChild(leafsWords[2][4 * i + 3]); - parents[3].addChild(leafsWords[3][4 * i + 2]); - parents[3].addChild(leafsWords[3][4 * i + 3]); - - let parent = new ParentSegment(this.templateContainer.copyParentTemplate()); - parent.addChild(parents[0]); - parent.addChild(parents[1]); - parent.addChild(parents[2]); - parent.addChild(parents[3]); - - rootSegment.addChild(parent); - } - this.setRootSegment(rootSegment); - } - } -} - -class FourWordsLevel8 extends FourWordsLevel{ - constructor(templateContainer) { - super(templateContainer, 8); - } -} - -class FourWordsLevel12 extends FourWordsLevel{ - constructor(templateContainer) { - super(templateContainer, 12); - } -} - -class ColumnSegment extends RowSegment{ - - _updateElement() { - const childContainer = this.element.querySelector(".child-container"); - childContainer.removeAllChildren(); - - this._updateRotationClass(); - - const self = this; - this.element.onclick = function (e) { - self.rotate(); - e.stopPropagation(); - }; - - for (let i = 0, n = this.children.length; i < n; i++) { - this.children[i]._updateElement(); - childContainer.appendChild(this.children[i].getElement()); - } - } - - // constructor(element) { - // super(element); - // this.rotatable = false; - // } - // - // applyRotations(rotations) - // { - // for (let i = 0, n = this.children.length; i < n; i++) { - // rotations = this.children[i].applyRotations(rotations); - // } - // return rotations; - // } - // - // getCurrentRotations(rotations){ - // for (let i = 0, n = this.children.length; i < n; i++) { - // rotations = this.children[i].getCurrentRotations(rotations); - // } - // return rotations; - // } - // - // getCurrentLocked(locked) { - // for (let i = 0, n = this.children.length; i < n; i++) { - // locked = this.children[i].getCurrentLocked(locked); - // } - // return locked; - // } - // - // applyLocks(locks) { - // for (let i = 0, n = this.children.length; i < n; i++) { - // locks = this.children[i].applyLocks(locks); - // } - // return locks; - // } - // - // _updateElement() { - // const childContainer = this.element.querySelector(".child-container"); - // childContainer.removeAllChildren(); - // - // this._updateRotationClass(); - // - // const self = this; - // this.element.onclick = function (e) { - // self.rotate(); - // e.stopPropagation(); - // }; - // - // for (let i = 0, n = this.children.length; i < n; i++) { - // this.children[i]._updateElement(); - // childContainer.appendChild(this.children[i].getElement()); - // } - // } -} - -class SimpleFourWordsLevel extends Level{ - constructor(templateContainer, wordLength, bigSegmentPosition) { - super(templateContainer); - this.wordLength = wordLength; - this.bigSegmentPosition = bigSegmentPosition; - } - - createSegments() { - if (this.words.length >= 4 && - this.words[0].length >= this.wordLength && - this.words[1].length >= this.wordLength && - this.words[2].length >= this.wordLength && - this.words[3].length >= this.wordLength && - this.wordLength >= 4 - ) { - let leafsWords = []; - leafsWords[0] = Level._createLeafsForWord(this.words[0], this.templateContainer.copyLeafTemplate()); - leafsWords[1] = Level._createLeafsForWord(this.words[1], this.templateContainer.copyLeafTemplate()); - leafsWords[2] = Level._createLeafsForWord(this.words[2], this.templateContainer.copyLeafTemplate()); - leafsWords[3] = Level._createLeafsForWord(this.words[3], this.templateContainer.copyLeafTemplate()); - - let rootSegment = new RowSegment(this.templateContainer.copyRowTemplate()); - for (let i = 0; i < this.wordLength / 2; i++) { - let parents = []; - parents[0] = new ParentSegment(this.templateContainer.copyParentTemplate()); - parents[1] = new ParentSegment(this.templateContainer.copyParentTemplate()); - - parents[0].addChild(leafsWords[0][2 * i]); - parents[0].addChild(leafsWords[0][2 * i + 1]); - parents[0].addChild(leafsWords[1][2 * i]); - parents[0].addChild(leafsWords[1][2 * i + 1]); - - parents[1].addChild(leafsWords[2][2 * i]); - parents[1].addChild(leafsWords[2][2 * i + 1]); - parents[1].addChild(leafsWords[3][2 * i]); - parents[1].addChild(leafsWords[3][2 * i + 1]); - - let parentSegment =null; - if (i === this.bigSegmentPosition){ - parents[2] = new ParentSegment(this.templateContainer.copyParentTemplate()); - parents[3] = new ParentSegment(this.templateContainer.copyParentTemplate()); - - parents[2].addChild(leafsWords[0][2 * i + 2]); - parents[2].addChild(leafsWords[0][2 * i + 3]); - parents[2].addChild(leafsWords[1][2 * i + 2]); - parents[2].addChild(leafsWords[1][2 * i + 3]); - - parents[3].addChild(leafsWords[2][2 * i + 2]); - parents[3].addChild(leafsWords[2][2 * i + 3]); - parents[3].addChild(leafsWords[3][2 * i + 2]); - parents[3].addChild(leafsWords[3][2 * i + 3]); - - parentSegment = new ParentSegment(this.templateContainer.copyParentTemplate()); - parentSegment.addChild(parents[0]); - parentSegment.addChild(parents[2]); - parentSegment.addChild(parents[1]); - parentSegment.addChild(parents[3]); - i++; - } - else{ - parentSegment = new ColumnSegment(this.templateContainer.copyColumnTemplate()); - parentSegment.addChild(parents[0]); - parentSegment.addChild(parents[1]); - } - - rootSegment.addChild(parentSegment); - } - this.setRootSegment(rootSegment); - } - } -} - -class SimpleFourWordsLevel10_0 extends SimpleFourWordsLevel{ - constructor(templateContainer) { - super(templateContainer, 10, 0); - } -} - -class SimpleFourWordsLevel10_1 extends SimpleFourWordsLevel{ - constructor(templateContainer) { - super(templateContainer, 10, 1); - } -} - -class SimpleFourWordsLevel10_2 extends SimpleFourWordsLevel{ - constructor(templateContainer) { - super(templateContainer, 10, 2); - } -} - -class SimpleFourWordsLevel10_3 extends SimpleFourWordsLevel{ - constructor(templateContainer) { - super(templateContainer, 10, 3); - } -} - -class LevelHelper { - static setLevelType(typeId, level) { - LevelHelper.types[typeId] = level; - } - - static getLevelClass(type) { - return LevelHelper.types[type]; - } - - static inflateLevel(jsonLevel, templateContainer) { - let level = new (LevelHelper.types[jsonLevel["rendererType"]])(templateContainer); - level.setWords(jsonLevel["words"]); - level.setId(jsonLevel["id"]); - - for (let i = 0, n = jsonLevel["rotations"].length; i < n; i++) { - if (jsonLevel["rotations"][i] <= 4) { - jsonLevel["rotations"][i] = 90 * jsonLevel["rotations"][i]; - } - } - - level.setStartRotations(jsonLevel["rotations"]); - return level; - } -} - -LevelHelper.types = { - 20: SimpleLevel, - 40: RowLevel8, - 60: RowLevel10, - 80: SimpleFourWordsLevel10_0, - 81: SimpleFourWordsLevel10_1, - 82: SimpleFourWordsLevel10_2, - 83: SimpleFourWordsLevel10_3, - 100: SixWordsRowLevel8, - 120: FourWordsLevel8, - 140: SixWordsRowLevel12, - 160: FourWordsLevel12, -}; - -class WordRotatorDb extends MyDb { - - static async getInstance() { - if (Helper.isNull(WordRotatorDb.instance)) { - WordRotatorDb.instance = new WordRotatorDb(); - } - await WordRotatorDb.instance.queryPromise; - return WordRotatorDb.instance; - } - - constructor() { - super("wordRotator", 6); - } - - upgrade(db, oldVersion, newVersion, e) { - console.log("upgrading!"); - - if (Helper.isNull(oldVersion) || oldVersion < 1 && newVersion >= 1) { - let levelObjectStore = db.createObjectStore(WordRotatorDb.OBJECT_STORE.LEVEL, {"keyPath": "id"}); - } - if (Helper.isNull(oldVersion) || oldVersion < 2 && newVersion >= 2) { - let levelObjectStore = e.target.transaction.objectStore(WordRotatorDb.OBJECT_STORE.LEVEL); - levelObjectStore.createIndex("played", ["deleted", "played", "difficulty", "id"], {"unique": false}); - } - if (Helper.isNull(oldVersion) || oldVersion < 3 && newVersion >= 3) { - let levelObjectStore = e.target.transaction.objectStore(WordRotatorDb.OBJECT_STORE.LEVEL); - levelObjectStore.createIndex("difficulty", "difficulty", {"unique": false}); - } - - console.log("update", oldVersion, newVersion); - if (Helper.isNull(oldVersion) || oldVersion < 6 && newVersion >= 6) { - try { - db.deleteObjectStore(WordRotatorDb.OBJECT_STORE.SYSTEM_VARS); - } catch (e) {} - let levelObjectStore = db.createObjectStore(WordRotatorDb.OBJECT_STORE.SYSTEM_VARS, {"keyPath": "name"}); - } - }; - - async saveManyLevels(levels) { - return this.saveMany(levels, WordRotatorDb.OBJECT_STORE.LEVEL).catch(e => { - console.error("insert error!", e); - }); - } - - async loadLevel(levelId) { - // console.log("load Level", levelId); - return this.load(levelId, WordRotatorDb.OBJECT_STORE.LEVEL); - } - - async loadNextLevel(rendererTypes) { - let levels = await this.loadAll(WordRotatorDb.OBJECT_STORE.LEVEL); - levels = levels.sort((a, b) => { - return (a["difficulty"] - b["difficulty"]); - }); - - let wrongLevels = []; - let newLevels = []; - let difficulty = -1; - for (let i = 0, n = levels.length; i < n; i++) { - if ((difficulty < 0 || difficulty === levels[i]["difficulty"]) && !levels[i]["deleted"] && !levels[i]["played"] && rendererTypes.indexOf(levels[i]["rendererType"]) !== -1) { - newLevels.push(levels[i]); - difficulty = levels[i]["difficulty"]; - } - else if (levels[i]["difficulty"] !== 0 && !levels[i]["deleted"] && !levels[i]["played"]) { - wrongLevels.push(levels[i]); - } - } - - if (newLevels.length === 0) { - return null; - } - - return newLevels[Math.round(Math.random() * newLevels.length) % newLevels.length]; - } - - async saveLevelPlayed(levelId) { - const level = await this.loadLevel(levelId); - level.played = true; - return await this.saveObj(level, WordRotatorDb.OBJECT_STORE.LEVEL); - } - - async loadDateLastSync() { - let dateLastSync = await this.load("date-last-sync", WordRotatorDb.OBJECT_STORE.SYSTEM_VARS); - if (dateLastSync) { - return dateLastSync["value"]; - } - return null; - } - - async saveDateLastSync(value) { - return await this.saveObj({"name": "date-last-sync", "value": value}, WordRotatorDb.OBJECT_STORE.SYSTEM_VARS) - } -} - -WordRotatorDb.OBJECT_STORE = { - LEVEL: "level", - SYSTEM_VARS: "vars" -}; -WordRotatorDb.instance = null; - -class EndSite extends WordRotatorBaseSite{ - constructor(siteManager) { - super(siteManager, "html/application/end.html"); - } - - onStart(args) { - Matomo.update("End Site"); - return super.onStart(args); - } -} - -class LevelSite extends WordRotatorBaseSite { - constructor(siteManager) { - super(siteManager, "html/application/level.html"); - } - - createActionBarMenu(menu) { - menu = super.createActionBarMenu(menu); - - let coinAction = new MenuAction(Helper.nonNull(localStorage.getItem("coins"), "0"), () => { - }, MenuAction.SHOW_ALWAYS, 900); - coinAction.setShouldTranslate(false); - coinAction._liClass = "coin-counter"; - menu.addAction(coinAction); - this.coinAction = coinAction; - - return menu; - } - - onConstruct(args) { - this.levelCounter = Helper.nonNull(localStorage.getItem("levelCounter"), 1); - this.levelScaler = () => { - }; - this.wonParams = { - aborted: false, - coinCounterTimer: null, - }; - this.coinPromise = Promise.resolve(); - - let settingsManager = SettingsManager.getInstance(); - let soundManager = SoundManager.getInstance(); - soundManager.set({ - audio: "sound/single_coin_fall_on_concrete_.mp3", - muted: (settingsManager.getSetting("play-sound", "1") !== "1"), - volume: 0.7 - }, SoundManager.CHANNELS.SOUND); - - soundManager.resume(SoundManager.CHANNELS.MUSIC); - - return super.onConstruct(args); - } - - async onFirstStart() { - super.onFirstStart(); - let leafSegmentTemplate = this.findBy("#segment-leaf-template"); - let parentSegmentTemplate = this.findBy("#segment-parent-template"); - let rowSegmentTemplate = this.findBy("#segment-row-template"); - let triangleTemplate = this.findBy("#segment-triangle-template"); - let columnTemplate = this.findBy("#segment-column-template"); - - leafSegmentTemplate.removeAttribute("id"); - parentSegmentTemplate.removeAttribute("id"); - rowSegmentTemplate.removeAttribute("id"); - triangleTemplate.removeAttribute("id"); - columnTemplate.removeAttribute("id"); - - leafSegmentTemplate.remove(); - parentSegmentTemplate.remove(); - rowSegmentTemplate.remove(); - triangleTemplate.remove(); - columnTemplate.remove(); - - let self = this; - let continueButton = this.findBy("#continue-button"); - continueButton.addEventListener("click", () => { - self.nextLevel(); - }); - - let wonText = this.findBy("#won-text"); - - let scaleHelper = new ScaleHelper(); - this.continueButtonScaler = await scaleHelper.scaleToFull(continueButton, continueButton.parentElement, false, true, 2); - this.wonTextScaler = await scaleHelper.scaleToFull(wonText, wonText.parentElement, false, false, 2, null, 5); - this.wonText = wonText; - this.wonText.style.fontSize = "0"; - - //Benutze Document, da Element außerhalb von Seite (eigentlich unschön!) - this.levelCounterActionContainer = document.getElementById("level-number-container"); - this.levelCounterAction = document.getElementById("level-number"); - this.levelCounterAction.innerText = this.levelCounter; - this.levelNumberScaler = await scaleHelper.scaleToFull(this.levelCounterAction, this.levelCounterActionContainer, false, false, 4); - this.levelCounterActionContainer.classList.add("visible"); - this.templateContainer = new TemplateContainer(leafSegmentTemplate, parentSegmentTemplate, rowSegmentTemplate, triangleTemplate, columnTemplate); - - this.coinTemplate = this.findBy("#coin-template"); - this.coinContainer = this.findBy("#coin-container"); - - this.coinTemplate.id = null; - this.coinContainer.removeAllChildren(); - - this.findBy("#help-button").addEventListener("click", () => { - this.help(); - }); - await this.loadLastLevel(); - } - - async loadLastLevel() { - try { - let currentLevelInfo = localStorage.getItem("currentLevel"); - if (Helper.isNotNull(currentLevelInfo)) { - currentLevelInfo = JSON.parse(currentLevelInfo); - - const db = await WordRotatorDb.getInstance(); - const levelJson = await db.loadLevel(currentLevelInfo["id"]); - - if (levelJson === null) { - return this.nextLevel(); - } - - let level = LevelHelper.inflateLevel(levelJson, this.templateContainer); - level.setStartRotations(currentLevelInfo["rotations"]); - - const self = this; - level.getWonPromise().then(() => { - self.levelWon(level); - }); - - level.createSegments(); - level.setLocks(currentLevelInfo["locks"]); - level.getRootSegment()._updateElement(); - - level.saveAsCurrentLevel(); - - let levelSegment = this.findBy("#level"); - levelSegment.removeAllChildren().appendChild(level.getRootSegment().getElement()); - let scaleHelper = new ScaleHelper(); - this.levelScaler = await scaleHelper.scaleToFull(levelSegment, levelSegment.parentElement, false, false, 1, level.words[0].length * 1.5, null, 0); - - this.level = level; - let res = this.tutorial(); - Matomo.push(["trackEvent", "LevelSite", "LoadLastLevel"]); - this.level.checkHasWon(); - return res; - } - } - catch (e) { - console.error(e); - } - return this.nextLevel(); - } - - startEndSite(){ - this.startSite(EndSite); - this.finish(); - } - - async nextLevel() { - try { - this._siteContent.classList.remove('won'); - this.wonText.style.fontSize = "0"; - - const db = await WordRotatorDb.getInstance(); - const nextLevelJson = await db.loadNextLevel(LevelSite.RENDERER_TYPES); - - console.log("nextLevelJson", nextLevelJson); - if (nextLevelJson === null) { - this.startEndSite(); - return; - } - const level = LevelHelper.inflateLevel(nextLevelJson, this.templateContainer); - const self = this; - level.getWonPromise().then(() => { - self.levelWon(level); - }); - - level.createSegments(); - level.getRootSegment()._updateElement(); - - level.saveAsCurrentLevel(); - - let levelSegment = this.findBy("#level"); - levelSegment.removeAllChildren().appendChild(level.getRootSegment().getElement()); - let scaleHelper = new ScaleHelper(); - this.levelScaler = await scaleHelper.scaleToFull(levelSegment, levelSegment.parentElement, false, false, 1, level.words[0].length * 1.5, null, 0); - - this.level = level; - this.levelCounterAction.innerText = this.levelCounter; - this.levelNumberScaler(); - - this.coinAction.setTitle(Helper.nonNull(localStorage.getItem("coins"), "0")); - this.coinAction.redraw(); - - this.wonParams.aborted = true; - clearTimeout(this.wonParams.coinCounterTimer); - - Matomo.push(["trackEvent", "LevelSite", "NextLevel", "Level Number Normal", this.levelCounter]); - - this.level.checkHasWon(); - - return this.tutorial(); - } - catch (e) { - console.log("Fehler!"); - console.error(e); - this.startEndSite(); - } - } - - onStart(args) { - Matomo.update("Level Site"); - let res = super.onStart(args); - - if (this.levelCounterAction) { - - this.levelCounterAction.innerText = this.levelCounter; - this.levelCounterActionContainer.classList.add("visible"); - } - this.levelScaler(); - - let settingsManager = SettingsManager.getInstance(); - let soundManager = SoundManager.getInstance(); - soundManager.set({ - audio: "sound/single_coin_fall_on_concrete_.mp3", - muted: (settingsManager.getSetting("play-sound", "1") !== "1"), - volume: 0.7 - }, SoundManager.CHANNELS.SOUND); - - return res; - } - - onPause(args) { - super.onPause(args); - this.levelCounterActionContainer.classList.remove("visible"); - } - - async levelWon(level) { - try { - const db = await WordRotatorDb.getInstance(); - const savePromise = db.saveLevelPlayed(level.getId()); - - this.levelCounter++; - localStorage.setItem("levelCounter", this.levelCounter); - - this._siteContent.classList.add('won'); - localStorage.removeItem("currentLevel"); - - let continueButton = this.findBy("#continue-button"); - continueButton.style.transition = "none"; - continueButton.style.opacity = 0; - - this.coinContainer.removeAllChildren(); - let coinsPerLevel = SystemSettings.get("coinsPerLevel", 5); - - let coinsBefore = 0; - - let soundManager = SoundManager.getInstance(); - let audioOptions = soundManager.get(SoundManager.CHANNELS.SOUND); - - this.coinPromise = this.coinPromise.then(() => { - coinsBefore = parseInt(Helper.nonNull(localStorage.getItem("coins"), "0")); - localStorage.setItem("coins", coinsBefore + parseInt(coinsPerLevel)); - }).then(() => { - return Promise.all([new Promise((r) => { - setTimeout(() => { - r(continueButton.fadeIn()); - }, 500); - }), audioOptions.loadedPromise.catch(e => { - console.error(e); - })]); - }); - - this.wonParams.aborted = false; - - for (let i = 0; i < coinsPerLevel; i++) { - let coinElem = Helper.cloneNode(this.coinTemplate); - this.coinContainer.appendChild(coinElem); - this.coinPromise = this.coinPromise.then(() => { - return new Promise(r => { - let timeout = 350; - if (!this.wonParams.aborted) { - coinElem.fadeIn(timeout / 1000); - soundManager.play(SoundManager.CHANNELS.SOUND); - - this.wonParams.coinCounterTimer = setTimeout(() => { - if (!this.wonParams.aborted) { - this.coinAction.setTitle(++coinsBefore); - this.coinAction.redraw(); - } - }, timeout / 2); - } - else { - r(); - } - //Always do the next promise for garbage collection - setTimeout(r, timeout); - }) - }); - } - - this.coinPromise = this.coinPromise.catch((e) => { - console.error(e); - }); - - this.wonTextScaler(); - this.continueButtonScaler(); - this.levelScaler(); - - Matomo.push(["trackEvent", "LevelSite", "LevelWon", "Coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"))]); - - await savePromise; - } - catch (e) { - console.error(e); - } - } - - help() { - let cost = SystemSettings.get("costForHelp", 25); - let currentCoins = parseInt(Helper.nonNull(localStorage.getItem("coins"), 0)); - - if (currentCoins >= cost) { - currentCoins -= cost; - localStorage.setItem("coins", currentCoins); - this.coinAction.title = currentCoins; - this.coinAction.redraw(); - - let rotatables = this.level.getRotatableSegments(); - rotatables = rotatables.filter((segment) => { - return (!segment.isSolved(false)); - }); - - let index = Math.floor(Math.random() * rotatables.length); - - let segmentToHelp = rotatables[index]; - while (segmentToHelp.rotation !== 0) { - segmentToHelp.rotate(); - } - segmentToHelp.setIsRotatable(false); - this.level.saveAsCurrentLevel(); - - Matomo.push(["trackEvent", "LevelSite", "Help", "Coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"))]); - } - else { - FlashMessenger.addMessage("not-enough-coins"); - Matomo.push(["trackEvent", "LevelSite", "Help", "Not enough Coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0"))]); - } - } - - async tutorial() { - if (this.level.id === LevelSite.TUTORIAL.FIRST_LEVEL) { - let currentStep = Helper.nonNull(localStorage.getItem("tutorial-step"), "1"); - - let scaleHelper = new ScaleHelper(); - this._siteContent.classList.add("tutorial"); - this._siteContent.classList.add("step-" + currentStep); - - switch (currentStep) { - case "1": { - this.level.setSegmentClickedListener(() => { - this._siteContent.classList.remove("step-1"); - localStorage.setItem("tutorial-step", "2"); - this.tutorial(); - }); - - let textElem = this.findBy(".tutorial-text .step-1"); - - await this.levelScaler(); - scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, 1, 2); - - break; - } - case "2": { - this.level.setSegmentClickedListener(() => { - }); - this.level.getWonPromise().then(() => { - this._siteContent.classList.remove("tutorial"); - this._siteContent.classList.remove("step-2"); - localStorage.removeItem("tutorial-step"); - this.coinPromise = this.coinPromise.then(() => { - FlashMessenger.addMessage("extra-coins-after-first-level"); - localStorage.setItem("coins", parseInt(Helper.nonNull(localStorage.getItem("coins"), "0")) + 50); - this.coinAction.setTitle(Helper.nonNull(localStorage.getItem("coins"), "0")); - this.coinAction.redraw(); - }); - // this.levelScaler(); - }); - - let textElem = this.findBy(".tutorial-text .step-2"); - - await this.levelScaler(); - scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, 1, 2); - - break; - } - default:{ - this._siteContent.classList.remove("tutorial"); - } - } - } - else if (this.level.id === LevelSite.TUTORIAL.SECOND_LEVEL) { - let currentStep = Helper.nonNull(localStorage.getItem("tutorial-step"), "3"); - - switch (currentStep) { - case "3": { - let scaleHelper = new ScaleHelper(); - - this._siteContent.classList.add("tutorial"); - this._siteContent.classList.add("step-" + currentStep); - - let eventListener = () => { - this._siteContent.classList.remove("tutorial"); - this._siteContent.classList.remove("step-3"); - localStorage.setItem("tutorial-step", "4"); - this.findBy("#help-button").removeEventListener("click", eventListener); - this.levelScaler(); - }; - this.findBy("#help-button").addEventListener("click", eventListener); - - let textElem = this.findBy(".tutorial-text .step-3"); - - await this.levelScaler(); - scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, 1, 2); - break; - } - default:{ - this._siteContent.classList.remove("tutorial"); - } - } - } - else if (this.level.id === LevelSite.TUTORIAL.BIG_SEGMENT_LEVEL) { - let currentStep = Helper.nonNull(localStorage.getItem("tutorial-step"), "4"); - - switch (currentStep) { - case "4": { - - let scaleHelper = new ScaleHelper(); - this._siteContent.classList.add("tutorial"); - this._siteContent.classList.add("step-" + currentStep); - - let rotatableSegments = this.level.getRotatableSegments(); - let firstSegment = rotatableSegments[2]; - - let pointer = this.findBy("#tutorial-pointer"); - pointer.remove(); - firstSegment.element.appendChild(pointer); - - this.level.setSegmentClickedListener((segment) => { - if (firstSegment === segment) { - this._siteContent.classList.remove("tutorial"); - this._siteContent.classList.remove("step-4"); - localStorage.setItem("tutorial-step", "5"); - this.levelScaler(); - } - }); - - let textElem = this.findBy(".tutorial-text .step-4"); - - await this.levelScaler(); - scaleHelper.scaleToFull(textElem, textElem.parentElement, null, true, 1, 2); - - break; - } - default:{ - this._siteContent.classList.remove("tutorial"); - } - } - } - } -} -LevelSite.RENDERER_TYPES = [20, 40, 60, 80, 81, 82, 83, 100, 120, 140, 160]; -LevelSite.TUTORIAL = { - FIRST_LEVEL: 67, - SECOND_LEVEL: 15, - BIG_SEGMENT_LEVEL: 1386 -}; - -class MainMenuLevel extends FourWordsLevel{ - - constructor(templateContainer) { - super(templateContainer, 4); - } - - saveAsCurrentLevel() { - } - - // checkHasWon(delayPromise) { - // } -} - -class ShareDialog extends Dialog{ - constructor() { - let viewPromise = ViewInflater.inflate("html/application/dialog/share.html").then(view => { - view.appendChild(ShareManager.generateDefaultShareElement(window.location.hostname + Helper.basePath(""))); - let closeListener = () => { - this.close(); - }; - - view.querySelectorAll("a").forEach((element) => { - element.addEventListener("click", closeListener); - }); - return view; - }); - - super(viewPromise, "share-dialog"); - } -} - -class MenuSite extends WordRotatorBaseSite { - constructor(siteManager) { - super(siteManager, "html/application/menu.html"); - this.loadLevelPromise = this.loadLevels(); - this.listener = null; - } - - onStart(args) { - Matomo.update("Menu Site"); - let res = super.onStart(args); - - let level = new MainMenuLevel(this.templateContainer); - level.setWords(["WORD", "ROTA", "TORW", "ORDR"]); - level.createSegments(); - - level.getWonPromise().then(() => { - Matomo.push(["trackEvent", "MainMenu", "levelSolved"]); - this.startLevelSite(); - }); - - let segment = level.getRootSegment(); - segment._updateElement(); - - let levelSegment = this.findBy("#level"); - levelSegment.removeAllChildren().appendChild(segment.getElement()); - - let rotationsSegments = level.getRotatableSegments(); - - let randomRotationFunction = () => { - let timeout = Math.random() * 4500 + 1500; - this.randomRotateTimeout = setTimeout(() => { - let indexBlocked = -1; - let indexesNotRight = []; - for (let i = 0; i < rotationsSegments.length; i++) { - if (rotationsSegments[i].rotation !== 0) { - indexesNotRight.push(i); - if (indexesNotRight.length >= 2) { - break; - } - } - } - if (indexesNotRight.length === 1) { - indexBlocked = indexesNotRight[0]; - } - - let index = Math.floor(Math.random() * rotationsSegments.length); - if (index === indexBlocked) { - index = (index + 1) % rotationsSegments.length; - } - - rotationsSegments[index].rotate(); - randomRotationFunction(); - }, timeout); - }; - randomRotationFunction(); - - this.listener = async () => { - let playButton = this.findBy("#play-button"); - let levelNumber = this.findBy("#level-number"); - levelNumber.innerText = Helper.nonNull(localStorage.getItem("levelCounter"), 1); - - let levelSegment = this.findBy("#level"); - - let scaleHelper = new ScaleHelper(); - await scaleHelper.scaleToFull(levelSegment, levelSegment.parentElement, false, false, 2, 8, null, false); - - // debugger; - let levelStyle = getComputedStyle(levelSegment); - playButton.style.width = levelStyle.getPropertyValue("width"); - scaleHelper.scaleToFull(playButton.children[0], playButton, null, null, null, 4, null, false); - - await scaleHelper.scaleTo(0.2, levelNumber.parentElement, levelNumber.parentElement.parentElement, null, null, null, 10, null, false); - scaleHelper.scaleToFull(levelNumber, levelNumber.parentElement, false, false, 8, null, null, false); - }; - - this.listener(); - window.addEventListener("resize", this.listener); - - //Musikbuttons update, falls in den Einstellungen umgestellt - let settingsManager = SettingsManager.getInstance(); - let playSoundButton = this.findBy("#play-sound"); - playSoundButton.checked = (settingsManager.getSetting("play-sound", "1") === "1"); - let playMusicButton = this.findBy("#play-music"); - playMusicButton.checked = (settingsManager.getSetting("play-music", "1") === "1"); - - return res; - } - - async startLevelSite() { - SoundManager.getInstance().resumeContext(); - this.startSite(LevelSite, Promise.race([this.loadLevelPromise, new Promise(async resolve => { - const db = await WordRotatorDb.getInstance(); - let level = await db.loadNextLevel(LevelSite.RENDERER_TYPES); - if (level !== null) { - resolve(); - } - })])); - } - - async onFirstStart() { - super.onFirstStart(); - - let playButton = this.findBy("#play-button"); - playButton.addEventListener("click", () => { - Matomo.push(["trackEvent", "MainMenu", "startButton"]); - this.startLevelSite(); - }); - - let leafSegmentTemplate = this.findBy("#segment-leaf-template"); - let parentSegmentTemplate = this.findBy("#segment-parent-template"); - let rowSegmentTemplate = this.findBy("#segment-row-template"); - let triangleTemplate = this.findBy("#segment-triangle-template"); - - leafSegmentTemplate.id = null; - parentSegmentTemplate.id = null; - rowSegmentTemplate.id = null; - triangleTemplate.id = null; - - leafSegmentTemplate.remove(); - parentSegmentTemplate.remove(); - rowSegmentTemplate.remove(); - triangleTemplate.remove(); - - this.templateContainer = new TemplateContainer(leafSegmentTemplate, parentSegmentTemplate, rowSegmentTemplate, triangleTemplate); - - if (Helper.nonNull(MenuSite.app._cookieClosePromise)) { - MenuSite.app._cookieClosePromise.then(() => { - if (this.listener) { - this.listener(); - } - }); - } - - let settingsManager = SettingsManager.getInstance(); - let soundManager = SoundManager.getInstance(); - - let playMusicButton = this.findBy("#play-music"); - playMusicButton.checked = (settingsManager.getSetting("play-music", "1") === "1"); - playMusicButton.addEventListener("change", () => { - settingsManager.setSetting("play-music", (playMusicButton.checked) ? "1" : "0"); - soundManager.set({muted: !playMusicButton.checked}, SoundManager.CHANNELS.MUSIC); - if (playMusicButton.checked) { - soundManager.play(SoundManager.CHANNELS.MUSIC); - } - Matomo.push(["trackEvent", "MainMenu", "PlayMusic", "Play Music", (playMusicButton.checked) ? 1 : 0]); - }); - - let playSoundButton = this.findBy("#play-sound"); - playSoundButton.checked = (settingsManager.getSetting("play-sound", "1") === "1"); - playSoundButton.addEventListener("change", () => { - settingsManager.setSetting("play-sound", (playSoundButton.checked) ? "1" : "0"); - soundManager.set({muted: !playSoundButton.checked}, SoundManager.CHANNELS.SOUND); - Matomo.push(["trackEvent", "MainMenu", "PlaySound", "Play Sound", (playSoundButton.checked) ? 1 : 0]); - }); - - this.findBy("#share-button").addEventListener("click", () => { - new ShareDialog().show(); - }); - // this.findBy("#share-buttons").appendChild(ShareManager.generateDefaultShareElement("https://wordrotator.silas.link")); - } - - onPause(args) { - clearTimeout(this.randomRotateTimeout); - window.removeEventListener("resize", this.listener); - super.onPause(args); - } - - async loadLevels() { - try { - const db = await WordRotatorDb.getInstance(); - const dateLastSync = Helper.nonNull(await db.loadDateLastSync(), 0); - // const dateLastSync = Helper.nonNull(localStorage.getItem("date-last-sync"), 0); - - // let numberLevels = db.countLevels(); - let newLastSync = null; - let maxRuns = 1; - let levelPromises = []; - for (let run = 0; run < maxRuns; run++) { - let res = await DataManager.load("wordRotator/levels" + DataManager.buildQuery({ - "currentRun": run, - "dateLastSync": dateLastSync - })); - if (!res["success"]) { - if (await db.loadNextLevel(LevelSite.RENDERER_TYPES) === null) { - FlashMessenger.addMessage("sync-error", null, 6000); - } - newLastSync = null; - break; - } - res = res["result"]; - newLastSync = Helper.nonNull(newLastSync, res["currentSyncDate"]); - maxRuns = res["maxRuns"]; - - let levels = res["levels"]; - for (let i = 0; i < levels.length; i++) { - let currentLevel = levels[i]; - levelPromises.push(db.loadLevel(levels[i]["id"]).then(level => { - currentLevel["played"] = (Helper.nonNull(Helper.nonNull(level, {}).played, false)); - return currentLevel; - })); - } - } - let levels = await Promise.all(levelPromises); - await db.saveManyLevels(levels); - - if (newLastSync != null && newLastSync !== "null") { - localStorage.setItem("date-last-sync", newLastSync); - db.saveDateLastSync(newLastSync); - } - } - catch(e){ - // if (await db.loadNextLevel(LevelSite.RENDERER_TYPES) === null) { - FlashMessenger.addMessage("sync-error", null, 6000); - // } - console.error(e); - } - } -} - -MenuSite.app = null; -InitPromise.addPromise(app => { - MenuSite.app = app; -}); - -class PrivacyPolicySite extends WordRotatorBaseSite { - constructor(siteManager) { - super(siteManager, "html/application/privacyPolicy.html", "privacyPolicy"); - } - - onFirstStart() { - let trackSwitch =this.findBy("#track-switch"); - - trackSwitch.addEventListener("change", function (e) { - Matomo.setTrack(this.checked === true); - e.stopPropagation(); - e.preventDefault(); - }); - super.onFirstStart(); - } - - onStart(args) { - let trackSwitch =this.findBy("#track-switch"); - let shouldTrack = (Helper.nonNull(localStorage.getItem("matomoShouldTrack"), "1") === "1"); - trackSwitch.checked = shouldTrack; - - Matomo.update("Privacy Policy Site"); - return super.onStart(args); - } -} - -InitPromise.addPromise(app => { - app.addDeepLink("privacyPolicy", PrivacyPolicySite); -}); - -class CreditsSite extends WordRotatorBaseSite{ - constructor(siteManager) { - super(siteManager, "html/application/credits.html", "credits"); - } - - onStart(args) { - Matomo.update("Credits Site"); - return super.onStart(args); - } -} - -InitPromise.addPromise(app => { - app.addDeepLink("credits", CreditsSite); -}); - -class ChooseThemeDialog extends Dialog { - - constructor() { - let viewPromise = ViewInflater.inflate("html/application/dialog/chooseTheme.html").then(view => { - - let template = view.querySelector("#choose-theme-template"); - template.remove(); - template.id = null; - - let themeTemplateContainer = view.querySelector("#theme-choose-container"); - - for (let i = 0; i < ThemeManager.themes.length; i++) { - let themeElem = Helper.cloneNode(template); - let theme = ThemeManager.themes[i]; - themeElem.querySelector(".name").appendChild(Translator.makePersistentTranslation(theme._name)); - themeElem["dataset"]["theme"] = theme._name; - - themeElem.addEventListener("click", () => { - this.result = themeElem["dataset"]["theme"]; - this.close(); - }); - themeTemplateContainer.appendChild(themeElem); - } - - return view; - }); - - super(viewPromise, "choose-theme-dialog-title"); - } -} - -class ImpressumSite extends WordRotatorBaseSite{ - constructor(siteManager) { - super(siteManager, "html/application/impressum.html", "impressum"); - } -} - -InitPromise.addPromise(app => { - app.addDeepLink("impressum", ImpressumSite); -}); - -class PersistDialog extends ConfirmDialog{ - constructor() { - super(Helper.isChrome()?"persist-storage-dialog-message":"persist-storage-dialog-message-firefox", "persist-storage-dialog-title"); - } -} - -class WordRotatorSettingFragment extends LocalStorageSettingsFragment { - constructor(site) { - super(site, "html/application/fragment/settings.html"); - } - - onFirstStart() { - let currentThemeName = ThemeManager.currentTheme._name; - SettingsManager.getInstance().setSetting("theme", currentThemeName); - - let themeNameElem = this.findBy("#theme-name"); - themeNameElem.removeAllChildren().appendChild(Translator.makePersistentTranslation(currentThemeName)); - this.findBy("#theme-chooser").addEventListener("click", async () => { - let newTheme = await (new ChooseThemeDialog()).show(); - if (Helper.isNotNull(newTheme)) { - SettingsManager.getInstance().setSetting("theme", newTheme); - ThemeManager.changeCurrentTheme(newTheme); - themeNameElem.removeAllChildren().appendChild(Translator.makePersistentTranslation(newTheme)); - } - }); - - this.findBy("#reset-levels").addEventListener("click", async () => { - localStorage.removeItem("currentLevel"); - localStorage.removeItem("date-last-sync"); - localStorage.removeItem("levelCounter"); - localStorage.removeItem("tutorial-step"); - (await WordRotatorDb.getInstance()).removeAll(WordRotatorDb.OBJECT_STORE.LEVEL); - }); - - if (location.hostname.includes("beta") || location.hostname.includes("127.0.0.1")) { - this.findBy("#reset-levels").classList.remove("hidden"); - } - - let playMusicButton = this.findBy("#play-music"); - playMusicButton.addEventListener("change", () => { - let soundManager = SoundManager.getInstance(); - soundManager.set({muted: !playMusicButton.checked}, SoundManager.CHANNELS.MUSIC); - if (playMusicButton.checked) { - soundManager.play(SoundManager.CHANNELS.MUSIC); - } - }); - - this.findBy("#track-switch").addEventListener("change", function (e) { - Matomo.setTrack(this.checked === true); - e.stopPropagation(); - e.preventDefault(); - }); - - this.findBy("#credits-button").addEventListener("click", () => { - this.getSite().startSite(CreditsSite); - }); - this.findBy("#privacy-policy-button").addEventListener("click", () => { - this.getSite().startSite(PrivacyPolicySite); - }); - this.findBy("#contact-button").addEventListener("click", () => { - this.getSite().startSite(ContactSite); - }); - this.findBy("#impressum-button").addEventListener("click", () => { - this.getSite().startSite(ImpressumSite); - }); - - InstallManager.setCanInstallListener(() => { - let installButton = this.findBy("#install-button"); - installButton.addEventListener("click", () => { - installButton.classList.add("hidden"); - InstallManager.prompt().then((e) => { - console.log("clicked", e); - if (e["outcome"] === "accepted") { - Matomo.trackEvent("installed", "installed"); - } - }); - }); - installButton.classList.remove("hidden"); - }); - - let storageManager = MyStorageManager.getInstance(); - if (storageManager.canPersist()) { - Promise.all([storageManager.isPersistent(), navigator.serviceWorker["ready"]]).then(res => { - let isPersisted = res[0]; - let storageObject = this.findBy("#storage-info"); - storageObject.appendChild(Translator.makePersistentTranslation("storage-info", [ - ((isPersisted) ? "" : "nicht")])); - storageObject.parentElement.classList.remove("hidden"); - storageObject.parentElement.addEventListener("click", async () => { - if (!isPersisted) { - let shouldAskForNotifications = false; - try { - // Helper.isChrome() - shouldAskForNotifications = await (new PersistDialog().show()); - if (shouldAskForNotifications) { - if (Helper.isChrome()) { - let sub = await res[1]["pushManager"]["subscribe"]({ - "userVisibleOnly": true, - "applicationServerKey": new Uint8Array([4, 148, 221, 15, 14, 122, 35, 21, 93, 74, 222, 174, 235, 216, 129, 40, 51, 187, 105, 151, 5, 96, 178, 155, 61, 201, 78, 209, 176, 187, 145, 94, 98, 96, 95, 27, 59, 90, 162, 0, 12, 225, 59, 105, 99, 135, 208, 210, 69, 29, 148, 141, 4, 178, 66, 114, 80, 207, 22, 90, 0, 115, 60, 150, 217]) - }); - } - } - } catch (e) { - if ('Notification' in window && Notification.permission === 'denied') { - FlashMessenger.addMessage('notification-permission-denied'); - } - } - if (Helper.isChrome() || shouldAskForNotifications) { - isPersisted = await storageManager.persist(); - storageObject.removeAllChildren().appendChild(Translator.makePersistentTranslation("storage-info", [ - ((isPersisted) ? "" : "nicht")])); - } - } - else { - new Dialog("already-persisted-dialog-message", "already-persisted-dialog-title").show(); - } - // storageManager.persist().then(isPersisted => { - // storageObject.removeAllChildren().appendChild(Translator.makePersistentTranslation("storage-info", [ - // Math.round(storage.usage / (1024 * 1024) * 100) / 100, - // Math.round(storage.quota / (1024 * 1024) * 100) / 100, - // Math.round(storage.usage / storage.quota * 10000) / 100, - // ((isPersisted) ? "" : "nicht")])); - // - // console.log("p", isPersisted); - // if (!isPersisted){ - // FlashMessenger.addMessage("storage-permission-not-get"); - // } - // else { - // FlashMessenger.addMessage("storage-permission-get"); - // } - // }); - }); - }); - } - return super.onFirstStart(); - } - - onStart() { - Matomo.update("Settings Site"); - super.onStart(); - } -} - -InitPromise.addPromise(function () { - SettingsSite.addSettingsFragment("settings", WordRotatorSettingFragment); -}); - -class SelectWordsSite extends UserSite{ - - constructor(siteManager) { - super(siteManager, "version/2/html/selectWords.html", null, "select-words"); - } - - async onConstruct(args) { - let res = await super.onConstruct(args); - this.stats = (await DataManager.load("words"))["result"]; - this.words = this.stats["wordsToCheck"]; - console.log(this.stats); - return res; - } - - onFirstStart() { - super.onFirstStart(); - this.findBy("#not-checked").appendChild(document.createTextNode(this.stats["wordsNotChecked"])); - this.findBy("#checked").appendChild(document.createTextNode(this.stats["wordsChecked"])); - this.findBy("#not-sure").appendChild(document.createTextNode(this.stats["wordsUnsure"])); - this.findBy("#deleted").appendChild(document.createTextNode(this.stats["wordsDeleted"])); - this.findBy("#unused").appendChild(document.createTextNode(this.stats["wordsNotUsed"])); - - let template = this.findBy("#word-template"); - template.id = null; - template.remove(); - - let container = this.findBy("#word-container"); - - let numWords = this.words.length; - for (let i = 0; i < numWords; i++) { - let wordElement = Helper.cloneNode(template); - wordElement.dataset["id"] = -1; - this.setWord(wordElement, this.words[i]); - container.appendChild(wordElement); - - wordElement.querySelector(".button-ok").addEventListener("click", async () => { - let newWord = (await DataManager.send("checkWord", { - "wordId":wordElement.dataset["id"], - "action":"1" - }))["result"]; - this.setWord(wordElement, newWord[0]); - }); - - wordElement.querySelector(".button-unsure").addEventListener("click", async () => { - let newWord = (await DataManager.send("checkWord", { - "wordId":wordElement.dataset["id"], - "action":"2" - }))["result"]; - this.setWord(wordElement, newWord[0]); - }); - - wordElement.querySelector(".button-delete").addEventListener("click", async () => { - let newWord = (await DataManager.send("checkWord", { - "wordId":wordElement.dataset["id"], - "action":"3" - }))["result"]; - this.setWord(wordElement, newWord[0]); - }); - } - } - - setWord(wordElement, word){ - wordElement.querySelector(".word").removeAllChildren().appendChild(document.createTextNode(word["word"])); - wordElement.dataset["id"] = word["id"]; - } -} - -InitPromise.addPromise(app => { - app.addDefaultAction(new UserAction("select-words", () => { - app.startSite(SelectWordsSite); - }, null, null, "select-words")); -}); - -class DeleteWordsSite extends UserSite { - constructor(siteManager) { - super(siteManager, "version/2/html/deleteLevels.html", null, "admin"); - } - - async onConstruct(args) { - let res = super.onConstruct(args); - this.words = (await DataManager.load("getDoubleUsedWordsAction"))["result"]; - return res; - } - - - onFirstStart() { - super.onFirstStart(); - - let levelTemplate = this.findBy("#level-template"); - let wordTemplate = this.findBy("#word-template"); - let wordContainer = this.findBy("#word-container"); - - levelTemplate.id = null; - levelTemplate.remove(); - - wordTemplate.id = null; - wordTemplate.remove(); - - for (let k in this.words) { - let wordElem = Helper.cloneNode(wordTemplate); - wordElem.querySelector(".name").appendChild(document.createTextNode(k)); - let levelContainer = wordElem.querySelector(".level-container"); - for (let j = 0; j < this.words[k].length; j++) { - let level = this.words[k][j]; - let levelElem = Helper.cloneNode(levelTemplate); - levelElem.querySelector(".id").appendChild(document.createTextNode(level["id"])); - levelElem.querySelector(".words").appendChild(document.createTextNode(level["words"])); - levelElem.querySelector(".positions").appendChild(document.createTextNode(level["rotations"])); - - levelElem.querySelector(".delete-button").addEventListener("click", async () => { - let res = await DataManager.send("deleteLevel", {"levelId": level["id"]}); - if (res["success"]){ - levelElem.remove(); - } - }); - - levelContainer.appendChild(levelElem); - } - wordContainer.appendChild(wordElem); - } - } -} - -InitPromise.addPromise(app => { - app.addDefaultAction(new UserAction("delete-levels", () => { - app.startSite(DeleteWordsSite); - },null, null, "admin")); -}); - -let basePath = "/pwa/wordRotator/public/"; -if (window.location.pathname.indexOf("publicTest/") >= 0) -{ - basePath = "/pwa/wordRotator/publicTest/"; -} - -SystemSettings.setBasePath(basePath); -Translator.supportedLanguages = ["de"]; -Translator.markTranslations = false; - -Matomo.SIDE_ID = "2"; - -window.onerror = (e, u, l) => { - console.error(e, u, l); -}; - -applyPolyfills(); - -ThemeManager.addTheme(new Theme('red', 'red')); -ThemeManager.addTheme(new Theme("blue", "blue")); -ThemeManager.addTheme(new Theme("black", "black")); -ThemeManager.addTheme(new Theme("green", "green")); -ThemeManager.addTheme(new Theme("pink", "pink")); -ThemeManager.addTheme(new Theme("dark", "dark")); - -ShareManager.addShareButton(new MatomoShareButton(new WhatsappShareButton('img/whatsapp.svg'), "whatsapp", true)); -ShareManager.addShareButton(new MatomoShareButton(new SmsShareButton('img/sms.svg'), "sms", true)); -ShareManager.addShareButton(new MatomoShareButton(new TelegramShareButton('img/telegram.svg'), "telegram", true)); -// ShareManager.addShareButton(new CopyShareButton('img/copy.svg')); - -let app$1 = new App(); - -AndroidBridge.addDefinition(() => { - window["app"] = app$1; - window["app"]["pause"] = app$1.pause; - window["app"]["resume"] = app$1.resume; - window["app"]["setAppEndListener"] = app$1.setAppEndListener; -}); - -SettingsSite.setTemplate("html/application/setting-template.html"); -// SettingsSite.shouldAddSettingsAction = false; - -RegistrationSite.addAction = false; -LoginSite.addLoginAction = false; - -InitPromise.resolve(app$1).then(async function () { - SettingsSite.settingsAction.showFor = MenuAction.SHOW_ALWAYS; - - let settingsManager = SettingsManager.getInstance(); - - let soundManager = SoundManager.getInstance(); - soundManager.play(SoundManager.CHANNELS.MUSIC, { - audio: "sound/brightAndBeautifull__.mp3", - loop: true, - volume: 0.6, - muted: (settingsManager.getSetting("play-music", "1") !== "1") - }).catch(e => console.error(e)); - - app$1.start(MenuSite); - Translator.setLanguage("de"); - - - - InstallManager.setCanInstallListener(e => {}); - let storageManager = MyStorageManager.getInstance(); - if (InstallManager.isInstalled()){ - storageManager.persist(); - } - - window["applyAndroidBridge"] = AndroidBridge.applyDefinitions; - - let wasOpened = (Helper.nonNull(localStorage.getItem('was-open'), "0") === "1"); - if (wasOpened){ - Promise.all([storageManager.isPersistent(), navigator["serviceWorker"]["ready"]]).then(res => { - if (!res[0]){ - FlashMessenger.addMessage("warning-data-not-persistent"); - } - }); - } - else{ - localStorage.setItem("was-open", "1"); - } -}); - -// console.log("trying push... 1"); -// navigator.serviceWorker["ready"].then(function (registration) { -// console.log("trying push... 2"); -// registration["pushManager"]["subscribe"]({ -// "userVisibleOnly": true, -// "applicationServerKey": new Uint8Array([0x4, 0x53, 0xb7, 0x8d, 0xc6, 0xd1, 0x1a, 0xd4, 0x8b, 0xb2, 0xeb, 0x82, 0xf0, 0x9e, 0x12, 0xf6, 0xd, 0x32, 0x18, 0xa, 0x35, 0xf, 0x2d, 0x4c, 0x5, 0x29, 0x15, 0x95, 0x23, 0xb1, 0xd3, 0xab, 0x87, 0x88, 0x85, 0x1d, 0xc0, 0x98, 0x6e, 0x65, 0xe3, 0xcb, 0xa2, 0x28, 0x63, 0x7, 0x34, 0x9b, 0xfa, 0x46, 0x9a, 0x49, 0xcc, 0x70, 0x7a, 0xdd, 0xbe, 0x1e, 0xfc, 0xde, 0xcc, 0xb3, 0x5b, 0xcb, 0xf4]) -// }).then(function (sub) { -// console.log("trying push... 3"); -// console.log("Subscription", sub); -// }).catch(function (e) { -// // if ('Notification' in window && Notification.permission === 'denied') { -// // console.warn('Permission for notifications was denied'); -// // } else { -// // console.error('Unable to subscribe to push', e); -// // } -// }); -// }); +!function(t){"use strict";var e,n=Object.prototype,r=n.hasOwnProperty,i="function"==typeof Symbol?Symbol:{},o=i.iterator||"@@iterator",s=i.asyncIterator||"@@asyncIterator",a=i.toStringTag||"@@toStringTag",u="object"==typeof module,l=t.regeneratorRuntime;if(l)u&&(module.exports=l);else{(l=t.regeneratorRuntime=u?module.exports:{}).wrap=k;var c="suspendedStart",h="suspendedYield",f="executing",p="completed",d={},v={};v[o]=function(){return this};var m=Object.getPrototypeOf,y=m&&m(m(C([])));y&&y!==n&&r.call(y,o)&&(v=y);var g=x.prototype=_.prototype=Object.create(v);b.prototype=g.constructor=x,x.constructor=b,x[a]=b.displayName="GeneratorFunction",l.isGeneratorFunction=function(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===b||"GeneratorFunction"===(e.displayName||e.name))},l.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,x):(t.__proto__=x,a in t||(t[a]="GeneratorFunction")),t.prototype=Object.create(g),t},l.awrap=function(t){return{__await:t}},O(P.prototype),P.prototype[s]=function(){return this},l.AsyncIterator=P,l.async=function(t,e,n,r){var i=new P(k(t,e,n,r));return l.isGeneratorFunction(e)?i:i.next().then(function(t){return t.done?t.value:i.next()})},O(g),g[a]="Generator",g[o]=function(){return this},g.toString=function(){return"[object Generator]"},l.keys=function(t){var e=[];for(var n in t)e.push(n);return e.reverse(),function n(){for(;e.length;){var r=e.pop();if(r in t)return n.value=r,n.done=!1,n}return n.done=!0,n}},l.values=C,E.prototype={constructor:E,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=e,this.done=!1,this.delegate=null,this.method="next",this.arg=e,this.tryEntries.forEach(S),!t)for(var n in this)"t"===n.charAt(0)&&r.call(this,n)&&!isNaN(+n.slice(1))&&(this[n]=e)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var n=this;function i(r,i){return a.type="throw",a.arg=t,n.next=r,i&&(n.method="next",n.arg=e),!!i}for(var o=this.tryEntries.length-1;o>=0;--o){var s=this.tryEntries[o],a=s.completion;if("root"===s.tryLoc)return i("end");if(s.tryLoc<=this.prev){var u=r.call(s,"catchLoc"),l=r.call(s,"finallyLoc");if(u&&l){if(this.prev=0;--n){var i=this.tryEntries[n];if(i.tryLoc<=this.prev&&r.call(i,"finallyLoc")&&this.prev=0;--e){var n=this.tryEntries[e];if(n.finallyLoc===t)return this.complete(n.completion,n.afterLoc),S(n),d}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.tryLoc===t){var r=n.completion;if("throw"===r.type){var i=r.arg;S(n)}return i}}throw new Error("illegal catch attempt")},delegateYield:function(t,n,r){return this.delegate={iterator:C(t),resultName:n,nextLoc:r},"next"===this.method&&(this.arg=e),d}}}function k(t,e,n,r){var i=e&&e.prototype instanceof _?e:_,o=Object.create(i.prototype),s=new E(r||[]);return o._invoke=function(t,e,n){var r=c;return function(i,o){if(r===f)throw new Error("Generator is already running");if(r===p){if("throw"===i)throw o;return j()}for(n.method=i,n.arg=o;;){var s=n.delegate;if(s){var a=L(s,n);if(a){if(a===d)continue;return a}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(r===c)throw r=p,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);r=f;var u=w(t,e,n);if("normal"===u.type){if(r=n.done?p:h,u.arg===d)continue;return{value:u.arg,done:n.done}}"throw"===u.type&&(r=p,n.method="throw",n.arg=u.arg)}}}(t,n,s),o}function w(t,e,n){try{return{type:"normal",arg:t.call(e,n)}}catch(t){return{type:"throw",arg:t}}}function _(){}function b(){}function x(){}function O(t){["next","throw","return"].forEach(function(e){t[e]=function(t){return this._invoke(e,t)}})}function P(t){var e;this._invoke=function(n,i){function o(){return new Promise(function(e,o){!function e(n,i,o,s){var a=w(t[n],t,i);if("throw"!==a.type){var u=a.arg,l=u.value;return l&&"object"==typeof l&&r.call(l,"__await")?Promise.resolve(l.__await).then(function(t){e("next",t,o,s)},function(t){e("throw",t,o,s)}):Promise.resolve(l).then(function(t){u.value=t,o(u)},function(t){return e("throw",t,o,s)})}s(a.arg)}(n,i,e,o)})}return e=e?e.then(o,o):o()}}function L(t,n){var r=t.iterator[n.method];if(r===e){if(n.delegate=null,"throw"===n.method){if(t.iterator.return&&(n.method="return",n.arg=e,L(t,n),"throw"===n.method))return d;n.method="throw",n.arg=new TypeError("The iterator does not provide a 'throw' method")}return d}var i=w(r,t.iterator,n.arg);if("throw"===i.type)return n.method="throw",n.arg=i.arg,n.delegate=null,d;var o=i.arg;return o?o.done?(n[t.resultName]=o.value,n.next=t.nextLoc,"return"!==n.method&&(n.method="next",n.arg=e),n.delegate=null,d):o:(n.method="throw",n.arg=new TypeError("iterator result is not an object"),n.delegate=null,d)}function I(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function S(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function E(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(I,this),this.reset(!0)}function C(t){if(t){var n=t[o];if(n)return n.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var i=-1,s=function n(){for(;++i=1;i--){var o={};o[r[i]]=n,n=o}e=r[0]}var s=e;e=function(){window[s]=n}}t.h.push(e)}},{key:"u",value:function(){for(var e=0;e0){this.it.splice(e,1);for(var n=this.wt(t),r=0,i=n.length;r0){var t=arguments[0],n=Array.prototype.slice.call(arguments,1);return e.I(t)&&(0===n.length||e.re.apply(null,[t[n[0]]].concat(n.slice(1))))}return!1}},{key:"Mt",value:function(t){return null===t||void 0===t}},{key:"I",value:function(t){return!e.Mt(t)}},{key:"m",value:function(){for(var t=0;t0&&(o=new Array(r+1-s).join("0")+o),n+=o}return n}},{key:"ge",value:function(t,e){for(var n=Math.floor(Math.log(265)/Math.log(e)),r=t.match(new RegExp(".{1,"+n+"}","g"))||[],i="",o=0,s=r.length;o1&&0==(3&a)&&(a%100!=0||a%400==0)?1:0),3),"%k":""+u,"%l":(u+11)%12+1,"%m":p(s+1,2),"%M":p(n.getMinutes(),2),"%p":u<12?"AM":"PM","%P":u<12?"am":"pm","%s":Math.round(n.getTime()/1e3),"%S":p(n.getSeconds(),2),"%u":i||7,"%V":function(){var t=f(),e=t.valueOf();t.setMonth(0,1);var n=t.getDay();return 4!==n&&t.setMonth(0,1+(4-n+7)%7),p(1+Math.ceil((e-t)/6048e5),2)}(),"%w":""+i,"%x":n.toLocaleDateString(),"%X":n.toLocaleTimeString(),"%y":(""+a).slice(2),"%Y":a,"%z":n.toTimeString().replace(/.+GMT([+-]\d+).+/,"$1"),"%Z":n.toTimeString().replace(/.+\((.+?)\)$/,"$1")}[t]||t})}},{key:"Se",value:function(n){var r=void 0;if(e.Mt(n)||"object"!=(void 0===n?"undefined":t(n)))return n;if(n instanceof Array){var i=[];for(r=0;r",""":'"',"'":"'","’":"’","‘":"‘","–":"–","—":"—","…":"…","”":"”"};return e.I(t)&&"function"==typeof t.replace?t.replace(/\&[\w\d\#]{2,5}\;/g,function(t){return n[t]}):t}},{key:"Me",value:function(t){var e=new FormData;for(var n in t)e.set(n,t[n]);return e}},{key:"ye",value:function(t,n){var r=window.getComputedStyle(t),i=window.getComputedStyle(n);if(i.height>r.height||i.width>r.width)return e.He(t,n)}},{key:"He",value:function(t,n){e.ve(t);for(var r=window.getComputedStyle(t),i=window.getComputedStyle(n),o=0,s=parseFloat(i.getPropertyValue("font-size")),a=i.width,u=i.height;i.height>r.height||i.width>r.width;)if(s*=.95,u>r.height&&(u*=.95),a>i.width&&(a*=.95),n.style["font-size"]=s+"px",n.style["max-height"]=u+"px",n.style["max-width"]=a+"px",++o>2e3){console.log("breaked");break}e.Pe(n),i=window.getComputedStyle(n),n.style["font-size"]=parseFloat(i.getPropertyValue("font-size"))/parseFloat(document.documentElement.clientHeight)*100+"vh"}},{key:"ve",value:function(t){for(var n=t.childNodes,r=0,i=n.length;r-1,i=e.userAgent.indexOf("Edge")>-1;return!!e.userAgent.match("CriOS")||null!==t&&void 0!==t&&"Google Inc."===n&&!1===r&&!1===i}},{key:"Te",value:function(t,e){for(var n={},r=0,i=t.length;r0&&(n=r[0])}else-1!==t.De.indexOf(e)&&(n=e);if(v.I(n)){localStorage.setItem("currentTheme",n.Re);var i=new Promise(function(t){document.querySelector("nav.top-bar").addEventListener("transitionend",function(){t()})});document.body.className=n.Be,t.Ie=n;for(var o=0,s=t.Ue.length;o0?t.xe(n[0]):t.De.length>0&&t.xe(t.De[0])}}},{key:"Ee",value:function(){return new l(t.Ie.Re,function(e){var n=(t.De.indexOf(t.Ie)+1)%t.De.length;t.xe(t.De[n]),e.title=t.Ie.Re,e.H.j()},h.Y)}},{key:"addChangeListener",value:function(e){t.Ue.push(e)}},{key:"getCurrentTheme",value:function(){return t.Ie}}]),t}();y.Ie=null,y.De=[],y.Ue=[],u.l("ThemeManager",{addChangeListener:y.addChangeListener,getCurrentTheme:y.getCurrentTheme});var g=function(){function t(e){s(this,t),this._e=e,this.Oe=!0,this.je=3650,this.Ve="complianceCookie",this.Je="true"}return n(t,null,[{key:"Ne",value:function(){var e=r(regeneratorRuntime.mark(function e(n){return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",new t(n).Ne());case 1:case"end":return e.stop()}},e,this)}));return function(){return e.apply(this,arguments)}}()}]),n(t,[{key:"Ne",value:function(){var e=r(regeneratorRuntime.mark(function e(){return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",t.qe(this.Ve)!==this.Je?this.show():Promise.resolve());case 1:case"end":return e.stop()}},e,this)}));return function(){return e.apply(this,arguments)}}()},{key:"ze",value:function(){this.$e(this.Ve,this.Je,this.je)}},{key:"$e",value:function(t,e,n){var r=void 0;if(v.I(n)){var i=new Date;i.setTime(i.getTime()+24*n*60*60*1e3),r="; expires="+i.toGMTString()}else r="";this.Oe&&(document.cookie=t+"="+e+r+"; path=/")}},{key:"Ke",value:function(t){this.$e(t,"",-1)}},{key:"show",value:function(){var t=this,e=document.getElementById(this._e);return e.style.display="block",new Promise(function(n){e.querySelector("#close-cookie-msg").onclick=function(){t.ze(),e.remove(),n()}})}}],[{key:"qe",value:function(t){for(var e=t+"=",n=document.cookie.split(";"),r=0;r0||("smedium"===t||"small"===t)&&r.Ze(e.getElementsByClassName(h.S)).length>0||"small"===t&&r.Ze(e.getElementsByClassName(h.yt)).length>0||r.Ze(e.getElementsByClassName(h.tt)).length>0?document.getElementById("responsive-menu-toggle").style.display="block":(document.getElementById("responsive-menu-toggle").style.display="none",v.I(r.Ge)&&r.Ge.close())}},{key:"gt",value:function(){var t=e(r.prototype.__proto__||Object.getPrototypeOf(r.prototype),"gt",this).call(this);return function(e){t(e)instanceof c||!v.I(r.Ge)||r.Ge.close()}}},{key:"ht",value:function(t){var n=e(r.prototype.__proto__||Object.getPrototypeOf(r.prototype),"ht",this).call(this,t);return this.Xe(),r.Ge=this,n}},{key:"close",value:function(){document.getElementById("responsive-menu").style.display="none";for(var t=0,e=this.rt.length;t0;){var o=this.hs.firstChild;o.remove(),i.appendChild(o)}this.us={vn:i,title:document.title};var a=this;window.onpopstate=function(){if(a.ns.length>=1){var t=a.ns[a.ns.length-1].qn();!1!==t.En()&&a.Cn(t)}}}return n(t,[{key:"Hn",value:function(){return this.us}},{key:"cs",value:function(t){this.ls=t}},{key:"bn",value:function(){return this.ls}},{key:"ds",value:function(t){this.as.push(t)}},{key:"Dn",value:function(){return this.as}},{key:"ms",value:function(){return v.I(this.ss)?this.ss.qn():null}},{key:"gs",value:function(){var t=r(regeneratorRuntime.mark(function t(e){var n;return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:n=this.ns.length-1;case 1:if(!(n>=0)){t.next=9;break}return t.next=4,e(this.ns[n].qn());case 4:if(!t.sent){t.next=6;break}return t.abrupt("return",this.ns[n].qn());case 6:n--,t.next=1;break;case 9:return t.abrupt("return",null);case 10:case"end":return t.stop()}},t,this)}));return function(){return t.apply(this,arguments)}}()},{key:"Tn",value:function(){var t=r(regeneratorRuntime.mark(function t(e,n){var i,o,s,a,u=this;return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if(e.prototype instanceof b){t.next=2;break}throw{error:"wrong class given! Expected AbstractSite, given "+e.name};case 2:return i=new e(this),o={},s=new Promise(function(t,e){o.resolve=t,o.reject=e}),a=new x(i,o),t.abrupt("return",(this.es.removeAllChildren().appendChild(v.he()),this.os=Promise.resolve(n).then(function(){var t=r(regeneratorRuntime.mark(function t(e){return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return a.Yn(e),t.next=3,Promise.all([i.an(e),i.sn]);case 3:return i.wn=i.xn(u.ps()),t.abrupt("return",u.show(a));case 5:case"end":return t.stop()}},t,u)}));return function(){return t.apply(this,arguments)}}()).catch(function(t){console.error("site start error for site ",e.name,t)}),s));case 4:case"end":return t.stop()}},t,this)}));return function(){return t.apply(this,arguments)}}()},{key:"Cn",value:function(t,e){var n=this;this.os.then(function(){var r=n.fs(t),i=n.ns.splice(r,1),o=null;if((i=i[0])===n.ss){n.ss.qn().cn(),n.ss=null;var s=n.ns.length-1;if(s<0)return n.Ss(),void app.ws();n.es.removeAllChildren().appendChild(v.he()),o=n.ns[s]}i.qn().dn(),Promise.resolve(e).then(function(t){i.Zn().resolve(t),v.I(o)&&n.show(o)})})}},{key:"addListener",value:function(t,e,n,r){this.es.addEventListener(e,function(e){var i=e.target;t.pn&&i.matches(n)&&r(i,e)})}},{key:"_n",value:function(t,e,n,r,i){this.addListener(t,n,r,i),this.Nn(t,e,i)}},{key:"Nn",value:function(t,e,n){window.addEventListener("keydown",function(r){t.pn&&r.which===e&&n(this,r)})}},{key:"kn",value:function(t){var e=this.fs(t),n=this.ns.splice(e,1);n=n[0],this.show(n)}},{key:"Ms",value:function(){return this.show(this.ss)}},{key:"show",value:function(t){v.I(this.ss)&&(this.ss.Xn(this.ss.qn().cn()),this.ss.Kn(this.es.innerHTML)),this.es.removeAllChildren().appendChild(v.he());var e=this;return this.ss=t,-1===this.ns.indexOf(t)&&this.ns.push(t),t.qn().sn.then(function(n){return t.qn().wn.j(),e.es.removeAllChildren().appendChild(n),e.Pn(),d.Gt().Xt(),n}).then(function(n){t.qn().ln(t.Gn()),history.pushState({siteName:t.qn().constructor.name,siteData:n.outerHTML,stackPosition:e.ns.length-1},t.qn().constructor.name,t.qn().Wn())})}},{key:"Bn",value:function(t){if(v.I(this.ss)&&this.ss.qn()===t){history.replaceState({siteName:t.constructor.name,siteData:t.en.outerHTML,stackPosition:this.ns.length-1},t.constructor.name,t.Wn())}}},{key:"ms",value:function(){if(null!=this.ss)return this.ss.qn()}},{key:"ys",value:function(){null!=this.ss&&this.ss.qn().wn.j()}},{key:"Pn",value:function(){var t=this.ms().title;this.hs.removeAllChildren().appendChild(t.vn),document.title=v.m(t.title,this.us.title)}},{key:"fs",value:function(t){for(var e=0,n=this.ns.length;e=0&&(this.Cs[e].remove(!0),this.Cs.splice(e,1))}},{key:"Tn",value:function(t,e){return this.Ls.Tn(t,e)}},{key:"start",value:function(e){m.Ae(this.Ce);var n=v.m(this.js(),e),r=t.zs();this.xs=e,d.init(),y.init(),this.ks&&this.ds(y.Ee()),this.Ls=new O(this.bs,this.Ts),this.Ls.as=this.Cs,this.Ls.cs(e),this.Ls.Tn(n,r),this.Vs(),this.Fs&&(this.$s=g.Ne("cookie-compliance"))}},{key:"ms",value:function(){return this.Ls.ms()}},{key:"ws",value:function(){var t=r(regeneratorRuntime.mark(function t(){return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:"function"==typeof this.Ds&&this.Ds();case 1:case"end":return t.stop()}},t,this)}));return function(){return t.apply(this,arguments)}}()},{key:"setAppEndListener",value:function(t){this.Ds=t}},{key:"gs",value:function(){var t=r(regeneratorRuntime.mark(function t(e){return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.abrupt("return",this.Ls.gs(e));case 1:case"end":return t.stop()}},t,this)}));return function(){return t.apply(this,arguments)}}()}],[{key:"Js",value:function(t){if(v.Mt(t))return null;for(var e={},n=[],r=t.split("&"),i=0;i0&&(e[n[0]]=decodeURIComponent(n[1]));return e}},{key:"zs",value:function(){return t.Js(window.location.search.substr(1))}}]),t}(),I=function(){function t(e,n){s(this,t),this.Ks=null,this.content=null,this.Gs=null,this.cancelable=!0,this.title=v.m(n,""),this.Xs=!0,this.Qs="",this.buttons=[],this.result=null,v.I(e)&&this.Ys(e)}return n(t,[{key:"k",value:function(t){return this.title=t,this}},{key:"Zs",value:function(t){this.Xs=t}},{key:"ti",value:function(t){this.Qs=t}},{key:"R",value:function(){return this.title}},{key:"ei",value:function(t){return this.cancelable=!0===t,this}},{key:"Ys",value:function(){var t=r(regeneratorRuntime.mark(function t(e){return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return this.ni=Promise.resolve(e),t.next=3,this.ni;case 3:return this.content=t.sent,t.abrupt("return",this);case 5:case"end":return t.stop()}},t,this)}));return function(){return t.apply(this,arguments)}}()},{key:"si",value:function(t,e,n){n=v.m(n,!0);var r=null;"string"==typeof t?((r=document.createElement("button")).classList.add("button"),r.classList.add("right"),r.appendChild(d.pt(t))):r=t;var i=this;if("function"!=typeof e){var o=e;e=function(){i.result=o}}var s;s=n?function(t){v.I(e)&&e(t),i.close()}:e,v.I(s)&&r.addEventListener("click",s),this.buttons.push(r)}},{key:"show",value:function(){var t=r(regeneratorRuntime.mark(function t(){var e,n,r,i,o,s,a,u,l;return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:for((e=document.createElement("span")).classList.add("title"),this.Xs&&""!==this.title?e.appendChild(d.pt(this.title)):e.innerHTML=this.title,(n=document.createElement("div")).appendChild(e),(r=document.createElement("div")).classList.add("content-container"),(i=document.createElement("div")).className=this.Qs,i.classList.add("modal"),i.appendChild(n),i.appendChild(r),(o=document.createElement("div")).classList.add("modal-button-container"),s=0,a=this.buttons.length;s0&&e.ri(e.li,i),e.li++}}]),e}();E.li=0,E.hi=3500,E.ui=1e3,E.ai="success",E.ci="error",E.di="default",E.mi="info",E.gi="warning";var C=function(){function t(e,n){var i,o=this;s(this,t),this.pi=new Promise((i=r(regeneratorRuntime.mark(function t(r,i){var s,a;return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return s=null,s=window.sqlite?new Promise(function(t){!function e(){window.sqliteIndexedDB?t(window.sqliteIndexedDB):setTimeout(e,200),console.log("t")}()}):Promise.resolve(window.myIndexedDB||window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB||window.shimIndexedDB),console.log("indexeddb 1"),t.next=5,s;case 5:o.fi=t.sent,console.log("indexeddb 2"),o.Si=o.fi.open(e,n),a=o,o.Si.onupgradeneeded=function(t){try{a.wi(a.Si.result,t.oldVersion,t.newVersion,t)}catch(t){throw i(t),t}},a.Si.onsuccess=function(t){a.Dt=a.Si.result,r(t)};case 10:case"end":return t.stop()}},t,o)})),function(){return i.apply(this,arguments)}))}return n(t,[{key:"Mi",value:function(t,e,n){var r=this;return"function"==typeof e&&v.Mt(n)&&(n=e,e="read"),this.pi.then(function(){var i=null;try{i=r.Si.result.transaction(t,e)}catch(e){console.warn(e),i=r.Si.result.transaction(t)}n(i)})}},{key:"yi",value:function(t,e,n){return"function"==typeof e&&v.Mt(n)&&(n=e,e="readonly"),this.Mi(t,e,function(e){n(e.objectStore(t))})}},{key:"Hi",value:function(t,e){var n=this;return new Promise(function(r){n.yi(e,"readwrite",function(e){var n=e.put(t);n.onsuccess=r,n.onerror=function(t){throw{type:"indexed-db-error",event:t}}})})}},{key:"vi",value:function(t,e){var n=this;return new Promise(function(r){n.yi(e,"readwrite",function(e){for(var n=[],i=function(r,i){n.push(new Promise(function(n){var r=e.put(t[i]);r.onsuccess=n,r.onerror=function(t){throw{type:"indexed-db-error",event:t}}}))},o=0,s=t.length;o=0){var n=new I("optimistic-locking-dialog","optimistic-locking-dialog-title");n.ii(),n.show()}else t(e)}:t,this.lr=n}},{key:"ur",value:function(){if(!this.rr){var t=this;return this.submit().then(function(e){if(e.success){if(null!==t.ar)return t.ar(e.result)}else if(v.I(t.lr))return t.lr(e.errors)})}}},{key:"load",value:function(t,e){return this.dr(H.load(t,e).then(function(t){return t.success?t.result:{}})),this}},{key:"dr",value:function(t){this.mr(!0);var e=this;return Promise.resolve(t).then(function(t){for(var n in e.mr(!1),t)if(v.I(e.sr.elements[n])){if(v.I(e.sr.elements[n].options)&&v.I(t[n+"Options"])){var r=e.sr.elements[n].options;for(var i in t[n+"Options"]){var o=document.createElement("option");o.value=i,o.innerText=t[n+"Options"][i],r.add(o)}}e.sr.elements[n].value=v.we(t[n]),v.I(t[n])&&""!==(""+t[n]).trim()?e.sr.elements[n].classList.add("notEmpty"):e.sr.elements[n].classList.remove("notEmpty")}return e})}},{key:"hr",value:function(){var t=r(regeneratorRuntime.mark(function t(e){var n,r,i,o;return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:for(i in n=!1,r=null,e)v.I(this.sr.elements[i])&&"hidden"!==this.sr.elements[i].type&&v.Mt(this.sr.elements[i].gr)&&(v.Mt(this.sr.elements[i].disabled)||!this.sr.elements[i].disabled)&&(this.sr.elements[i].setCustomValidity(d.translate(v.m(e[i],"form-default-error"))),n=!0),v.Mt(r)&&(r=v.m(e[i],"form-default-error"));if(n||!v.I(r)){t.next=11;break}t.t0=regeneratorRuntime.keys(this.sr.elements);case 4:if((t.t1=t.t0()).done){t.next=11;break}if(o=t.t1.value,"hidden"===this.sr.elements[o].type){t.next=9;break}return this.sr.elements[o].setCustomValidity(d.translate(r)),n=!0,t.abrupt("break",11);case 9:t.next=4;break;case 11:n&&this.sr.querySelector("input[type=submit]").click();case 12:case"end":return t.stop()}},t,this)}));return function(){return t.apply(this,arguments)}}()},{key:"mr",value:function(t){this.rr=t,this.rr?this.sr.classList.add("sending"):this.sr.classList.remove("sending")}},{key:"submit",value:function(){var t=this;return new Promise(function(e){t.mr(!0);var n=new FormData(t.sr);e(t.or(n))}).then(function(e){return t.mr(!1),e})}},{key:"pr",value:function(t){this.ar=t}}]),t}(),U=function(){function t(){s(this,t),this.ke=null,this.wr="settings"}return n(t,null,[{key:"Gt",value:function(){return null===t.Sr&&(t.Sr=new t),t.Sr}}]),n(t,[{key:"Mr",value:function(){return v.Mt(this.ke)&&this.yr(),this.ke}},{key:"Hr",value:function(t,e){var n=this.Mr();return v.I(n[t])?n[t].value:e}},{key:"vr",value:function(t){this.Mr(),delete this.ke[t],this.Pr()}},{key:"Lr",value:function(t,e){this.Mr(),this.ke[t]={Tr:(new Date).getTime(),value:e},this.Pr()}},{key:"br",value:function(t){for(var e in this.Mr(),t)this.ke[e]=t[e];this.Pr()}},{key:"Ar",value:function(t){return v.m(this.ke[t])}},{key:"yr",value:function(){this.ke=localStorage.getItem(this.wr),null===this.ke?this.ke={}:this.ke=JSON.parse(this.ke)}},{key:"Pr",value:function(){null!==this.ke&&localStorage.setItem(this.wr,JSON.stringify(this.ke))}}]),t}();U.Sr=null;var V=function(){function t(){return s(this,t),i(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments))}return o(t,G),n(t,[{key:"hn",value:function(){for(var n=e(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"hn",this).call(this),r=this.gn(".setting",!0),i=U.Gt(),o=function(t){var e=r[t],n=e.name,o=void 0;o=e.dataset.raw?localStorage.getItem(n):i.Hr(n);var s=!1;e instanceof HTMLInputElement&&("checkbox"===e.type||"radio"===e.type)&&(s=!0),(!e.dataset.raw&&!i.Ar(n)||e.dataset.raw&&null===o)&&v.I(r[t].dataset.default)&&(o=e.dataset.default,v.I(e.dataset.defaultTranslateable)&&(e.dataset.translation="",e.dataset.translationValue=o,o=d.translate(o))),v.I(o)&&(s?e.checked=o===e.value:e.value=o,""!==o&&e.classList.add("notEmpty")),e.addEventListener("change",function(){var t=this.value;s&&!this.checked&&(t=null),e.dataset.raw?localStorage.setItem(n,t):i.Lr(n,t),delete e.dataset.translationValue,delete e.dataset.translation})},s=0;sn&&o.zr[n].click(e,i,t)}),this.list=i,i}},{key:"Gr",value:function(){for(var t=document.createElement("tr"),e=document.createElement("tr"),n=[],r=0,i=this.zr.length;r=1&&(n=this.$r(n),r[0].values(n))}},{key:"Yr",value:function(t){t?this.Vr.classList.add("sending"):this.Vr.classList.remove("sending")}}]),t}(),K=function(){function t(e){s(this,t);var n=i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,t.Zr,"settings"));for(var r in t.to)n.eo(r,new t.to[r](n));return n.active=null,n}return o(t,b),n(t,[{key:"eo",value:function(t,e){this.mn("#settings-fragments",e),delete this.rn["#settings-fragments"],this.rn[t]=e}},{key:"ln",value:function(){var n=e(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"ln",this).call(this);return v.I(this.active)&&!this.rn[this.active].un()&&this.setActive(null),this.no(),n}},{key:"setActive",value:function(t){v.I(this.active)&&(this.rn[this.active].sn.then(function(t){t.classList.remove("active")}),this.gn("#show-fragment-"+this.active).classList.remove("active")),this.active=t,v.I(this.active)&&(this.rn[this.active].sn.then(function(t){t.classList.add("active")}),this.gn("#show-fragment-"+this.active).classList.add("active"))}},{key:"no",value:function(){var t=this,e=this.gn("#settings-fragment-list");e.removeAllChildren();var n=this,r=function(r){if(t.rn[r].un()){var i=document.createElement("li");i.id="show-fragment-"+r,i.appendChild(d.pt(r,null,"a")),i.addEventListener("click",function(){n.setActive(r)}),e.appendChild(i),v.Mt(t.active)&&t.setActive(r)}};for(var i in this.rn)r(i)}}],[{key:"eo",value:function(e,n){t.to[e]=n}},{key:"so",value:function(e){t.io=e}},{key:"ro",value:function(e){t.Zr=e}}]),t}();K.Zr="core/html/settings.html",K.to={},K.io=!0,K.oo=null,K.ao=!0,a.t(function(t){var e=this;if(K.io){if(t.Ns("settings",K),v.Mt(K.oo)){var n=new l("settings",r(regeneratorRuntime.mark(function n(){var r,i;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(!((r=t.ms())instanceof K)){e.next=5;break}r.finish(),e.next=9;break;case 5:return e.next=7,t.gs(function(t){return t instanceof K});case 7:i=e.sent,v.I(i)?i.kn():t.Tn(K);case 9:case"end":return e.stop()}},n,e)})),l.Z,1e4);n.q("img/settings.png"),K.oo=n}K.ao&&t.ds(K.oo)}});var $=function(){function t(){s(this,t)}return n(t,null,[{key:"init",value:function(e){t.lo=null,t.ho={uo:!1,id:null,accesses:["default"]},t.app=e,t.co=new Promise(function(e){t.do=e})}},{key:"setData",value:function(e){t.ho=Object.assign(t.ho,e);var n=t.app.Rs();n&&n.ys()}},{key:"mo",value:function(e){return t.lo=v.m(e,t.lo),H.load(t.lo).then(function(e){e.success&&t.setData(e.result),t.do()})}},{key:"po",value:function(){return H.load("u/logout").then(function(e){if(e.success){t.setData(e.result);var n=t.app.Rs();n&&n.Ms(),E.oi(E.ai,d.translate("logged-out-successfully"))}})}},{key:"fo",value:function(e){return t.ho.accesses.indexOf(e)>=0}},{key:"So",value:function(e,n){t.wo(function(r){n(r&&t.Mo(e))})}},{key:"wo",value:function(e){this.co.then(function(){e(t.yo())})}},{key:"Mo",value:function(e){return t.ho.id===e}},{key:"yo",value:function(){return v.I(t.ho)&&v.I(t.ho.id)}}]),t}();a.t(function(t){return $.init(t),$.mo("u/me").then(function(){$.wo(function(t){if(t){var e=U.Gt(),n=v.Se(e.Mr());for(var r in n)n[r].value=JSON.stringify(n[r].value);H.send("u/syncSettings",n).then(function(t){if(t.success){for(var n in t.result)t.result[n].value=JSON.parse(t.result[n].value);e.br(t.result)}})}})})});var Q=function(){function t(e,n,r,o,a){var u;return s(this,t),(u=i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,n,r,o))).Ho=v.m(a,"default"),u}return o(t,l),n(t,[{key:"_",value:function(){return e(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"_",this).call(this)&&$.fo(this.Ho)}},{key:"vo",value:function(){return this.Ho}},{key:"G",value:function(n){var r=e(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"G",this).call(this,v.m(n,new t));return r.Ho=this.Ho,r}}]),t}(),Z=function(){function t(e){return s(this,t),i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,"userManagement/html/403.html"))}return o(t,b),t}(),tt=function(){function t(e,n,r,o){var a;return s(this,t),(a=i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,n,r))).Ho=o,a}return o(t,b),n(t,[{key:"an",value:function(n){return $.fo(this.Ho)?e(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"an",this).call(this,n):(this.Tn(Z),void this.finish({error:403}))}},{key:"ln",value:function(n){return $.fo(this.Ho)?e(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"ln",this).call(this,n):(this.Tn(Z),void this.finish({error:403}))}}]),t}(),et=function(){function t(e,n,r,o){s(this,t);var a=i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,n,r,o)),u=e.querySelector("#email"),l=e.querySelector("#password"),c=function(){u.setCustomValidity(""),l.setCustomValidity("")};return u.addEventListener("keydown",c),l.addEventListener("keydown",c),a}return o(t,B),t}(),nt=function(){function t(e,n,r,o){return s(this,t),i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,n,r,o))}return o(t,B),n(t,[{key:"Po",value:function(){}}]),t}(),rt=function(){function t(e,n,r){var o;return s(this,t),(o=i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,n))).Ho=r,o}return o(t,G),n(t,[{key:"un",value:function(){return e(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"un",this).call(this)&&$.fo(this.Ho)}}]),t}(),it=function(){function t(e){return s(this,t),i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,"userManagement/html/fragments/passwordSettings.html","online"))}return o(t,rt),n(t,[{key:"hn",value:function(){var n=e(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"hn",this).call(this),r=new B(document.getElementById("change-password-form"),"u/passwordSettings/set","post");return r.pr(function(t){for(var e=0,n=t.length;e0,!t.t0){t.next=8;break}return t.next=8,new Promise(function(t){setTimeout(t,u),n.style.fontSize=c+"px"});case 8:return h=this,f=function(){return new Promise(function(t){setTimeout(function(){t(h.Xo(e,n,r,i,o,s,a,u,!1))},"number"==typeof l?l:255)})},t.abrupt("return",(!1!==l&&window.addEventListener("resize",f),f));case 10:case"end":return t.stop()}},t,this)}));return function(){return t.apply(this,arguments)}}()},{key:"Yo",value:function(){var t=r(regeneratorRuntime.mark(function t(e,n,r,i,o,s,a,u){return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.abrupt("return",this.Xo(1,e,n,r,i,o,s,a,u));case 1:case"end":return t.stop()}},t,this)}));return function(){return t.apply(this,arguments)}}()},{key:"Qo",value:function(){var t=r(regeneratorRuntime.mark(function t(e,n,r,i,o,s,a,u){var l,c,h,f,p,d,m,y,g,k,w,_;return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:for(s=v.m(s,10),i=v.m(i,!1),o=v.m(o,!1),a=v.m(a,n.innerHTML.length),u=v.m(u,!0),(l=r.classList.contains("no-transition"))||r.classList.add("no-transition"),c=0,h=[],f=0;f<5;f++)h.push(0);p=n.style.fontSize,d=1,m=0,y=0,g=0,k=0;case 6:if(d+=h[c]/(a+1),n.style.fontSize=d+"px",w=window.getComputedStyle(r),g=w.getPropertyValue("width").replace("px",""),k=w.getPropertyValue("height").replace("px",""),m=g-n.offsetWidth,y=k-n.offsetHeight,c=(c+1)%5,(_=o?y:i?m:Math.min(m,y))!==h[(c+1)%5]){t.next=12;break}return t.abrupt("break",14);case 12:h[c]=_;case 13:if((m>(1-e)*g||o)&&(y>(1-e)*k||i)){t.next=6;break}case 14:if(d-=s,n.style.fontSize=u?d+"px":p,t.t0=l,t.t0){t.next=21;break}return t.next=20,new Promise(function(t){setTimeout(t,50)});case 20:r.classList.remove("no-transition");case 21:return t.abrupt("return",d);case 22:case"end":return t.stop()}},t,this)}));return function(){return t.apply(this,arguments)}}()}]),t}(),mt=function(){function t(e,n,r){s(this,t),this.buffer=n,this.Zo=!1,this.loopStart=null,this.loopEnd=null,this.ta=r,this.context=e,this.startTime=null,this.ea=null,this.source=null,this.na=!1}return n(t,[{key:"sa",value:function(t){this.buffer=t}},{key:"ia",value:function(t,e,n){this.Zo=t,v.I(e)&&(this.loopStart=e),v.I(n)&&(this.loopEnd=n)}},{key:"start",value:function(){var t=r(regeneratorRuntime.mark(function t(e,n,r){var i;return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return e=v.m(e,0),n=v.m(n,0),(i=this.context.createBufferSource()).loop=this.Zo,v.I(this.loopStart)&&(i.loopStart=this.loopStart),v.I(this.loopEnd)&&(i.loopEnd=this.loopEnd),i.buffer=this.buffer,t.next=8,this.ta(i);case 8:v.Mt(r)?i.start(e,n):i.start(e,n,r),this.startTime=(new Date).getTime()-1e3*v.m(n,0),this.source=i,this.na=!0;case 12:case"end":return t.stop()}},t,this)}));return function(){return t.apply(this,arguments)}}()},{key:"stop",value:function(){var t=r(regeneratorRuntime.mark(function t(e){return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.abrupt("return",v.I(this.source)?(e=v.m(e,0),this.ea=(new Date).getTime()-this.startTime,this.na=!1,this.source.stop(e)):null);case 1:case"end":return t.stop()}},t,this)}));return function(){return t.apply(this,arguments)}}()},{key:"resume",value:function(){var t=r(regeneratorRuntime.mark(function t(){return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if(this.na){t.next=2;break}return t.abrupt("return",this.start(null,v.m(this.ea,0)/1e3));case 2:case"end":return t.stop()}},t,this)}));return function(){return t.apply(this,arguments)}}()}]),t}(),yt=function(){function e(){var t=this;s(this,e),this.ra={},this.context=new AudioContext,this.context.onstatechange=function(){console.log("stateChange from context",arguments)},this.context.oncomplete=function(){console.log("onComplete from context",arguments)},window.addEventListener("visibilitychange",function(){t.oa()})}return n(e,null,[{key:"Gt",value:function(){return v.Mt(e.te)&&(e.te=new e),e.te}}]),n(e,[{key:"aa",value:function(){return"suspended"!==this.context.state}},{key:"set",value:function(t,n){var r=this;n=v.m(n,e.ha.la);var i=v.m(this.ra[n],{});"string"==typeof t&&(t={ua:t});var o=t.ua;return v.I(o)&&(i.ca=fetch(o).then(function(t){return t.arrayBuffer()}).then(function(t){return new Promise(function(e){return r.context.decodeAudioData(t,e)})}).catch(function(t){return console.error(t)}),this.stop(n)),i.muted=v.m(t.muted,i.muted,!1),i.volume=v.m(t.volume,i.volume,1),i.loop=v.m(t.loop,i.loop,!1),i.da=v.m(t.da,i.da,0),this.ra[n]=i,i.muted&&this.stop(n),this.ra[n]}},{key:"ma",value:function(){var t=r(regeneratorRuntime.mark(function t(){return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if("function"!=typeof this.context.resume){t.next=2;break}return t.abrupt("return",this.context.resume());case 2:case"end":return t.stop()}},t,this)}));return function(){return t.apply(this,arguments)}}()},{key:"play",value:function(){var n=r(regeneratorRuntime.mark(function n(r,i){var o,s,a=this;return regeneratorRuntime.wrap(function(n){for(;;)switch(n.prev=n.next){case 0:if(this.ma(),r=v.m(r,e.ha.la),v.Mt(i)?i={}:"object"!=(void 0===i?"undefined":t(i))&&(i={ua:i}),i.da=v.m(i.da,0),this.stop(r),this.set(i,r),this.ra[r].muted){n.next=10;break}return n.next=3,this.ra[r].ca;case 3:return o=n.sent,(s=new mt(this.context,o,function(t){var e=a.context.createGain();e.gain.value=a.ra[r].volume,t.connect(e),e.connect(a.context.destination)})).sa(o),s.ia(this.ra[r].loop,.3,o.duration-.3),this.ra[r].source=s,n.next=10,s.start();case 10:return n.abrupt("return",this.ra[r]);case 11:case"end":return n.stop()}},n,this)}));return function(){return n.apply(this,arguments)}}()},{key:"stop",value:function(t){t=v.m(t,e.ha.la);var n=this.ra[t];v.I(n)&&v.I(n.source)&&n.source.stop()}},{key:"get",value:function(t){return t=v.m(t,e.ha.la),this.ra[t]}},{key:"resume",value:function(){var t=r(regeneratorRuntime.mark(function t(n){return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if(n=v.m(n,e.ha.la),!v.I(this.ra[n])||this.ra[n].muted||!v.I(this.ra[n].source)){t.next=2;break}return t.abrupt("return",this.ra[n].source.resume());case 2:case"end":return t.stop()}},t,this)}));return function(){return t.apply(this,arguments)}}()},{key:"ga",value:function(){for(var t in this.ra)v.I(this.ra[t].source)&&this.ra[t].source.stop()}},{key:"pa",value:function(){for(var t in this.ra)v.I(this.ra[t])&&!this.ra[t].muted&&v.I(this.ra[t].source)&&this.ra[t].source.resume()}},{key:"oa",value:function(){document.hidden?this.ga():this.pa()}}]),e}();yt.ha={fa:"music",Sa:"sound",la:"default"},a.t(function(){P.Ps.push(function(){yt.Gt().ga()}),P.vs.push(function(){yt.Gt().pa()})});var gt=function(){function t(e){s(this,t),"string"==typeof e&&(e={code:e}),this.wa=e,this.Ma=!1}return n(t,[{key:"ya",value:function(t){this.Ma=t}},{key:"Ha",value:function(){return this.Ma}},{key:"va",value:function(){return H.send("c/code",this.wa)}}]),t}(),kt=function(){function t(e){return s(this,t),i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,"core/html/load.html","code"))}return o(t,b),n(t,[{key:"an",value:function(n){e(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"an",this).call(this,n),console.log(n);Promise.resolve();if(v.I(n.code)){var r=n.code,i=v.m(n.cachable,!1),o=new gt(r);o.ya(i);var s=this;o.va().then(function(t){t.success?E.oi(E.ai,d.translate(v.m(t.result.successMessage,"code-activated"))):E.oi(E.ai,d.translate(t.errors[0])),s.finish()})}}}]),t}();a.t(function(t){t.Ns("code",kt)});var wt=function(){function t(e){return s(this,t),i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,"contact/html/contact.html",t.Pa))}return o(t,b),n(t,[{key:"hn",value:function(){var n=this;new B(this.gn("#contact-form"),"contact","post").pr(function(){E.oi("contact-message-sent"),n.finish()}),e(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"hn",this).call(this)}}]),t}();wt.Pa="contactMe",a.t(function(t){wt.Pa&&t.Ns(wt.Pa,wt)});var _t=function(){function t(){return s(this,t),i(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments))}return o(t,b),t}(),bt=function(){function t(e,n,r,i,o){s(this,t),this.La=e,this.Ta=n,this.ba=r,this.Aa=i,this.Ca=o}return n(t,[{key:"ka",value:function(){return v.cloneNode(this.La)}},{key:"Fa",value:function(){return v.cloneNode(this.Ta)}},{key:"xa",value:function(){return v.cloneNode(this.ba)}},{key:"Da",value:function(){return v.cloneNode(this.Aa)}},{key:"Ra",value:function(){return v.cloneNode(this.Ca)}}]),t}(),xt=function(){function t(e){s(this,t),this.rotation=0,this.vn=e,this.parent=null}return n(t,[{key:"Ba",value:function(t){return t}},{key:"Ia",value:function(){return!1}},{key:"Ua",value:function(t){this.parent=t}},{key:"Wa",value:function(){if(null!==this.parent)return this.parent.Wa()}},{key:"Ea",value:function(){return!1}},{key:"Na",value:function(){return 0===this.rotation}},{key:"rotate",value:function(){var t=r(regeneratorRuntime.mark(function t(){return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.abrupt("return",Promise.resolve());case 1:case"end":return t.stop()}},t,this)}));return function(){return t.apply(this,arguments)}}()},{key:"_a",value:function(){}},{key:"Oa",value:function(t){return t}},{key:"ja",value:function(t){return t}},{key:"Va",value:function(t){return t}},{key:"Ja",value:function(){return this.vn}}]),t}(),Ot=function(){function t(e,n){var r;return s(this,t),(r=i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e))).qa="A",v.I(n)&&r.za(n),r}return o(t,xt),n(t,[{key:"Ia",value:function(e){return e instanceof t&&e.qa===this.qa}},{key:"za",value:function(t){this.qa=t}},{key:"_a",value:function(){this.vn.querySelector(".leaf-element").removeAllChildren().appendChild(document.createTextNode(this.qa))}}]),t}(),Pt=function(){function t(e){var n;s(this,t),(n=i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e))).children=[],n.Ya="rotate-0",n.Qa=!0,n.Za=100,n.tl=0;var r=n;return n.el=function(e){var n=(new Date).getTime(),i=null,o=null;if(e.changedTouches.length>=1&&(i=document.elementFromPoint(e.changedTouches[0].pageX,e.changedTouches[0].pageY),o={x:e.changedTouches[0].pageX,y:e.changedTouches[0].pageY}),null!=i&&0===e.targetTouches.length&&r.vn.contains(t.Ka)&&r.vn.contains(i)){if(e.stopPropagation(),e.preventDefault(),r.tl+r.Za>n)return;r.Wa().nl(r),r.rotate(t.Ka,i,t.Ga,o),r.tl=(new Date).getTime()}},n.sl=function(e){var n=(new Date).getTime();if(null!==t.Ka&&r.vn.contains(t.Ka)&&r.vn.contains(e.target)){var i={x:e.pageX,y:e.pageY};if(e.stopPropagation(),e.preventDefault(),r.tl+r.Za>n)return;r.Wa().nl(r),r.rotate(t.Ka,e.target,t.Ga,i),r.tl=(new Date).getTime()}},n}return o(t,xt),n(t,[{key:"Xa",value:function(t){this.Qa=t,this._a()}}],[{key:"$a",value:function(){window.addEventListener("mousedown",function(e){t.Ka=e.target,t.Ga={x:e.pageX,y:e.pageY}}),window.addEventListener("mouseup",function(){t.Ka=null,t.Ga={}}),window.addEventListener("touchstart",function(e){1===e.targetTouches.length&&(t.Ka=e.targetTouches[0].target,t.Ga={x:e.targetTouches[0].pageX,y:e.targetTouches[0].pageY})}),window.addEventListener("touchend",function(){t.Ka=null,t.Ga={}})}}]),n(t,[{key:"Ea",value:function(){return this.Qa&&!this.Wa().il()}},{key:"rotate",value:function(){var t=r(regeneratorRuntime.mark(function t(e,n,r,i){var o,s,a,u,l,c,h,f=this;return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if(o=1,v.I(n)&&v.I(e)&&(v.Mt(r)||v.Mt(i)||Math.abs(r.x-i.x)>5||Math.abs(r.y-i.y)>5)){for(s=-1,a=-1,u=[0,1,3,2],l=0;l=0&&a>=0&&(2===s&&(0===a||1===a)||1===s&&(0===a||3===a)||0===s&&3===a||3===s&&2===a)&&(o=-1)}if(!this.Ea()){t.next=8;break}return this.rotation+=360+90*o,this.rotation%=360,c=this.rotation,this.rl(),this.vn.classList.add("rotating"),-1===o&&this.vn.classList.add("reverse"),h=new Promise(function(t){setTimeout(t,250)}).then(function(){f.rotation===c&&(f.vn.classList.remove("rotating"),f.vn.classList.remove("reverse"))}),t.abrupt("return",(this.Wa().ol(h),h));case 8:case"end":return t.stop()}},t,this)}));return function(){return t.apply(this,arguments)}}()},{key:"Ia",value:function(e){if(!(e instanceof t)||e.children.length!==this.children.length)return!1;for(var n=0;n=2&&this.vn.classList.add("layer-"+t),this.Qa||this.vn.classList.add("locked");var e=this.vn.querySelector(".child-container");e.removeAllChildren(),this.rl(),this.vn.removeEventListener("mouseup",this.sl),this.vn.removeEventListener("touchend",this.el),this.vn.addEventListener("mouseup",this.sl),this.vn.addEventListener("touchend",this.el);for(var n=0,r=this.children.length;n=1&&this.children[0]&&this.children[0]instanceof t?this.children[0].hl()+1:1}}]),t}();Pt.$a();var Lt=function(){function t(e){s(this,t),this.ul=null,this.words=[],this.cl=[],this.dl=e,this.ml=!1,this.id=null,this.gl=null,this.pl=null;var n=this;this.fl=new Promise(function(t,e){n.gl=t,n.pl=e}),this.nl=function(){}}return n(t,[{key:"Sl",value:function(){var t=this.Ba(),e=this.Va();localStorage.setItem("currentLevel",JSON.stringify({id:this.id,rotations:t,locks:e}))}},{key:"Va",value:function(){return null!==this.ul?this.ul.Va([]):[]}},{key:"Ba",value:function(){return null!==this.ul?this.ul.Ba([]):[]}},{key:"wl",value:function(t){null!==this.ul&&this.ul.ja(t)}},{key:"Ml",value:function(t){this.id=t}},{key:"$",value:function(){return this.id}},{key:"Wa",value:function(){return this}},{key:"yl",value:function(t){this.ul=t,this.ul.Ua(this),this.cl&&this.Oa()}},{key:"Hl",value:function(t){this.words=[];for(var e=0,n=t.length;e=2&&this.words[0].length>=this.Fl&&this.words[1].length>=this.Fl){for(var t=Lt.kl(this.words[0],this.dl.ka()),e=Lt.kl(this.words[1],this.dl.ka()),n=new It(this.dl.xa()),r=0,i=this.Fl/2;r=6&&this.words[0].length>=this.Fl&&this.words[1].length>=this.Fl&&this.words[2].length>=this.Fl&&this.words[3].length>=this.Fl&&this.words[4].length>=this.Fl&&this.words[5].length>=this.Fl){var t=[];t[0]=Lt.kl(this.words[0],this.dl.ka()),t[1]=Lt.kl(this.words[1],this.dl.ka()),t[2]=Lt.kl(this.words[2],this.dl.ka()),t[3]=Lt.kl(this.words[3],this.dl.ka()),t[4]=Lt.kl(this.words[4],this.dl.ka()),t[5]=Lt.kl(this.words[5],this.dl.ka());for(var e=new It(this.dl.xa()),n=0;n=4&&this.words[0].length>=this.Fl&&this.words[1].length>=this.Fl&&this.words[2].length>=this.Fl&&this.words[3].length>=this.Fl){var t=[];t[0]=Lt.kl(this.words[0],this.dl.ka()),t[1]=Lt.kl(this.words[1],this.dl.ka()),t[2]=Lt.kl(this.words[2],this.dl.ka()),t[3]=Lt.kl(this.words[3],this.dl.ka());for(var e=new It(this.dl.xa()),n=0;n=4&&this.words[0].length>=this.Fl&&this.words[1].length>=this.Fl&&this.words[2].length>=this.Fl&&this.words[3].length>=this.Fl&&this.Fl>=4){var t=[];t[0]=Lt.kl(this.words[0],this.dl.ka()),t[1]=Lt.kl(this.words[1],this.dl.ka()),t[2]=Lt.kl(this.words[2],this.dl.ka()),t[3]=Lt.kl(this.words[3],this.dl.ka());for(var e=new It(this.dl.xa()),n=0;n=1)&&e.createObjectStore(t.Ul.Il,{keyPath:"id"}),(v.Mt(n)||n<2&&r>=2)&&i.target.transaction.objectStore(t.Ul.Il).createIndex("played",["deleted","played","difficulty","id"],{unique:!1}),(v.Mt(n)||n<3&&r>=3)&&i.target.transaction.objectStore(t.Ul.Il).createIndex("difficulty","difficulty",{unique:!1}),console.log("update",n,r),v.Mt(n)||n<6&&r>=6){try{e.deleteObjectStore(t.Ul.Wl)}catch(i){}e.createObjectStore(t.Ul.Wl,{keyPath:"name"})}}},{key:"El",value:function(){var e=r(regeneratorRuntime.mark(function e(n){return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",this.vi(n,t.Ul.Il).catch(function(t){console.error("insert error!",t)}));case 1:case"end":return e.stop()}},e,this)}));return function(){return e.apply(this,arguments)}}()},{key:"Nl",value:function(){var e=r(regeneratorRuntime.mark(function e(n){return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.abrupt("return",this.load(n,t.Ul.Il));case 1:case"end":return e.stop()}},e,this)}));return function(){return e.apply(this,arguments)}}()},{key:"_l",value:function(){var e=r(regeneratorRuntime.mark(function e(n){var r,i,o,s,a,u;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,this.Pi(t.Ul.Il);case 2:for(r=e.sent,i=[],o=[],s=-1,a=0,u=(r=r.sort(function(t,e){return t.difficulty-e.difficulty})).length;a=t){e-=t,localStorage.setItem("coins",e),this.Jl.title=e,this.Jl.j();for(var n=this.level.bl(),r=(n=n.filter(function(t){return!t.Na(!1)}))[Math.floor(Math.random()*n.length)];0!==r.rotation;)r.rotate();r.Xa(!1),this.level.Sl(),pt.push(["trackEvent","LevelSite","Help","Coins",parseInt(v.m(localStorage.getItem("coins"),"0"))])}else E.oi("not-enough-coins"),pt.push(["trackEvent","LevelSite","Help","Not enough Coins",parseInt(v.m(localStorage.getItem("coins"),"0"))])}},{key:"hh",value:function(){var e=r(regeneratorRuntime.mark(function e(){var n,r,i,o,s,a,u,l,c,h,f,p,d,m=this;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(this.level.id!==t.gh.mh){e.next=20;break}n=v.m(localStorage.getItem("tutorial-step"),"1"),r=new vt,e.t0=(this.en.classList.add("tutorial"),this.en.classList.add("step-"+n),n),e.next="1"===e.t0?5:"2"===e.t0?11:17;break;case 5:return this.level.Cl(function(){m.en.classList.remove("step-1"),localStorage.setItem("tutorial-step","2"),m.hh()}),i=this.gn(".tutorial-text .step-1"),e.next=9,this.zl();case 9:return r.Yo(i,i.parentElement,null,!0,1,2),e.abrupt("break",18);case 11:return this.level.Cl(function(){}),this.level.Pl().then(function(){m.en.classList.remove("tutorial"),m.en.classList.remove("step-2"),localStorage.removeItem("tutorial-step"),m.Xl=m.Xl.then(function(){E.oi("extra-coins-after-first-level"),localStorage.setItem("coins",parseInt(v.m(localStorage.getItem("coins"),"0"))+50),m.Jl.k(v.m(localStorage.getItem("coins"),"0")),m.Jl.j()})}),o=this.gn(".tutorial-text .step-2"),e.next=15,this.zl();case 15:return r.Yo(o,o.parentElement,null,!0,1,2),e.abrupt("break",18);case 17:this.en.classList.remove("tutorial");case 18:e.next=54;break;case 20:if(this.level.id!==t.gh.ph){e.next=37;break}s=v.m(localStorage.getItem("tutorial-step"),"3"),e.t1=s,e.next="3"===e.t1?25:34;break;case 25:return a=new vt,this.en.classList.add("tutorial"),this.en.classList.add("step-"+s),u=function t(){m.en.classList.remove("tutorial"),m.en.classList.remove("step-3"),localStorage.setItem("tutorial-step","4"),m.gn("#help-button").removeEventListener("click",t),m.zl()},this.gn("#help-button").addEventListener("click",u),l=this.gn(".tutorial-text .step-3"),e.next=32,this.zl();case 32:return a.Yo(l,l.parentElement,null,!0,1,2),e.abrupt("break",35);case 34:this.en.classList.remove("tutorial");case 35:e.next=54;break;case 37:if(this.level.id!==t.gh.fh){e.next=54;break}c=v.m(localStorage.getItem("tutorial-step"),"4"),e.t2=c,e.next="4"===e.t2?42:53;break;case 42:return h=new vt,this.en.classList.add("tutorial"),this.en.classList.add("step-"+c),f=this.level.bl()[2],console.log(f),(p=this.gn("#tutorial-pointer")).remove(),f.vn.appendChild(p),this.level.Cl(function(t){console.log("clicked Segment",t),f===t&&(m.en.classList.remove("tutorial"),m.en.classList.remove("step-4"),localStorage.setItem("tutorial-step","5"),m.zl())}),d=this.gn(".tutorial-text .step-4"),e.next=51,this.zl();case 51:return h.Yo(d,d.parentElement,null,!0,1,2),e.abrupt("break",54);case 53:this.en.classList.remove("tutorial");case 54:case"end":return e.stop()}},e,this)}));return function(){return e.apply(this,arguments)}}()}]),t}();Jt.dh=[20,40,60,80,81,82,83,100,120,140,160],Jt.gh={mh:67,ph:15,fh:1921};var Xt=function(){function t(e){return s(this,t),i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,4))}return o(t,Nt),n(t,[{key:"Sl",value:function(){}}]),t}(),Kt=function(){function t(){var e;return s(this,t),e=i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,w.tn("html/application/dialog/share.html").then(function(t){t.appendChild(M.ji(window.location.hostname+v.Kt("")));var n=function(){e.close()};return t.querySelectorAll("a").forEach(function(t){t.addEventListener("click",n)}),t}),"share-dialog"))}return o(t,I),t}(),$t=function(){function t(e){var n;return s(this,t),(n=i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,"html/application/menu.html"))).Sh=n.wh(),n.listener=null,n}return o(t,_t),n(t,[{key:"ln",value:function(n){var i=this;pt.update("Menu Site");var o=e(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"ln",this).call(this,n),s=new Xt(this.dl);s.Hl(["WORD","ROTA","TORW","ORDR"]),s.Tl(),s.Pl().then(function(){pt.push(["trackEvent","MainMenu","levelSolved"]),i.Mh()});var a=s.Ll();a._a(),this.gn("#level").removeAllChildren().appendChild(a.Ja());var u=s.bl();(function t(){var e=4500*Math.random()+1500;i.yh=setTimeout(function(){for(var e=-1,n=[],r=0;r=2));r++);1===n.length&&(e=n[0]);var i=Math.floor(Math.random()*u.length);i===e&&(i=(i+1)%u.length),u[i].rotate(),t()},e)})(),this.listener=r(regeneratorRuntime.mark(function t(){var e,n,r,o,s;return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return e=i.gn("#play-button"),(n=i.gn("#level-number")).innerText=v.m(localStorage.getItem("levelCounter"),1),r=i.gn("#level"),o=new vt,t.next=5,o.Yo(r,r.parentElement,!1,!1,2,8,null,!1);case 5:return s=getComputedStyle(r),e.style.width=s.getPropertyValue("width"),o.Yo(e.children[0],e,null,null,null,4,null,!1),t.next=10,o.Xo(.2,n.parentElement,n.parentElement.parentElement,null,null,null,10,null,!1);case 10:o.Yo(n,n.parentElement,!1,!1,8,null,null,!1);case 11:case"end":return t.stop()}},t,i)})),this.listener(),window.addEventListener("resize",this.listener);var l=U.Gt();return this.gn("#play-sound").checked="1"===l.Hr("play-sound","1"),this.gn("#play-music").checked="1"===l.Hr("play-music","1"),o}},{key:"Mh",value:function(){var t=r(regeneratorRuntime.mark(function t(){var e=this;return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:yt.Gt().ma(),this.Tn(Jt,Promise.race([this.Sh,new Promise(function(){var t=r(regeneratorRuntime.mark(function t(n){var r;return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,Yt.Gt();case 2:return r=t.sent,t.next=5,r._l(Jt.dh);case 5:if(t.t0=t.sent,t.t1=null!==t.t0,!t.t1){t.next=9;break}n();case 9:case"end":return t.stop()}},t,e)}));return function(){return t.apply(this,arguments)}}())]));case 1:case"end":return t.stop()}},t,this)}));return function(){return t.apply(this,arguments)}}()},{key:"hn",value:function(){var n=r(regeneratorRuntime.mark(function n(){var r,i,o,s,a,u,l,c,h=this;return regeneratorRuntime.wrap(function(n){for(;;)switch(n.prev=n.next){case 0:e(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"hn",this).call(this),this.gn("#play-button").addEventListener("click",function(){pt.push(["trackEvent","MainMenu","startButton"]),h.Mh()}),r=this.gn("#segment-leaf-template"),i=this.gn("#segment-parent-template"),o=this.gn("#segment-row-template"),s=this.gn("#segment-triangle-template"),r.id=null,i.id=null,o.id=null,s.id=null,r.remove(),i.remove(),o.remove(),s.remove(),this.dl=new bt(r,i,o,s),v.m(t.app.$s)&&t.app.$s.then(function(){h.listener&&h.listener()}),a=U.Gt(),u=yt.Gt(),(l=this.gn("#play-music")).checked="1"===a.Hr("play-music","1"),l.addEventListener("change",function(){a.Lr("play-music",l.checked?"1":"0"),u.set({muted:!l.checked},yt.ha.fa),l.checked&&u.play(yt.ha.fa),pt.push(["trackEvent","MainMenu","PlayMusic","Play Music",l.checked?1:0])}),(c=this.gn("#play-sound")).checked="1"===a.Hr("play-sound","1"),c.addEventListener("change",function(){a.Lr("play-sound",c.checked?"1":"0"),u.set({muted:!c.checked},yt.ha.Sa),pt.push(["trackEvent","MainMenu","PlaySound","Play Sound",c.checked?1:0])}),this.gn("#share-button").addEventListener("click",function(){(new Kt).show()});case 7:case"end":return n.stop()}},n,this)}));return function(){return n.apply(this,arguments)}}()},{key:"cn",value:function(n){clearTimeout(this.yh),window.removeEventListener("resize",this.listener),e(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"cn",this).call(this,n)}},{key:"wh",value:function(){var t=r(regeneratorRuntime.mark(function t(){var e,n,r,i,o,s,a,u,l,c,h;return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.prev=0,t.next=3,Yt.Gt();case 3:return e=t.sent,t.t0=v,t.next=7,e.jl();case 7:t.t1=t.sent,n=t.t0.m.call(t.t0,t.t1,0),r=null,i=1,o=[],s=0;case 11:if(!(s=0&&(se="/pwa/wordRotator/publicTest/"),m.Ae(se),d.It=["de"],d.Vt=!1,pt.Jo="2",window.onerror=function(t,e,n){console.error(t,e,n)},String.prototype.format||(String.prototype.format=function(t){return this.replace(/{(\d+)}/g,function(e,n){return void 0!==t[n]?t[n]:e})}),Object.assign=v.m(Object.assign,function(e,n){if(e=v.m(e,{}),null===n||"object"!=(void 0===n?"undefined":t(n))||"isActiveClone"in n)return e;for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(n.isActiveClone=null,e[r]=n[r],delete n.isActiveClone);return e}),"undefined"!=typeof window&&(v.I(window.Node)&&!window.Node.prototype.removeAllChildren&&(Node.prototype.removeAllChildren=function(){for(;this.firstChild;)this.removeChild(this.firstChild);return this}),HTMLElement&&(HTMLElement.prototype.fadeOut=v.m(HTMLElement.prototype.fadeOut,function(t,e,n){t=v.m(t,.5),e=v.m(e,"ease-in-out"),n=v.m(n,0),this.style.transition="opacity "+t+"s "+e+" "+n+"s";var r=this,i=new Promise(function(e){var i=function t(n){r.removeEventListener("transitionend",t),r.removeEventListener("transitioncancel",o),r.style.opacity=null,r.style.transition=null,e(!0,n)},o=function t(n){r.removeEventListener("transitionend",i),r.removeEventListener("transitioncancel",t),r.style.opacity=null,r.style.transition=null,e(!1,n)};r.addEventListener("transitionend",i),r.addEventListener("transitioncancel",o),setTimeout(function(){e(!1)},1e3*(t+n))});return requestAnimationFrame(function(){requestAnimationFrame(function(){r.style.opacity=0})}),i}),HTMLElement.prototype.fadeIn=v.m(HTMLElement.prototype.fadeIn,function(t,e,n){t=v.m(t,.5),e=v.m(e,"ease-in-out"),n=v.m(n,0),this.style.transition="opacity "+t+"s "+e+" "+n+"s";var r=this;return new Promise(function(e){var i=function t(n){r.removeEventListener("transitionend",t),r.removeEventListener("transitioncancel",o),r.style.opacity=null,r.style.transition=null,e(!0,n)},o=function t(n){r.removeEventListener("transitionend",i),r.removeEventListener("transitioncancel",t),r.style.opacity=null,r.style.transition=null,e(!1,n)};r.addEventListener("transitionend",i),r.addEventListener("transitioncancel",o),"1"===getComputedStyle(r).getPropertyValue("opacity")&&e(!1),setTimeout(function(){e(!1)},1e3*(t+n)),requestAnimationFrame(function(){requestAnimationFrame(function(){r.style.opacity=1})})})})),Node&&(Node.prototype.replaceWith=v.m(Node.prototype.replaceWith,function(t){this.parentElement.replaceChild(t,this)}),Node.prototype.remove=v.m(Node.prototype.remove,function(){this.parentElement.removeChild(this)})),Element&&(Element.prototype.matches=v.m(Element.prototype.matches,v.m(Element.prototype.matchesSelector,Element.prototype.webkitMatchesSelector)),window.Element.prototype.closest=v.m(window.Element.prototype.getAll,function(t){var e=this;if(!document.documentElement.contains(e))return null;do{if(e.matches(t))return e;e=e.parentElement}while(null!==e);return null})),window.IDBObjectStore.prototype.getAll=v.m(window.IDBObjectStore.prototype.getAll,function(){var t={},e=[];return this.openCursor().onsuccess=function(n){var r=n.target.result;v.I(r)?(e.push(r.value),r.continue()):v.I(t.onsuccess)&&t.onsuccess({currentTarget:{result:e}})},t})),String.prototype.startsWith=v.m(String.prototype.startsWith,function(t,e){return e=e||0,this.indexOf(t,e)===e}),String.prototype.includes=v.m(String.prototype.includes,function(t){return this.indexOf(t)>=0}),String.prototype.endsWith=v.m(String.prototype.endsWith,function(t,e){var n=this.toString();("number"!=typeof e||!isFinite(e)||Math.floor(e)!==e||e>n.length)&&(e=n.length),e-=t.length;var r=n.indexOf(t,e);return-1!==r&&r===e}),window.fetch=v.m(window.fetch,function(t){console.log("customFetch",t);var e=null;if(window.XMLHttpRequest)e=new XMLHttpRequest;else if(window.Gi)try{e=new ActiveXObject("Msxml2.XMLHTTP")}catch(t){try{e=new ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}var n=new Promise(function(t){e.onload=t,e.onerror=function(e){t(Promise.reject(e))}}),r=new Promise(function(t){t({json:function(){return e.send(),n.then(function(){return JSON.parse(e.responseText)})},text:function(){return e.send(),n.then(function(){return e.responseText})},arrayBuffer:function(){return e.responseType="arraybuffer",e.send(),n.then(function(){return e.response})}})});return e.open("get",t,!0),r}),y.We(new D("red","red")),y.We(new D("blue","blue")),y.We(new D("black","black")),y.We(new D("green","green")),y.We(new D("pink","pink")),y.We(new D("dark","dark")),M.Oi(new dt(new q("img/whatsapp.svg"),"whatsapp",!0)),M.Oi(new dt(new A("img/sms.svg"),"sms",!0)),M.Oi(new dt(new N("img/telegram.svg"),"telegram",!0));var ae=new L;u.l(function(){window.app=ae,window.app.pause=ae.pause,window.app.resume=ae.resume,window.app.setAppEndListener=ae.setAppEndListener}),K.ro("html/application/setting-template.html"),lt.at=!1,ut.ko=!1,a.resolve(ae).then(r(regeneratorRuntime.mark(function t(){var e,n;return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:K.oo.p=l.Y,e=U.Gt(),yt.Gt().play(yt.ha.fa,{ua:"sound/brightAndBeautifull__.mp3",loop:!0,volume:.6,muted:"1"!==e.Hr("play-music","1")}).catch(function(t){return console.error(t)}),ae.start($t),d.bt("de"),ft.Eo(function(){}),n=ht.Gt(),ft.Wo()&&n.persist(),window.applyAndroidBridge=u.u,"1"===v.m(localStorage.getItem("was-open"),"0")?Promise.all([n.xo(),navigator.serviceWorker.ready]).then(function(t){t[0]||E.oi("warning-data-not-persistent")}):localStorage.setItem("was-open","1");case 5:case"end":return t.stop()}},t,this)}))); \ No newline at end of file diff --git a/src/module/Application/pwa/js/site/LevelSite.js b/src/module/Application/pwa/js/site/LevelSite.js index f7943cf..a0cdf47 100755 --- a/src/module/Application/pwa/js/site/LevelSite.js +++ b/src/module/Application/pwa/js/site/LevelSite.js @@ -438,12 +438,14 @@ export class LevelSite extends WordRotatorBaseSite { let rotatableSegments = this.level.getRotatableSegments(); let firstSegment = rotatableSegments[2]; + console.log(firstSegment); let pointer = this.findBy("#tutorial-pointer"); pointer.remove(); firstSegment.element.appendChild(pointer); this.level.setSegmentClickedListener((segment) => { + console.log("clicked Segment", segment); if (firstSegment === segment) { this._siteContent.classList.remove("tutorial"); this._siteContent.classList.remove("step-4"); @@ -470,5 +472,5 @@ LevelSite.RENDERER_TYPES = [20, 40, 60, 80, 81, 82, 83, 100, 120, 140, 160]; LevelSite.TUTORIAL = { FIRST_LEVEL: 67, SECOND_LEVEL: 15, - BIG_SEGMENT_LEVEL: 1386 + BIG_SEGMENT_LEVEL: 1921 }; \ No newline at end of file diff --git a/src/module/Application/src/Model/Manager/LevelManager.php b/src/module/Application/src/Model/Manager/LevelManager.php index de52221..43e3ae4 100755 --- a/src/module/Application/src/Model/Manager/LevelManager.php +++ b/src/module/Application/src/Model/Manager/LevelManager.php @@ -254,7 +254,7 @@ class LevelManager extends StandardManager array_splice($levelsToGenerate, $currentIndex, 1); } - } while (count($levelsToGenerate) > 0); + } while (count($levelsToGenerate) > 0 && $levelGenerated < 500); $this->emFlush(); $this->wordManager->emFlush(); diff --git a/src/scss/_tutorial.scss b/src/scss/_tutorial.scss index 6272318..33fafee 100644 --- a/src/scss/_tutorial.scss +++ b/src/scss/_tutorial.scss @@ -1,9 +1,9 @@ @keyframes tutorialPointer { 0% { - top: 75%; + top: 25%; } 100% { - top: 25%; + top: 75%; } } @@ -96,11 +96,11 @@ border-radius: 50%; - left: 25%; - right: 50%; + left: 75%; + //right: 50%; position: absolute; top: 75%; - bottom: 50%; + //bottom: 50%; z-index: 1; transform: translate(-50%, -50%); diff --git a/src/scss/wordRotator.scss b/src/scss/wordRotator.scss index 91536df..e1a873c 100755 --- a/src/scss/wordRotator.scss +++ b/src/scss/wordRotator.scss @@ -25,7 +25,7 @@ nav.top-bar.title-bar { } } -.relative-level-number{ +.relative-level-number { position: relative; #level-number-container { top: 50%; @@ -197,7 +197,7 @@ $coinTowerDimension: 28px; > .child-container { > .segment { //transform: rotate(#{360- nth($rotationDegrees, $i)}deg); - transform: #{map-get($degreeMatrix, 360- nth($rotationDegrees, $i))}; + transform: #{map-get($degreeMatrix, 360- nth($rotationDegrees, $i))}; background-color: inherit; z-index: 1; @@ -247,6 +247,7 @@ $coinTowerDimension: 28px; } .segment { + vertical-align: top; white-space: initial; cursor: pointer; @@ -267,7 +268,8 @@ $coinTowerDimension: 28px; } &.segment-column { - > .child-container > .segment{ + padding-top: 4px; + > .child-container > .segment { display: block; width: 100%; } @@ -376,7 +378,8 @@ body { #site-content { overflow: visible; } -div.mainContainer{ + +div.mainContainer { overflow-x: hidden; } @@ -387,13 +390,13 @@ div.mainContainer{ // background: url('../img/speaker.svg') //} -.clickable{ +.clickable { cursor: pointer; } #share-button { overflow: hidden; - svg{ + svg { cursor: pointer; max-width: 1.5rem; } diff --git a/test/test.testcafe.js b/test/test.testcafe.js index c40d5cd..7a6265a 100644 --- a/test/test.testcafe.js +++ b/test/test.testcafe.js @@ -1,7 +1,7 @@ import {Selector} from 'testcafe'; import {ClientFunction} from 'testcafe'; -let isLocal = false; +let isLocal = true; let isMobile = false; const checkMatrix = async (matrixStringSelector, shouldValues, timeout) => { @@ -22,7 +22,7 @@ const checkMatrix = async (matrixStringSelector, shouldValues, timeout) => { return await checkMatrix(matrixStringSelector._reExecute(), shouldValues, timeout - step) } else { - console.error(values[i] +" not "+ shouldValues[i] + " with", values, shouldValues, i ); + console.error(values[i] + " not " + shouldValues[i] + " with", values, shouldValues, i); return false; } } @@ -86,7 +86,7 @@ else { } let dragDimen = 280; -if (isMobile){ +if (isMobile) { dragDimen = 90; } @@ -134,7 +134,7 @@ test('Play', async t => { .expect(Selector('.tutorial-text .step-1').visible).eql(false) .click(Selector('.segment-parent').nth(SEGMENT.THREE)) .expect(Selector('.tutorial-text .step-2').visible).eql(true); - await t.click(Selector('.segment-parent').nth(SEGMENT.THREE)) + await t.click(Selector('.segment-parent').nth(SEGMENT.THREE)) .expect(Selector('#continue-button').visible).eql(true) .click(Selector('#continue-button')) .wait(1000); @@ -170,9 +170,9 @@ test('Play', async t => { .expect(Selector('.segment-parent').nth(SEGMENT.TWO).textContent).eql("AUER") .expect(Selector('.segment-parent').nth(SEGMENT.THREE).textContent).eql("ERAP") .expect(Selector('.segment-parent').nth(SEGMENT.FOUR).textContent).eql("EIIE") - .expect(await checkMatrix(Selector('.segment.segment-parent.rotate-270').nth(0).getStyleProperty('transform'), [0, -1, 1, 0, ])).ok() - .expect(await checkMatrix(Selector('.segment.segment-parent.rotate-180').getStyleProperty('transform'), [-1, 0, 0, -1, ])).ok() - .expect(await checkMatrix(Selector('.segment.segment-parent.rotate-360').getStyleProperty('transform'), [1, 0, 0, 1, ])).ok() + .expect(await checkMatrix(Selector('.segment.segment-parent.rotate-270').nth(0).getStyleProperty('transform'), [0, -1, 1, 0,])).ok() + .expect(await checkMatrix(Selector('.segment.segment-parent.rotate-180').getStyleProperty('transform'), [-1, 0, 0, -1,])).ok() + .expect(await checkMatrix(Selector('.segment.segment-parent.rotate-360').getStyleProperty('transform'), [1, 0, 0, 1,])).ok() .expect(Selector('#continue-button').visible).eql(false) .expect(Selector('#level-number').textContent).eql("3") .expect(Selector('#won-text').visible).eql(false) @@ -180,9 +180,9 @@ test('Play', async t => { .click(Selector('.segment-parent').nth(SEGMENT.ONE)) .click(Selector('.segment-parent').nth(SEGMENT.FOUR)) .click(Selector('.segment-parent').nth(SEGMENT.TWO)) - .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.TWO).getStyleProperty('transform'), [1, 0, 0, 1, ])).ok() + .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.TWO).getStyleProperty('transform'), [1, 0, 0, 1,])).ok() .click(Selector('.segment-parent').nth(SEGMENT.TWO)) - .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.TWO).getStyleProperty('transform'), [1, 0, 0, 1, ])).ok() + .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.TWO).getStyleProperty('transform'), [1, 0, 0, 1,])).ok() .expect(Selector('#won-text').visible).eql(true) .expect(Selector('#continue-button').visible).eql(true) .click(Selector('#continue-button')) @@ -208,6 +208,98 @@ test('Play', async t => { levelNumber++; + await t + .drag(Selector('.segment-parent').nth(SEGMENT.THREE), dragDimen, 4, { + offsetX: 10, + offsetY: 17 + }) + .click(Selector('.segment-parent').nth(SEGMENT.TWO)) + .click(Selector('.segment-parent').nth(SEGMENT.SIX)) + .click(Selector('.segment-parent').nth(SEGMENT.ELEVEN)) + .click(Selector('.segment-parent').nth(SEGMENT.ONE)) + .click(Selector('.segment-parent').nth(SEGMENT.NINE)) + .click(Selector('.segment-parent').nth(SEGMENT.TWO)) + .click(Selector('.segment-parent').nth(SEGMENT.SIX)) + .click(Selector('.segment-parent').nth(SEGMENT.SEVEN)) + .click(Selector('.segment-parent').nth(SEGMENT.NINE)) + .click(Selector('.segment-parent').nth(SEGMENT.TWO)) + .click(Selector('.segment-parent').nth(SEGMENT.ELEVEN)) + .click(Selector('.segment-parent').nth(SEGMENT.NINE)) + .click(Selector('.segment-parent').nth(SEGMENT.SIX)) + .click(Selector('.segment-parent').nth(SEGMENT.ELEVEN)) + .click(Selector('#continue-button')) + .expect(Selector('.coin-counter').innerText).contains("" + (coinsPerLevel * levelNumber + extraCoins - helpCost)); + + levelNumber++; + + await t + .click(Selector('.segment-parent').nth(SEGMENT.FOUR)) + .click(Selector('.segment-parent').nth(SEGMENT.SIX)) + .click(Selector('.segment-parent').nth(SEGMENT.EIGHT)) + .click(Selector('.segment-parent').nth(SEGMENT.TEN)) + .click(Selector('.segment-parent').nth(SEGMENT.NINE)) + .click(Selector('.segment-parent').nth(SEGMENT.TEN)) + .click(Selector('.segment-parent').nth(SEGMENT.SIX)) + .click(Selector('.segment-parent').nth(SEGMENT.FOUR)) + .click(Selector('.segment-parent').nth(SEGMENT.NINE)) + .click(Selector('.segment-parent').nth(SEGMENT.TEN)) + .click(Selector('.segment-parent').nth(SEGMENT.ELEVEN)) + .click(Selector('.segment-parent').nth(SEGMENT.SIX)) + .click(Selector('#continue-button')) + .expect(Selector('.coin-counter').innerText).contains("" + (coinsPerLevel * levelNumber + extraCoins - helpCost)); + + levelNumber++; + + await t + .drag(Selector('.segment-parent').nth(SEGMENT.FIVE), -dragDimen, 4, { + offsetX: dragDimen + 50, + offsetY: 17 + }) + .click(Selector('.segment-parent').nth(SEGMENT.TWO)) + .click(Selector('.segment-parent').nth(SEGMENT.THREE)) + .click(Selector('.segment-parent').nth(SEGMENT.TWO)) + .click(Selector('.segment-parent').nth(SEGMENT.ONE)) + .click(Selector('.segment-parent').nth(SEGMENT.THREE)) + .click(Selector('.segment-parent').nth(SEGMENT.FOUR)) + .click(Selector('.segment-parent').nth(SEGMENT.TEN)) + .click(Selector('.segment-parent').nth(SEGMENT.SEVEN)) + .click(Selector('.segment-parent').nth(SEGMENT.EIGHT)) + .click(Selector('.segment-parent').nth(SEGMENT.NINE)) + .click(Selector('.segment-parent').nth(SEGMENT.SIX)) + .click(Selector('.segment-parent').nth(SEGMENT.TEN)) + .click(Selector('.segment-parent').nth(SEGMENT.THREE)) + .click(Selector('.segment-parent').nth(SEGMENT.TWO)) + .click(Selector('.segment-parent').nth(SEGMENT.FOUR)) + .click(Selector('.segment-parent').nth(SEGMENT.TEN)) + .click(Selector('.segment-parent').nth(SEGMENT.ELEVEN)) + .click(Selector('.segment-parent').nth(SEGMENT.NINE)) + .click(Selector('#continue-button')) + .expect(Selector('.coin-counter').innerText).contains("" + (coinsPerLevel * levelNumber + extraCoins - helpCost)); + levelNumber++; + + await t + .click(Selector('.segment-parent').nth(SEGMENT.TEN)) + .click(Selector('.segment-parent').nth(SEGMENT.EIGHT)) + .click(Selector('.segment-parent').nth(SEGMENT.FOUR)) + .click(Selector('.segment-parent').nth(SEGMENT.FIVE)) + .click(Selector('.segment-parent').nth(SEGMENT.ELEVEN)) + .click(Selector('.segment-parent').nth(SEGMENT.ONE)) + .click(Selector('.segment-parent').nth(SEGMENT.TWO)) + .click(Selector('.segment-parent').nth(SEGMENT.THREE)) + .click(Selector('.segment-parent').nth(SEGMENT.TEN)) + .click(Selector('.segment-parent').nth(SEGMENT.FOUR)) + .click(Selector('.segment-parent').nth(SEGMENT.SIX)) + .click(Selector('.segment-parent').nth(SEGMENT.ONE)) + .click(Selector('.segment-parent').nth(SEGMENT.EIGHT)) + .click(Selector('.segment-parent').nth(SEGMENT.FIVE)) + .click(Selector('.segment-parent').nth(SEGMENT.TEN)) + .click(Selector('.segment-parent').nth(SEGMENT.ELEVEN)) + .click(Selector('.segment-parent').nth(SEGMENT.EIGHT)) + .click(Selector('#continue-button')) + .expect(Selector('.coin-counter').innerText).contains("" + (coinsPerLevel * levelNumber + extraCoins - helpCost)); + + levelNumber++; + await t.drag(Selector('.segment-parent').nth(SEGMENT.ONE), -dragDimen, 4, { offsetX: dragDimen + 50, offsetY: 17 @@ -244,24 +336,24 @@ test('Play', async t => { .expect(Selector('.segment-parent').nth(SEGMENT.THIRTEEN).textContent).eql("TUTO") .expect(Selector('.segment-parent').nth(SEGMENT.FOURTEEN).textContent).eql("NGPF") .drag(Selector('.segment-parent').nth(SEGMENT.TEN), dragDimen, 4, { - offsetX: dragDimen/5, + offsetX: dragDimen / 5, offsetY: 10 }) .drag(Selector('.segment-parent').nth(SEGMENT.ONE), dragDimen, 3, { - offsetX: dragDimen/5, + offsetX: dragDimen / 5, offsetY: 10 }) .drag(Selector('.segment-parent').nth(SEGMENT.TEN).find('div').withText('I'), dragDimen, 4, { - offsetX: dragDimen/5, - offsetY: dragDimen/5 + offsetX: dragDimen / 5, + offsetY: dragDimen / 5 }) .drag(Selector('.segment-parent').nth(SEGMENT.ONE).find('div').withText('S'), 10, dragDimen, { offsetX: dragDimen, - offsetY: dragDimen/5 + offsetY: dragDimen / 5 }) .drag(Selector('.segment-parent').nth(SEGMENT.TEN), dragDimen, 4, { offsetX: 10, - offsetY: dragDimen/5 + offsetY: dragDimen / 5 }) .click(Selector('.segment-parent').nth(SEGMENT.NINE)) .click(Selector('.segment-parent').nth(SEGMENT.EIGHT)) @@ -290,15 +382,15 @@ test('Play', async t => { await t.expect(Selector('#level-number').textContent).eql("" + levelNumber) .expect(Selector('.segment-parent').nth(SEGMENT.ONE).textContent).eql("BEANTOBEALBALEUM") .expect(Selector('.segment-parent').nth(SEGMENT.SIX).textContent).eql("NUTUNGNGRGHAIEUS") - .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.ONE).getStyleProperty('transform'), [1, 0, 0, 1, ])).ok() - .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.SIX).getStyleProperty('transform'), [0, 1, -1, 0, ])).ok() + .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.ONE).getStyleProperty('transform'), [1, 0, 0, 1,])).ok() + .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.SIX).getStyleProperty('transform'), [0, 1, -1, 0,])).ok() .click(Selector('.segment-parent').nth(SEGMENT.THREE)) .click(Selector('.segment-parent').nth(SEGMENT.FOUR)) .click(Selector('.segment-parent').nth(SEGMENT.TWO)) .drag(Selector('.segment-parent').nth(SEGMENT.SIX).find('div').withText('U'), 3, dragDimen, { offsetX: 10, - offsetY: dragDimen/5 + offsetY: dragDimen / 5 }) .click(Selector('.segment-parent').nth(SEGMENT.SEVEN)) .click(Selector('.segment-parent').nth(SEGMENT.THREE)) @@ -316,8 +408,8 @@ test('Play', async t => { //Level 6 await t.expect(Selector('#level-number').textContent).eql("" + levelNumber) .expect(Selector('.segment-parent').nth(SEGMENT.ONE).textContent).eql("FEGEHLISARBEBERE") - .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.ONE).getStyleProperty('transform'), [1, 0, 0, 1, ])).ok() - .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.TEN).getStyleProperty('transform'), [-1, 0, 0, -1, ])).ok() + .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.ONE).getStyleProperty('transform'), [1, 0, 0, 1,])).ok() + .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.TEN).getStyleProperty('transform'), [-1, 0, 0, -1,])).ok() .expect(Selector('.segment-parent').nth(SEGMENT.TEN).textContent).eql("ITITSPSCIKARAROT") .click(Selector('.segment-parent').nth(SEGMENT.FOUR)) @@ -358,7 +450,7 @@ test('Play', async t => { offsetX: 10, offsetY: 10 }) - .expect(await checkMatrix(Selector('div').withText('P').nth(11).find('.segment.segment-parent.layer-2.rotate-360').getStyleProperty('transform'), [1, 0, 0, 1, ])).ok() + .expect(await checkMatrix(Selector('div').withText('P').nth(11).find('.segment.segment-parent.layer-2.rotate-360').getStyleProperty('transform'), [1, 0, 0, 1,])).ok() .expect(Selector('#continue-button').visible).eql(true) .expect(Selector('#won-text').visible).eql(true) .click(Selector('#continue-button')) @@ -366,7 +458,7 @@ test('Play', async t => { levelNumber++; //Level 7 - await t.expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.SIX).getStyleProperty('transform'), [1, 0, 0, 1, ])).ok() + await t.expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.SIX).getStyleProperty('transform'), [1, 0, 0, 1,])).ok() .expect(Selector('.segment-row > .child-container').childElementCount).eql(3) .drag(Selector('.segment-parent').nth(SEGMENT.ONE), 4, dragDimen, { @@ -408,9 +500,9 @@ test('LoadLastLevel', async t => { await waitForMainMenu(t); await t.click(Selector('#play-button')).wait(500) .expect(Selector('.segment-parent').nth(SEGMENT.ONE).hasClass('locked')).ok() - .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.ONE).getStyleProperty('transform'), [1, 0, 0, 1, ])).ok() - .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.TWO).getStyleProperty('transform'), [1, 0, 0, 1, ])).ok() - .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.THREE).getStyleProperty('transform'), [0, -1, 1, 0, ])).ok() + .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.ONE).getStyleProperty('transform'), [1, 0, 0, 1,])).ok() + .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.TWO).getStyleProperty('transform'), [1, 0, 0, 1,])).ok() + .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.THREE).getStyleProperty('transform'), [0, -1, 1, 0,])).ok() }).before(async t => { await testLocalStorageSet("currentLevel", "{\"id\":15,\"rotations\":[0,0,270],\"locks\":[false,true,true]}"); }); @@ -420,10 +512,10 @@ test('LevelRotation', async t => { .click(Selector('.segment-parent').nth(SEGMENT.THREE)) .click(Selector('.segment-parent').nth(SEGMENT.THREE)) .click(Selector('.segment-parent').nth(SEGMENT.THREE)) - .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.THREE).getStyleProperty('transform'), [0, -1, 1, 0, ])).ok() + .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.THREE).getStyleProperty('transform'), [0, -1, 1, 0,])).ok() .wait(1000) - .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.THREE).getStyleProperty('transform'), [0, -1, 1, 0, ])).ok() - .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.FOUR).getStyleProperty('transform'), [0, 1, -1, 0, ])).ok() + .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.THREE).getStyleProperty('transform'), [0, -1, 1, 0,])).ok() + .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.FOUR).getStyleProperty('transform'), [0, 1, -1, 0,])).ok() .click(Selector('.segment-parent').nth(SEGMENT.THREE)) .click(Selector('.segment-parent').nth(SEGMENT.FOUR)) .click(Selector('.segment-parent').nth(SEGMENT.FOUR)) @@ -436,10 +528,10 @@ test('LevelRotation', async t => { .click(Selector('.segment-parent').nth(SEGMENT.THREE)) .click(Selector('.segment-parent').nth(SEGMENT.THREE)) .click(Selector('.segment-parent').nth(SEGMENT.THREE)) - .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.THREE).getStyleProperty('transform'), [0, -1, 1, 0, ])).ok() + .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.THREE).getStyleProperty('transform'), [0, -1, 1, 0,])).ok() .wait(2000) - .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.THREE).getStyleProperty('transform'), [0, -1, 1, 0, ])).ok() - .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.FOUR).getStyleProperty('transform'), [0, 1, -1, 0, ])).ok() + .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.THREE).getStyleProperty('transform'), [0, -1, 1, 0,])).ok() + .expect(await checkMatrix(Selector('.segment-parent').nth(SEGMENT.FOUR).getStyleProperty('transform'), [0, 1, -1, 0,])).ok() .click(Selector('.segment-parent').nth(SEGMENT.THREE)) .click(Selector('.segment-parent').nth(SEGMENT.FOUR)) .click(Selector('.segment-parent').nth(SEGMENT.FOUR))