basti1012.bplaced.net

Du siehst gerade eine vereinfachte Darstellung unserer Inhalte. Normale Ansicht mit richtiger Formatierung.
    Zeigt die aktuellen Coronazahlen weltweit an <span style="color:#fd0808">Script defekt<br>API nicht mehr erreichbar</span>

    Code

                                        
                                    <style>
      @charset "UTF-8";
    @import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css");
    @import url("https://fonts.googleapis.com/css2?family=Fira+Sans:wght@200;400;500&display=swap");
    :root {
      --current-hue: 45;
      --confirmed-hue: 45;
      --recovered-hue: 164;
      --deaths-hue: 353;
      --compl-hue: calc(var(--current-hue) - 15);
      --map-rotate-x: 0deg;
      --map-rotate-y: 0deg;
    }
    
    *,
    *::before,
    *::after {
      box-sizing: border-box;
    }
    
    #app {
      font-family: "Fira Sans", sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      width: 100vw;
      height: 100vh;
    }
    
    body {
      background-color: #f3f4f6;
      min-height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
      user-select: none;
      margin: 0;
    }
    
    #notification {
      position: fixed;
      top: 1vh;
      right: 1vw;
      border-left: 5px solid;
      min-width: 200px;
      background-color: #e74c3c;
      min-height: 50px;
      z-index: 50;
      display: flex;
      align-items: center;
      padding: 0.8em 1em;
    }
    #notification.error {
      border-color: #bf2718;
      color: #200704;
    }
    #notification .icon {
      padding-right: 0.5em;
      font-size: 1.3em;
    }
    #notification .text {
      font-size: 0.9em;
    }
    
    .main {
      height: 100%;
      display: flex;
      position: relative;
      background: url("https://www.toptal.com/designers/subtlepatterns/patterns/dot-grid.png");
      overflow: hidden;
    }
    .main[data-show-map=true] .content-wrapper {
      transform: scale(0.9) translateX(10%);
    }
    .main .reset-map {
      position: absolute;
      bottom: 1em;
      right: 1em;
      font-size: 1.4em;
      padding: 0.3em 0.4em;
      z-index: 10;
      transition: all 0.4s cubic-bezier(0.5, 0, 1, 0.81);
      opacity: 0;
      cursor: pointer;
      background-color: rgba(255, 255, 255, 0.5);
    }
    .main .reset-map:hover {
      background-color: rgba(255, 255, 255, 0.8);
    }
    .main .reset-map.show {
      opacity: 1;
    }
    
    .top-nav .current-location {
      padding-top: 5em;
      margin-bottom: 5em;
    }
    .top-nav .current-location .flag-wrapper .flag {
      border-radius: 3px;
      width: 40%;
      overflow: hidden;
    }
    .top-nav .current-location .flag-wrapper.world {
      display: flex;
      justify-content: center;
    }
    .top-nav .current-location .flag-wrapper.world .flag {
      background-color: white;
      padding: 0.3em;
      font-size: 1.8em;
      width: 90px;
      height: 60px;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .top-nav .current-location .location-title {
      color: white;
      margin-top: 0.5em;
    }
    
    .map-countries-container {
      height: 70%;
      overflow: hidden;
      transition: all 0.4s cubic-bezier(0.5, 0, 1, 0.81);
      position: relative;
      max-height: 70%;
    }
    
    .sidebar {
      justify-content: center;
      display: flex;
      flex-direction: column;
      background-image: linear-gradient(60deg, #21425f, #2e5c85);
      width: 250px;
      padding: 1em;
      z-index: 5;
      justify-content: space-between;
      position: relative;
      overflow: hidden;
    }
    .sidebar::before, .sidebar::after {
      background-image: radial-gradient(#4284bd, #7ba9d1);
      content: "";
      position: absolute;
      width: 40em;
      height: 40em;
      z-index: -1;
      top: -5%;
      left: 50%;
      border-radius: 50%;
      transform: translateX(-50%);
      filter: blur(50px);
      opacity: 0.3;
    }
    .sidebar::after {
      top: 80%;
      transform: translateX(-20%) rotate(180deg);
    }
    .sidebar .case-type {
      color: white;
      font-size: 1rem;
      padding: 1em;
      margin-bottom: 0.5em;
      display: flex;
      cursor: pointer;
      user-select: none;
      transition: all 0.2s ease-in-out;
      border-radius: 6px;
      height: 70px;
    }
    .sidebar .case-type.confirmed .case-type-icon {
      color: hsl(var(--confirmed-hue), 100%, 50%);
      background-color: hsl(var(--confirmed-hue), 100%, 95%);
    }
    .sidebar .case-type.deaths .case-type-icon {
      color: hsl(var(--deaths-hue), 100%, 50%);
      background-color: hsl(var(--deaths-hue), 100%, 95%);
    }
    .sidebar .case-type.recovered .case-type-icon {
      color: hsl(var(--recovered-hue), 60%, 34%);
      background-color: hsl(var(--recovered-hue), 100%, 95%);
    }
    .sidebar .case-type.active {
      background-color: rgba(255, 225, 255, 0.2);
    }
    .sidebar .case-type.active .case-type-inner .case-title {
      font-size: 1em;
      color: white;
    }
    .sidebar .case-type.active .case-type-inner .case-count {
      font-size: 0.7em;
    }
    .sidebar .case-type:hover:not(.active) {
      background-color: rgba(255, 225, 255, 0.1);
    }
    .sidebar .case-type:hover:not(.active) i {
      font-size: 1.1em;
    }
    .sidebar .case-type:hover:not(.active) .case-title {
      font-size: 1em;
      color: white;
    }
    .sidebar .case-type:hover:not(.active) .case-count {
      font-size: 0.7em;
    }
    .sidebar .case-type .case-type-icon {
      padding: 1em;
      width: 25%;
      display: flex;
      justify-content: center;
      align-items: center;
      background-color: white;
      border-radius: 5px;
    }
    .sidebar .case-type .case-type-icon i {
      position: absolute;
      transition: all 0.2s ease-in-out;
    }
    .sidebar .case-type .case-type-inner {
      flex-grow: 1;
      text-align: left;
      margin-left: 1em;
    }
    .sidebar .case-type .case-type-inner .case-title {
      font-size: 0.7em;
      text-transform: uppercase;
      font-weight: normal;
      color: #b0b0b0;
      transition: all 0.2s ease-in-out;
    }
    .sidebar .case-type .case-type-inner .case-count {
      font-size: 1.1em;
      font-feature-settings: "tnum";
      font-variant-numeric: tabular-nums;
      transition: all 0.2s ease-in-out;
    }
    .sidebar .bottom-nav {
      display: flex;
      justify-content: space-around;
      margin-top: auto;
    }
    .sidebar .bottom-nav > div {
      cursor: pointer;
      padding: 1.4em;
      color: white;
      position: relative;
      font-size: 1.5em;
      border-radius: 5px;
      transition: all 0.2s ease-in-out;
    }
    .sidebar .bottom-nav > div:hover:not(.active) {
      background-color: rgba(255, 225, 255, 0.1);
    }
    .sidebar .bottom-nav > div.active {
      background-color: rgba(255, 225, 255, 0.2);
    }
    .sidebar .bottom-nav > div i {
      position: absolute;
      color: white;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
    }
    .sidebar .info-nav {
      display: flex;
      justify-content: space-around;
      color: white;
      margin-top: 1em;
      padding-top: 1em;
      border-top: 1px dashed rgba(255, 225, 255, 0.3);
    }
    .sidebar .info-nav > div,
    .sidebar .info-nav > a {
      padding: 0.5em 1em;
      border-radius: 4px;
      transition: all 0.2s ease-in-out;
      cursor: pointer;
      color: white;
      font-size: 1.2em;
      display: flex;
      justify-content: center;
      align-items: center;
      text-decoration: none;
    }
    .sidebar .info-nav > div.twitter,
    .sidebar .info-nav > a.twitter {
      color: #1c9cea;
      background-color: rgba(255, 255, 255, 0.8);
    }
    .sidebar .info-nav > div.twitter:hover,
    .sidebar .info-nav > a.twitter:hover {
      background-color: white;
    }
    .sidebar .info-nav > div:hover,
    .sidebar .info-nav > a:hover {
      background-color: rgba(255, 225, 255, 0.1);
    }
    .sidebar .info-nav > div.active,
    .sidebar .info-nav > a.active {
      background-color: rgba(255, 225, 255, 0.2);
    }
    .sidebar .copyright-wrapper {
      background-color: rgba(0, 0, 0, 0.2);
      margin: 1em -1em -1em -1em;
      padding: 1em;
      text-align: left;
      background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.1) 0, transparent 2%);
      overflow: auto;
    }
    .sidebar .copyright-wrapper a {
      display: block;
      font-size: 0.8em;
      margin: 0.2em 0;
      padding: 0.4em 0.8em;
      color: white;
      text-decoration: none;
      transition: all 0.2s;
      border-radius: 2px;
    }
    .sidebar .copyright-wrapper a::after {
      font-family: "Font Awesome 5 Free";
      font-weight: 900;
      -webkit-font-smoothing: antialiased;
      display: inline-block;
      font-style: normal;
      font-variant: normal;
      text-rendering: auto;
      line-height: 1;
      font-size: 0.8em;
      margin-left: 1em;
    }
    .sidebar .copyright-wrapper a:hover {
      background-color: rgba(255, 225, 255, 0.1);
    }
    .sidebar .copyright-wrapper a:hover::after {
      content: "";
    }
    
    .content-wrapper {
      height: 100%;
      flex-grow: 1;
      transition: all 0.4s cubic-bezier(0.5, 0, 1, 0.81);
      position: relative;
      padding: 2em;
    }
    .content-wrapper .series-container {
      height: 40%;
      position: absolute;
      bottom: 0;
      z-index: 1;
      width: 100%;
      padding: inherit;
      left: 0;
      transition: all 0.4s cubic-bezier(0.5, 0, 1, 0.81);
    }
    
    .fadeslide-enter-active {
      animation: bounce-in 0.5s;
    }
    
    .fadeslide-leave-active {
      animation: bounce-in 0.5s reverse;
    }
    
    @keyframes bounce-in {
      0% {
        transform: translateX(10%);
        opacity: 0;
      }
      100% {
        transform: translateX(0%);
        opacity: 1;
      }
    }
    #countries-list-wrapper {
      height: 100%;
      background-color: #e1ebf4;
      width: 350px;
      transform: translateX(-50%);
      z-index: 3;
      position: absolute;
      transition: all 0.4s cubic-bezier(0.5, 0, 1, 0.81);
      left: 0;
      display: flex;
      flex-direction: column;
    }
    #countries-list-wrapper.active {
      transform: translateX(0);
      left: 250px;
    }
    #countries-list-wrapper .countries-search-wrapper {
      padding: 1em 2em;
    }
    #countries-list-wrapper .countries-search-wrapper input {
      border: 0px solid;
      background-color: rgba(255, 255, 255, 0.6);
      width: 100%;
      border-radius: 5px;
      transition: all 0.2s ease-in-out;
      font-size: 0.8em;
      padding: 1em 1em;
      outline: 0;
    }
    #countries-list-wrapper .countries-search-wrapper input:focus {
      background-color: white;
    }
    #countries-list-wrapper .countries-list-container {
      height: 100%;
      display: flex;
      flex-direction: column;
      overflow: auto;
      padding: 1em;
    }
    #countries-list-wrapper .countries-list-container::-webkit-scrollbar {
      width: 6px;
      height: 6px;
    }
    #countries-list-wrapper .countries-list-container::-webkit-scrollbar-thumb {
      background: #396791;
    }
    #countries-list-wrapper .countries-list-container::-webkit-scrollbar-track {
      background: rgba(57, 103, 145, 0.2);
    }
    #countries-list-wrapper .countries-list-container {
      scrollbar-face-color: #396791;
      scrollbar-track-color: rgba(57, 103, 145, 0.2);
    }
    #countries-list-wrapper .countries-list-container .countries-list {
      height: 100%;
    }
    #countries-list-wrapper .countries-list-container .countries-list.is-loading .country-wrapper {
      cursor: default;
    }
    #countries-list-wrapper .countries-list-container .countries-list.is-loading .country-wrapper:hover {
      background-color: initial;
    }
    #countries-list-wrapper .countries-list-container .countries-list.is-loading .country-wrapper .country-content,
    #countries-list-wrapper .countries-list-container .countries-list.is-loading .country-wrapper .flag-wrapper {
      opacity: 0.6;
    }
    #countries-list-wrapper .countries-list-container .countries-list.is-loading .country-wrapper.loading .country-content,
    #countries-list-wrapper .countries-list-container .countries-list.is-loading .country-wrapper.loading .flag-wrapper {
      opacity: 0.1;
      filter: blur(1px);
    }
    #countries-list-wrapper .countries-list-container .countries-list .country-wrapper {
      display: flex;
      font-size: 0.8rem;
      padding: 1em;
      width: 100%;
      cursor: pointer;
      transition: all 0.3s;
      position: relative;
    }
    #countries-list-wrapper .countries-list-container .countries-list .country-wrapper:hover {
      background-color: hsla(var(--current-hue), 30%, 80%, 0.5);
    }
    #countries-list-wrapper .countries-list-container .countries-list .country-wrapper.active {
      background-color: hsla(var(--current-hue), 30%, 70%, 0.8);
    }
    #countries-list-wrapper .countries-list-container .countries-list .country-wrapper .flag-wrapper {
      font-size: 2em;
      transition: all 0.2s;
    }
    #countries-list-wrapper .countries-list-container .countries-list .country-wrapper .country-content {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      grid-template-rows: repeat(2, 1fr);
      text-align: left;
      flex-grow: 1;
      margin-left: 1em;
      transition: all 0.2s;
    }
    #countries-list-wrapper .countries-list-container .countries-list .country-wrapper .country-content .country-name {
      grid-column: 1/2;
      white-space: nowrap;
      text-overflow: ellipsis;
      overflow: hidden;
    }
    #countries-list-wrapper .countries-list-container .countries-list .country-wrapper .country-content .country-count-diff {
      grid-column: 1/2;
      grid-row: 2/3;
      font-size: 0.8em;
    }
    #countries-list-wrapper .countries-list-container .countries-list .country-wrapper .country-content .country-count-diff.extra {
      color: red;
    }
    #countries-list-wrapper .countries-list-container .countries-list .country-wrapper .country-content .country-count-diff.less {
      color: green;
    }
    #countries-list-wrapper .countries-list-container .countries-list .country-wrapper .country-content .country-count {
      grid-column: 2/3;
      grid-row: 1/3;
      text-align: right;
      font-size: 1.2em;
      font-weight: bold;
    }
    @keyframes loader-bar {
      0% {
        background-position: 0 0;
      }
      100% {
        background-position: 15px 15px;
      }
    }
    
    .flag {
      position: relative;
      display: inline-flex;
      width: 2.1em;
    }
    .flag.fa-globe {
      height: 43px;
      background-color: #fff;
      display: flex;
      justify-content: center;
      align-items: center;
      border-radius: 4px;
      overflow: hidden;
      width: 58px;
      font-size: 0.8em;
    }
    .flag img {
      max-width: 100%;
    }
    .flag::after {
      content: "";
      width: 100%;
      height: 100%;
      position: absolute;
      display: block;
      mix-blend-mode: overlay;
      box-sizing: border-box;
      background-image: linear-gradient(0deg, rgba(0, 0, 0, 0.3) 2%, rgba(255, 255, 255, 0.7) 100%);
    }
    
    #chartjs-tooltip {
      background: hsl(var(--compl-hue), 73%, 90%);
      filter: drop-shadow(0px 0px 1px hsl(var(--compl-hue), 100%, 30%));
      transform: translate(-50%, -25px);
      z-index: 50;
      padding: 1em;
      pointer-events: none;
      border-radius: 0.2em;
      position: absolute;
      top: 0;
      font-size: 0.9em;
      text-align: left;
      min-width: 150px;
      opacity: 0;
    }
    #chartjs-tooltip .title {
      white-space: nowrap;
      font-weight: bold;
    }
    #chartjs-tooltip .count-wrapper {
      white-space: nowrap;
      font-size: 0.9em;
      text-transform: capitalize;
    }
    #chartjs-tooltip .count-wrapper .count-total-type {
      white-space: nowrap;
    }
    #chartjs-tooltip .count-wrapper .count-total-number {
      padding: 0.2em;
    }
    #chartjs-tooltip::after {
      position: absolute;
      top: 100%;
      left: 50%;
      background-color: hsl(var(--compl-hue), 73%, 90%);
      width: 1em;
      height: 1em;
      transform: translate(-50%, -70%) rotate(45deg);
      content: "";
    }
    
    .series-data-wrapper {
      position: relative;
      width: 100%;
      height: 100%;
      display: flex;
      flex-direction: column;
    }
    .series-data-wrapper .series-data-options {
      font-size: 0.8em;
      width: 100%;
      padding: 1em 2em;
      text-align: left;
      transition: all 0.4s cubic-bezier(0.5, 0, 1, 0.81);
      display: flex;
    }
    .series-data-wrapper .series-data-options > div {
      display: flex;
      margin: 0 1em;
      border-radius: 0.2em;
      overflow: hidden;
    }
    .series-data-wrapper .series-data-options > div span {
      padding: 0.3em 0.9em;
      background-color: hsl(var(--compl-hue), 73%, 30%);
      transition: all 0.3s;
      display: inline-block;
      color: hsl(var(--compl-hue), 73%, 75%);
    }
    .series-data-wrapper .series-data-options > div span:not(.active) {
      cursor: pointer;
    }
    .series-data-wrapper .series-data-options > div span:not(.active):hover {
      background-color: hsl(var(--compl-hue), 73%, 20%);
    }
    .series-data-wrapper .series-data-options > div span.active {
      background-color: hsl(var(--compl-hue), 73%, 15%);
      color: white;
    }
    .series-data-wrapper .series-data {
      width: 100%;
      flex-grow: 1;
      position: relative;
      height: 80%;
    }
    
    .loader-wrapper {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      width: 80%;
      z-index: 50;
      max-width: 1000px;
    }
    .loader-wrapper .loader-bar {
      width: 100%;
      height: 3px;
      position: relative;
      box-shadow: 0 0 2em 0.5em rgba(103, 103, 103, 0.3);
    }
    .loader-wrapper .loader-bar.indeterminant .loader-bar-loaded {
      width: 100%;
      animation: loader-bar 1s linear infinite;
      background-size: 15px 15px;
      background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.5) 25%, transparent 25% 50%, rgba(255, 255, 255, 0.5) 50% 75%, transparent 75% 100%);
    }
    @keyframes loader-bar {
      0% {
        background-position: 0 0;
      }
      100% {
        background-position: 15px 15px;
      }
    }
    .loader-wrapper .loader-bar .loader-bar-loaded {
      position: absolute;
      top: 0;
      left: 0;
      height: 100%;
      background-color: hsl(var(--current-hue), 50%, 50%);
      transition: all 0.3s;
    }
    .loader-wrapper .loader-text {
      text-align: center;
      font-size: 1em;
      margin-top: 1em;
    }
    
    #location-tooltip {
      display: block;
      z-index: 50;
      transition: opacity 0.1s linear;
      pointer-events: none;
      min-width: 200px;
      left: 0;
      top: 0;
      position: fixed;
      transform: translate(-50%, 20%);
      font-size: 0.9em;
    }
    #location-tooltip .tooltip-inner {
      background: hsl(var(--current-hue), 30%, 20%);
      color: white;
      border-radius: 3px;
      padding: 1em;
      text-align: left;
    }
    #location-tooltip .tooltip-inner .tooltip-title {
      border-bottom: 1px solid white;
      margin-bottom: 1em;
      padding-bottom: 0.3em;
    }
    #location-tooltip .tooltip-inner .tooltip-content {
      font-size: 0.8em;
      margin-top: 1em;
    }
    #location-tooltip .tooltip-inner .tooltip-content > div {
      display: flex;
    }
    #location-tooltip .tooltip-inner .tooltip-content > div span {
      width: 50%;
      white-space: nowrap;
      padding: 0.2em 0.2em;
    }
    #location-tooltip .tooltip-inner .tooltip-content > div span:first-child {
      text-align: right;
    }
    #location-tooltip .tooltip-inner .tooltip-content > div span:last-child {
      text-transform: capitalize;
    }
    
    .map-container {
      position: absolute;
      top: 50%;
      left: 50%;
      width: 100%;
      max-width: 1000px;
      transform: translate(-50%, -60%) perspective(1000px) rotateX(var(--map-rotate-x)) rotateY(var(--map-rotate-y));
      max-height: 100%;
      padding: 2em 2em;
      box-sizing: initial;
      background-color: white;
      box-shadow: 0 0 1em 1em hsla(var(--current-hue), 100%, 10%, 0.1);
    }
    .map-container .svg-wrapper {
      max-width: 100%;
      max-height: 100%;
      position: relative;
      top: 50%;
      left: 50%;
    }
    .map-container svg {
      max-width: 100%;
      max-height: 100%;
      position: relative;
      filter: drop-shadow(0px 0px 2em hsla(var(--current-hue), 100%, 10%, 0.5));
      width: 1000px;
      height: 400px;
      transition: all 0.2s;
    }
    .map-container svg.loading {
      opacity: 0.5;
    }
    .map-container g {
      transition: all 0.2s ease-in-out;
      cursor: pointer;
    }
    .map-container g.no-select {
      cursor: default;
    }
    .map-container g.active path {
      stroke-width: 0;
      stroke: purple;
      z-index: 5;
    }
    .map-container:not([data-status=single-location]):hover g {
      fill-opacity: 0.5;
    }
    .map-container:not([data-status=single-location]):hover g:hover {
      fill-opacity: 1;
    }
    .map-container[data-status=single-location] g {
      fill-opacity: 0.1;
    }
    .map-container[data-status=single-location] g:hover {
      fill-opacity: 0.3;
    }
    .map-container[data-status=single-location] g[data-status=selected] {
      fill-opacity: 1;
    }
      
      
      
    </style>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.6.0/vuex.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.6.0/gsap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.1/axios.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.css">
    
    
    
    
    
    
    
    
    	<div id="app">
    			<notify
    				:show="getNotifyDetails.show"
    				:type="getNotifyDetails.type"
    				:message="getNotifyDetails.message"
    			></notify>
    
    			<div class="main" :data-show-map="show_countries_list">
    				<div class="sidebar">
    					<div class="top-nav">
    						<div class="current-location">
    							<div class="flag-wrapper" v-if="getCurrentLocation !== 'WO'">
    								<flag :iso="getCurrentLocation.toLowerCase()"></flag>
    							</div>
    							<div class="flag-wrapper world" v-if="getCurrentLocation === 'WO'">
    								<i class="flag fas fa-globe"></i>
    							</div>
    
    							<div class="location-title">{{ getCountriesList[getCurrentLocation] }}</div>
    						</div>
    					</div>
    					<div class="cases-nav">
    						<div
    							class="case-type confirmed"
    							@click="changeCaseType('confirmed')"
    							:class="{ active: getDisplayedCasesType == 'confirmed' }"
    						>
    							<div class="case-type-icon">
    								<i class="fas fa-virus"></i>
    							</div>
    							<div class="case-type-inner">
    								<div class="case-title">Confiremd</div>
    								<div class="case-count">{{ confirmedCount }}</div>
    							</div>
    						</div>
    						<div
    							class="case-type recovered"
    							@click="changeCaseType('recovered')"
    							:class="{ active: getDisplayedCasesType == 'recovered' }"
    						>
    							<div class="case-type-icon">
    								<i class="fas fa-first-aid"></i>
    							</div>
    							<div class="case-type-inner">
    								<div class="case-title">Recovered</div>
    								<div class="case-count">{{ recoveredCount }}</div>
    							</div>
    						</div>
    						<div
    							class="case-type deaths"
    							@click="changeCaseType('deaths')"
    							:class="{ active: getDisplayedCasesType == 'deaths' }"
    						>
    							<div class="case-type-icon">
    								<i class="fas fa-biohazard"></i>
    							</div>
    							<div class="case-type-inner">
    								<div class="case-title">Deaths</div>
    								<div class="case-count">{{ deathsCount }}</div>
    							</div>
    						</div>
    					</div>
    					<div class="bottom-nav">
    						<div class="fill-screen" @click="is_full_screen = !is_full_screen">
    							<i class="fas fa-expand" v-if="is_full_screen == false"></i>
    							<i class="fas fa-compress" v-if="is_full_screen == true"></i>
    						</div>
    						<div
    							class="locations-list"
    							:class="{ active: show_countries_list == true }"
    							@click="show_countries_list = !show_countries_list"
    						>
    							<i class="fas fa-map-marked-alt"></i>
    						</div>
    					</div>
    					<div class="info-nav">
    						<div
    							class="copyright-button"
    							:class="{ active: show_copyright == true }"
    							@click="show_copyright = !show_copyright"
    						>
    							<i class="far fa-copyright"></i>
    						</div>
    
    						<a target="_blank" href="https://codepen.io/khr2003"> <i class="fab fa-codepen"></i></a>
    
    						<a
    						target="_top"
    							class="twitter"
    							 href="https://twitter.com/intent/follow?screen_name=kalimahapps&tw_p=followbutton"
    							><i class="fab fa-twitter"></i
    						></a>
    					</div>
    
    					<div class="copyright-wrapper" v-if="show_copyright">
    						<a target="_blank" :href="link" v-for="( link, text)  in copyright_data">{{text}}</a>
    					</div>
    				</div>
    
    				<CountriesList :class="{ active: show_countries_list == true }"></CountriesList>
    
    				<div class="content-wrapper">
    					<WorldMap></WorldMap>
    
    					<div class="series-container">
    						<series></series>
    					</div>
    				</div>
    			</div>
    			<location-tooltip></location-tooltip>
    		</div>
    
    		<!-- Countries list -->
    		<template id="countries-list-template">
    			<div id="countries-list-wrapper">
    				<div class="countries-search-wrapper">
    					<input
    						type="text"
    						class="search-countries"
    						placeholder="Search Countries ..."
    						@input="filterCountries"
    					/>
    				</div>
    				<div class="countries-list-container">
    					<div class="countries-list" :class="{'is-loading': getLocationLoading != false}">
    						<div
    							class="country-wrapper"
    							:class="{ active: key == getCurrentLocation, loading: getLocationLoading == key }"
    							v-for="(country, key) in filterCountriesList"
    							:key="`country-${key}`"
    							:data-loading="!is_loading[key] || is_loading[key] == 'undefined' ? 'no' : 'yes'"
    							@click="selectCountry(key)"
    						>
    							<loader-bar
    								v-if="getLocationLoading == key"
    								:loading-indeterminant="true"
    							></loader-bar>
    							<div class="flag-wrapper" v-if="key.toLowerCase() !== 'wo'">
    								<flag :iso="key.toLowerCase()"></flag>
    							</div>
    							<div class="flag-wrapper world" v-if="key.toLowerCase() === 'wo'">
    								<i class="flag fas fa-globe"></i>
    							</div>
    							<div class="country-content">
    								<div class="country-name" :title="country.name">{{ country.name }}</div>
    								<div class="country-count-diff" :class="country.diff.type">
    									<span class="type-operator">
    										<span class="extra" v-if="country.diff.type == 'extra'">+</span>
    										<span class="extra" v-if="country.diff.type == 'less'">-</span>
    									</span>
    									<span class="diff-count">{{ country.diff.value.toLocaleString('en-US') }}</span>
    								</div>
    								<div class="country-count">{{ country.value.toLocaleString('en-US') }}</div>
    							</div>
    						</div>
    					</div>
    				</div>
    			</div>
    		</template>
    
    		<!-- Notify Template -->
    		<template id="notify-template">
    			<transition name="fadeslide">
    				<div id="notification" :class="type" v-if="show_notify">
    					<div class="icon">
    						<i class="fas fa-exclamation-triangle" v-if="type == 'error'"></i>
    						<i class="fas fa-check-circle" v-if="type == 'success'"></i>
    					</div>
    					<div class="text">{{message}}</div>
    				</div>
    			</transition>
    		</template>
    
    		<!-- Flag Template -->
    		<template id="flag-template">
    			<span class="flag">
    				<img :src="flag" />
    			</span>
    		</template>
    
    		<!-- Loader Bar Template -->
    		<template id="loader-bar-template">
    			<div class="loader-wrapper">
    				<div class="loader-bar" :class="{ indeterminant: loadingIndeterminant == true }">
    					<div class="loader-bar-loaded" :style="{ width: `${loadedPercentage}%` }"></div>
    				</div>
    				<div class="loader-text">{{ loadingText }}</div>
    			</div>
    		</template>
    
    		<!-- Worldmap Template -->
    		<template id="worldmap-template">
    			<div class="map-countries-container">
    				<loader-bar
    					v-if="loading == true"
    					:loading-text="loading_text"
    					:loaded-percentage="loaded_percentage"
    				></loader-bar>
    
    				<loader-bar
    					v-if="getLocationLoading != false"
    					loading-text="Loading Location Data"
    					:loading-indeterminant="true"
    				></loader-bar>
    
    				<div
    					class="map-container"
    					:data-status="getCurrentLocation != 'WO' ? 'single-location' : 'world'"
    					ref="world_map_container"
    					:style="getMapStyle"
    					@mouseleave="stopRotateMap"
    					@mousemove="rotateMap"
    				>
    					<div
    						class="reset-map"
    						:class="{ show: getCurrentLocation != 'WO' }"
    						@click="resetLocation()"
    					>
    						<i class="fas fa-home"></i>
    					</div>
    					<svg
    						xmlns="http://www.w3.org/2000/svg"
    						version="1.1"
    						ref="world_map"
    						:view-box.camel="viewbox"
    						:class="{loading: getLocationLoading != false}"
    					>
    						<g
    							v-for="(data, key) in getWorlMapWithColors"
    							:id="key"
    							:key="key"
    							:fill="data.color"
    							:ref="`location-${key}`"
    							stroke="white"
    							:data-count="data.value"
    							@click="selectLocation(key)"
    							@mouseenter="handleMoustEnter($event, key, data.value)"
    							@mouseleave="handleMoustOut"
    							@mousemove="handleMouseMove"
    							:class="{ active: key == getCurrentLocation, 'no-select': typeof getDayCaseByType[key] == 'undefined' }"
    							:data-status="getCurrentLocation == key ? 'selected' : ''"
    						>
    							<path
    								:d="data.path"
    								:key="`path-${key}`"
    								stroke-width="0.3"
    								stroke-opacity="0.5"
    							></path>
    						</g>
    					</svg>
    				</div>
    			</div>
    		</template>
    
    		<!-- Location details tooltip -->
    		<template id="location-tooltip-template">
    			<div id="location-tooltip" role="tooltip" ref="tooltip" :style="getTooltipStyle">
    				<div class="tooltip-inner">
    					<div class="tooltip-title">{{ this.getTooltipData.title }}</div>
    					<div class="tooltip-content" v-if="'count' in this.getTooltipData">
    						<div class="cases-type">
    							<span>{{ this.getTooltipData.count }}</span>
    							<span>{{ this.getTooltipData.type }}</span>
    						</div>
    						<div class="cases-diff">
    							<span>{{ this.getTooltipData.diff }}</span>
    							<span>Daily {{ this.getTooltipData.difftext }}</span>
    						</div>
    						<div class="cases-percentage">
    							<span>{{ this.getTooltipData.percentage }}%</span>
    							<span>Daily change</span>
    						</div>
    					</div>
    					<div v-else>No data available</div>
    				</div>
    				<div class="arrow" data-popper-arrow></div>
    			</div>
    		</template>
    
    		<!-- Series Tempmate -->
    		<template id="series-template">
    			<div class="series-data-wrapper">
    				<loader-bar
    					v-if="series_loading == true"
    					:loading-indeterminant="true"
    					loading-text="Loading Series"
    				></loader-bar>
    				<div class="series-data-options" v-if="series_loading == false">
    					<div class="bar-line-options">
    						<span class="bar" @click="chart_type = 'bar'" :class="{ active: chart_type == 'bar' }"
    							>Bar</span
    						>
    						<span
    							class="line"
    							@click="chart_type = 'line'"
    							:class="{ active: chart_type == 'line' }"
    							>Line</span
    						>
    					</div>
    					<div class="daily-weekly">
    						<span
    							class="daily"
    							@click="series_type = 'daily'"
    							:class="{ active: series_type == 'daily' }"
    							>Daily</span
    						>
    						<span
    							class="weekly"
    							@click="series_type = 'weekly'"
    							:class="{ active: series_type == 'weekly' }"
    							>Weekly</span
    						>
    					</div>
    					<div class="chart-data-representation">
    						<span
    							class="change"
    							@click="series_representation = 'change'"
    							:class="{ active: series_representation == 'change' }"
    							>Change</span
    						>
    						<span
    							class="cumulative"
    							@click="series_representation = 'cumulative'"
    							:class="{ active: series_representation == 'cumulative' }"
    							>Cumulative</span
    						>
    						<span
    							class="log"
    							@click="series_representation = 'log'"
    							:class="{ active: series_representation == 'log' }"
    							>Log</span
    						>
    					</div>
    				</div>
    				<div class="series-data" v-show="series_loading == false">
    					<canvas ref="chart"></canvas>
    				</div>
    				<div id="chartjs-tooltip">
    					<div class="title"></div>
    					<div class="count-wrapper">
    						<div class="count-total-type"></div>
    						<div class="count-total-number"></div>
    					</div>
    				</div>
    			</div>
    		</template>
    
    
    <script>
      
      const countriesIso = {
    	AF: 'Afghanistan',
    	AX: 'Åland Islands',
    	AL: 'Albania',
    	DZ: 'Algeria',
    	AS: 'American Samoa',
    	AD: 'Andorra',
    	AO: 'Angola',
    	AI: 'Anguilla',
    	AQ: 'Antarctica',
    	AG: 'Antigua and Barbuda',
    	AR: 'Argentina',
    	AM: 'Armenia',
    	AW: 'Aruba',
    	AU: 'Australia',
    	AT: 'Austria',
    	AZ: 'Azerbaijan',
    	BS: 'Bahamas',
    	BH: 'Bahrain',
    	BD: 'Bangladesh',
    	BB: 'Barbados',
    	BY: 'Belarus',
    	BE: 'Belgium',
    	BZ: 'Belize',
    	BJ: 'Benin',
    	BM: 'Bermuda',
    	BT: 'Bhutan',
    	BO: 'Bolivia',
    	BA: 'Bosnia and Herzegovina',
    	BW: 'Botswana',
    	BL: 'Saint Barthélemy',
    	BV: 'Bouvet Island',
    	BR: 'Brazil',
    	IO: 'British Indian Ocean Territory',
    	BN: 'Brunei Darussalam',
    	BQ: 'BONAIRE, SINT EUSTATIUS AND SABA',
    	BG: 'Bulgaria',
    	BF: 'Burkina Faso',
    	BI: 'Burundi',
    	KH: 'Cambodia',
    	CM: 'Cameroon',
    	CA: 'Canada',
    	CV: 'Cape Verde',
    	CW: 'Curaçao',
    	MF: 'Saint Martin',
    	KY: 'Cayman Islands',
    	CF: 'Central African Republic',
    	TD: 'Chad',
    	CL: 'Chile',
    	CN: 'China',
    	CX: 'Christmas Island',
    	CC: 'Cocos (Keeling) Islands',
    	CO: 'Colombia',
    	KM: 'Comoros',
    	CG: 'Congo',
    	CD: 'The Democratic Republic of the Congo',
    	CK: 'Cook Islands',
    	CR: 'Costa Rica',
    	CI: "Cote D'Ivoire",
    	HR: 'Croatia',
    	CU: 'Cuba',
    	CY: 'Cyprus',
    	CZ: 'Czech Republic',
    	DK: 'Denmark',
    	DJ: 'Djibouti',
    	DM: 'Dominica',
    	DO: 'Dominican Republic',
    	EC: 'Ecuador',
    	EG: 'Egypt',
    	SV: 'El Salvador',
    	GQ: 'Equatorial Guinea',
    	ER: 'Eritrea',
    	EE: 'Estonia',
    	ET: 'Ethiopia',
    	FK: 'Falkland Islands (Malvinas)',
    	FO: 'Faroe Islands',
    	FJ: 'Fiji',
    	FI: 'Finland',
    	FR: 'France',
    	GF: 'French Guiana',
    	PF: 'French Polynesia',
    	TF: 'French Southern Territories',
    	GA: 'Gabon',
    	GM: 'Gambia',
    	GE: 'Georgia',
    	DE: 'Germany',
    	GH: 'Ghana',
    	GI: 'Gibraltar',
    	GR: 'Greece',
    	GL: 'Greenland',
    	GD: 'Grenada',
    	GP: 'Guadeloupe',
    	GU: 'Guam',
    	GT: 'Guatemala',
    	GG: 'Guernsey',
    	GN: 'Guinea',
    	GW: 'Guinea-Bissau',
    	GY: 'Guyana',
    	HT: 'Haiti',
    	HM: 'Heard Island and Mcdonald Islands',
    	VA: 'Holy See (Vatican City State)',
    	HN: 'Honduras',
    	HK: 'Hong Kong',
    	HU: 'Hungary',
    	IS: 'Iceland',
    	IN: 'India',
    	ID: 'Indonesia',
    	IR: 'Islamic Republic Of Iran',
    	IQ: 'Iraq',
    	IE: 'Ireland',
    	IM: 'Isle of Man',
    	IL: 'Israel',
    	IT: 'Italy',
    	JM: 'Jamaica',
    	JP: 'Japan',
    	JE: 'Jersey',
    	JO: 'Jordan',
    	KZ: 'Kazakhstan',
    	KE: 'Kenya',
    	KI: 'Kiribati',
    	KP: "Democratic People's Republic of Korea",
    	KR: 'Republic of Korea',
    	XK: 'Kosovo',
    	KW: 'Kuwait',
    	KG: 'Kyrgyzstan',
    	LA: "Lao People's Democratic Republic",
    	LV: 'Latvia',
    	LB: 'Lebanon',
    	LS: 'Lesotho',
    	LR: 'Liberia',
    	LY: 'Libyan Arab Jamahiriya',
    	LI: 'Liechtenstein',
    	LT: 'Lithuania',
    	LU: 'Luxembourg',
    	MO: 'Macao',
    	MK: 'The Former Yugoslav Republic of Macedonia',
    	MG: 'Madagascar',
    	MW: 'Malawi',
    	MY: 'Malaysia',
    	MV: 'Maldives',
    	ML: 'Mali',
    	MT: 'Malta',
    	MH: 'Marshall Islands',
    	MQ: 'Martinique',
    	MR: 'Mauritania',
    	MU: 'Mauritius',
    	YT: 'Mayotte',
    	MX: 'Mexico',
    	FM: 'Federated States of Micronesia',
    	MD: 'Republic of Moldova',
    	MC: 'Monaco',
    	MN: 'Mongolia',
    	ME: 'Montenegro',
    	MS: 'Montserrat',
    	MA: 'Morocco',
    	MZ: 'Mozambique',
    	MM: 'Myanmar',
    	NA: 'Namibia',
    	NR: 'Nauru',
    	NP: 'Nepal',
    	NL: 'Netherlands',
    	AN: 'Netherlands Antilles',
    	NC: 'New Caledonia',
    	NZ: 'New Zealand',
    	NI: 'Nicaragua',
    	NE: 'Niger',
    	NG: 'Nigeria',
    	NU: 'Niue',
    	NF: 'Norfolk Island',
    	MP: 'Northern Mariana Islands',
    	NO: 'Norway',
    	OM: 'Oman',
    	PK: 'Pakistan',
    	PW: 'Palau',
    	PS: 'Occupied Palestinian Territory',
    	PA: 'Panama',
    	PG: 'Papua New Guinea',
    	PY: 'Paraguay',
    	PE: 'Peru',
    	PH: 'Philippines',
    	PN: 'Pitcairn',
    	PL: 'Poland',
    	PT: 'Portugal',
    	PR: 'Puerto Rico',
    	QA: 'Qatar',
    	RE: 'Reunion',
    	RO: 'Romania',
    	RU: 'Russian Federation',
    	RW: 'Rwanda',
    	SH: 'Saint Helena',
    	KN: 'Saint Kitts and Nevis',
    	LC: 'Saint Lucia',
    	PM: 'Saint Pierre and Miquelon',
    	VC: 'Saint Vincent and the Grenadines',
    	WS: 'Samoa',
    	SM: 'San Marino',
    	ST: 'Sao Tome and Principe',
    	SA: 'Saudi Arabia',
    	SN: 'Senegal',
    	RS: 'Serbia',
    	SC: 'Seychelles',
    	SL: 'Sierra Leone',
    	SG: 'Singapore',
    	SK: 'Slovakia',
    	SI: 'Slovenia',
    	SS: 'South Sudan',
    	SB: 'Solomon Islands',
    	SO: 'Somalia',
    	ZA: 'South Africa',
    	GS: 'South Georgia and the South Sandwich Islands',
    	ES: 'Spain',
    	LK: 'Sri Lanka',
    	SD: 'Sudan',
    	SR: 'Suriname',
    	SJ: 'Svalbard and Jan Mayen',
    	SZ: 'Swaziland',
    	SE: 'Sweden',
    	CH: 'Switzerland',
    	SY: 'Syrian Arab Republic',
    	TW: 'Taiwan',
    	TJ: 'Tajikistan',
    	TZ: 'United Republic of Tanzania',
    	TH: 'Thailand',
    	TL: 'Timor-Leste',
    	TG: 'Togo',
    	TK: 'Tokelau',
    	TO: 'Tonga',
    	TT: 'Trinidad and Tobago',
    	TN: 'Tunisia',
    	TR: 'Turkey',
    	TM: 'Turkmenistan',
    	TC: 'Turks and Caicos Islands',
    	TV: 'Tuvalu',
    	UG: 'Uganda',
    	UA: 'Ukraine',
    	SX: 'Sint Maarten',
    	AE: 'United Arab Emirates',
    	GB: 'United Kingdom',
    	US: 'United States',
    	UM: 'United States Minor Outlying Islands',
    	UY: 'Uruguay',
    	UZ: 'Uzbekistan',
    	VU: 'Vanuatu',
    	VE: 'Venezuela',
    	VN: 'Viet Nam',
    	VG: 'British Virgin Islands',
    	VI: 'U.S. Virgin Islands',
    	WF: 'Wallis and Futuna',
    	EH: 'Western Sahara',
    	YE: 'Yemen',
    	ZM: 'Zambia',
    	ZW: 'Zimbabwe',
    	WO: 'World'
    };
    const store = new Vuex.Store({
    	state: {
    		day_cases: {
    			by_locations: {
    				confirmed: [],
    				recovered: [],
    				deaths: []
    			},
    			max: {
    				confirmed: 0,
    				recovered: 0,
    				deaths: 0
    			}
    		},
    		displayed_series: {
    			aggregate: {
    				confirmed: [],
    				recovered: [],
    				deaths: []
    			},
    			by_locations: {
    				confirmed: [],
    				recovered: [],
    				deaths: []
    			},
    			max: {
    				confirmed: 0,
    				recovered: 0,
    				deaths: 0
    			},
    			total: {
    				confirmed: 0,
    				recovered: 0,
    				deaths: 0
    			}
    		},
    		all_series: {},
    		cases_type: 'confirmed',
    		current_location: '',
    		worldmap: {},
    		current_hover_location: '',
    		notify: {
    			show: false,
    			message: '',
    			type: 'error'
    		},
    		location_loading: false
    	},
    	mutations: {
    		update_location_loading(state, status) {
    			state.location_loading = status;
    		},
    		update_day_cases(state, payload) {
    			const cases = payload.data;
    			// Get max of each data series
    			state.day_cases = cases;
    		},
    		update_cases_type(state, type) {
    			state.cases_type = type;
    			// Set current hue to modify colors
    			const hue = getComputedStyle(document.documentElement).getPropertyValue(`--${type}-hue`);
    			document.documentElement.style.setProperty('--current-hue', hue);
    		},
    		update_displayed_series(state, data) {
    			state.series = data;
    		},
    		update_all_series(state, payload) {
    			const { data, extra } = payload;
    			const { iso } = extra;
    			state.all_series[iso] = data;
    		},
    		update_location(state, location) {
    			state.current_location = location;
    		},
    		update_world_map(state, payload) {
    			const map = payload.data;
    			state.worldmap = JSON.parse(map);
    		},
    		update_current_hover_location(state, iso) {
    			state.current_hover_location = iso;
    		},
    		update_notify(state, data) {
    			state.notify = { ...state.notify, ...data };
    		}
    	},
    	getters: {
    		getLocationLoading(state) {
    			return state.location_loading;
    		},
    		getNotifyDetails(state) {
    			return state.notify;
    		},
    		getCountriesList() {
    			return countriesIso;
    		},
    		getCurrentHoverLocation(state) {
    			return state.current_hover_location;
    		},
    		getWorldMap(state) {
    			return state.worldmap;
    		},
    		/**
    		 * Get world map path and value for each location
    		 *
    		 * @param {object} state
    		 * @param {object} getters
    		 */
    		getWorldMapData(state, getters) {
    			const cases = getters.getDayCaseByType;
    			const mapData = Object.keys(getters.getWorldMap).reduce((acc, key) => {
    				const value = cases[key]?.value || 0;
    				acc[key] = {
    					path: getters.getWorldMap[key],
    					value
    				};
    				return acc;
    			}, {});
    
    			return mapData.length === 0 ? [] : mapData;
    		},
    		/**
    		 * Retrun cases based on selected type ('confirmed', 'recovered', 'deaths')
    		 *
    		 * @param {object} state
    		 */
    		getDayCaseByType(state) {
    			const cases = state.day_cases.by_locations[state.cases_type];
    
    			const keys = Object.keys(cases).sort((a, b) => cases[b].value - cases[a].value);
    			const casesOrdered = {};
    			keys.forEach(k => (casesOrdered[k] = cases[k]));
    			return casesOrdered.length === 0 ? {} : casesOrdered;
    		},
    		/**
    		 * Get total day cases count
    		 *
    		 * @param {object} state
    		 */
    		getDayCasesTotalCount(state) {
    			const casesTypes = ['confirmed', 'deaths', 'recovered'];
    			const casesTotal = {};
    			casesTypes.forEach(caseType => {
    				casesTotal[caseType] =
    					state.day_cases.by_locations[caseType][state.current_location]?.value;
    			});
    			return casesTotal;
    		},
    		getMaxCountPerDay(state) {
    			const max = state.day_cases.max[state.cases_type];
    			return max || 0;
    		},
    		getDisplayedCasesType(state) {
    			return state.cases_type;
    		},
    		getAllSeries(state) {
    			return state.all_series;
    		},
    		getDisplayedSeries(state) {
    			return state.all_series[state.current_location];
    		},
    		getSeriesByCaseType(state, getters) {
    			return getters.getDisplayedSeries?.aggregate[state.cases_type] || [];
    		},
    		getCurrentLocation(state) {
    			return state.current_location;
    		}
    	},
    	actions: {
    		loadFromBackend({ commit }, { endpoint, request_data = {}, config = {}, mutation_key }) {
    			return new Promise((resolve, reject) => {
    				this._vm.$http
    					.post(endpoint, request_data, config)
    					.then(response => {
    						commit(mutation_key, { data: response.data, extra: request_data });
    						resolve(response.data);
    					})
    					.catch(error => {
    						commit('update_notify', { message: error, show: true });
    						reject(error.response);
    					});
    			});
    		}
    	}
    });
    const { mapGetters, mapMutations } = Vuex;
    
    let axi = axios.create({
    	baseURL: 'https://covid.kalimah-apps.com/wp-json/api/v1/',
    	// baseURL: 'http://kitab.test/wp-json/api/v1/',
    	timeout: 100000
    });
    Vue.prototype.$http = axi;
    Vue.component('loaderBar', {
    	template: '#loader-bar-template',
    	props: ['loading', 'loadingText', 'loadedPercentage', 'loadingIndeterminant']
    });
    
    Vue.component('countrieslist', {
    	template: '#countries-list-template',
    	data() {
    		return {
    			search_keywords: '',
    			is_loading: {}
    		};
    	},
    	computed: {
    		...mapGetters([
    			'getDayCaseByType',
    			'getCountriesList',
    			'getCurrentLocation',
    			'getAllSeries',
    			'getLocationLoading'
    		]),
    		getCasesWithCountriesNames() {
    			return Object.keys(this.getDayCaseByType).reduce((list, iso) => {
    				list[iso] = this.getDayCaseByType[iso];
    				list[iso].name = this.getCountriesList[iso];
    				return list;
    			}, {});
    		},
    		filterCountriesList() {
    			const locationsList = this.getCasesWithCountriesNames;
    			if (this.search_keywords === '') return locationsList;
    
    			return Object.keys(locationsList).reduce((list, iso) => {
    				const location = locationsList[iso];
    				if (iso !== 'none' && location.name.toLowerCase().indexOf(this.search_keywords) > -1) {
    					list[iso] = locationsList[iso];
    				}
    				return list;
    			}, {});
    		}
    	},
    	methods: {
    		...mapMutations(['update_location', 'update_location_loading']),
    		selectCountry(iso) {
    			// check if the data for this location has been loaded already
    			if (iso in this.getAllSeries) {
    				this.update_location(iso);
    				return;
    			}
    
    			// Don't process if there is another country data being loaded
    			if (this.getLocationLoading !== false) return;
    
    			// show loader
    			//this.$set(this.is_loading, iso, true);
    			this.update_location_loading(iso);
    
    			this.$store
    				.dispatch('loadFromBackend', {
    					endpoint: 'get-total-series',
    					request_data: { iso },
    					mutation_key: 'update_all_series'
    				})
    				.then(() => {
    					this.update_location(iso);
    					this.update_location_loading(false);
    				})
    				.catch(() => {
    					this.update_location_loading(false);
    				});
    		},
    		filterCountries(e) {
    			this.search_keywords = e.target.value.toLowerCase();
    		}
    	}
    });
    
    Vue.component('flag', {
    	template: '#flag-template',
    	props: ['iso'],
    	computed: {
    		flag() {
    			if (this.iso === 'none' || this.iso === '') return '';
    			//return `https://covid.kalimah-apps.com/index.php?flag_iso=${this.iso}`;
    			return `https://raw.githubusercontent.com/lipis/flag-icon-css/master/flags/4x3/${this.iso}.svg`;
    		}
    	}
    });
    
    Vue.component('location-tooltip', {
    	template: '#location-tooltip-template',
    	data() {
    		return {
    			tooltip_x: 0,
    			tooltip_y: 0,
    			show_tooltip: false
    		};
    	},
    	mounted() {
    		this.$root.$on('mouse_coord', coord => {
    			this.tooltip_x = coord.tooltip_x;
    			this.tooltip_y = coord.tooltip_y;
    		});
    
    		this.$root
    			.$on('tooltip_on', () => {
    				this.show_tooltip = true;
    			})
    			.$on('tooltip_off', () => {
    				this.show_tooltip = false;
    			});
    	},
    	computed: {
    		...mapGetters([
    			'getDayCaseByType',
    			'getCountriesList',
    			'getCurrentHoverLocation',
    			'getDisplayedCasesType'
    		]),
    		getTooltipData() {
    			const location = this.getCurrentHoverLocation;
    
    			if (location === 'WO' || location === '') return {};
    
    			const data = this.getDayCaseByType[location];
    			// Some countires (Turkminstan and Greenland) don't have data
    			if (typeof data === 'undefined') {
    				return {
    					title: this.getCountriesList[location]
    				};
    			}
    
    			// Get data and return an object
    			const dailyDiffValue = data.diff.value;
    			const dailyDiffType = data.diff.type;
    
    			// Make sure percentage is only showing two decimal points
    			const dailyPercentage = (data.diff.value * 100) / data.value;
    			const dailyPercentageRounded = Math.round(dailyPercentage * 100) / 100;
    
    			return {
    				title: this.getCountriesList[location],
    				type: this.getDisplayedCasesType,
    				count: data.value.toLocaleString('en-US'),
    				diff: dailyDiffValue.toLocaleString('en-US'),
    				difftext: dailyDiffType === 'extra' ? 'Increase' : 'Decrease',
    				percentage: dailyPercentageRounded
    			};
    		},
    		getTooltipStyle() {
    			const left = this.tooltip_x;
    			const top = this.tooltip_y;
    
    			return {
    				opacity: this.show_tooltip === true ? 1 : 0,
    				left: `${left}px`,
    				top: `${top}px`
    			};
    		}
    	}
    });
    
    Vue.component('notify', {
    	template: '#notify-template',
    	props: ['show', 'type', 'message'],
    	data() {
    		return {
    			show_notify: false
    		};
    	},
    	methods: {
    		...mapMutations(['update_notify'])
    	},
    	watch: {
    		show(newShowValue) {
    			this.show_notify = newShowValue;
    			if (newShowValue === false) return;
    			setTimeout(() => {
    				this.update_notify({ message: '', show: false });
    			}, 8000);
    		}
    	}
    });
    
    Vue.component('worldmap', {
    	template: '#worldmap-template',
    	data() {
    		return {
    			map_container: null,
    			map_svg: null,
    			loading: true,
    			loading_text: 'Loading Map',
    			loaded_percentage: 0,
    			viewbox: '0 267 1000 400',
    			show_tooltip_timer: null,
    			show_tooltip: false,
    			tooltip_x: 0,
    			tooltip_y: 0,
    			x_rotate: 0,
    			y_rotate: 0
    		};
    	},
    	mounted() {
    		this.$store.dispatch('loadFromBackend', {
    			endpoint: 'get-day-cases',
    			mutation_key: 'update_day_cases'
    		});
    		// Load world map on start
    		this.$store
    			.dispatch('loadFromBackend', {
    				endpoint: 'get-world-map',
    				mutation_key: 'update_world_map',
    				config: {
    					onDownloadProgress: progressEvent => {
    						const total = parseFloat(
    							progressEvent.currentTarget.getResponseHeader('x-map-filesize')
    						);
    						const current = progressEvent.loaded;
    
    						const percentCompleted = Math.floor((current / total) * 100);
    						this.loaded_percentage = percentCompleted;
    					}
    				}
    			})
    			.then(() => {
    				this.loading = false;
    			})
    			.catch(() => {
    				this.loading = false;
    			});
    
    		this.map_container = this.$refs.world_map_container;
    		this.map_svg = this.$refs.world_map;
    	},
    	methods: {
    		...mapMutations([
    			'update_location',
    			'update_current_hover_location',
    			'update_location_loading'
    		]),
    		resetLocation() {
    			this.update_location('WO');
    		},
    		/**
    		 * Rotate map on mouse move
    		 *
    		 * @param {object} e Event
    		 */
    		rotateMap(e) {
    			const rect = this.map_svg.getBoundingClientRect();
    			const left = e.x - rect.x;
    			const top = e.y - rect.y;
    			const horizontalMiddle = rect.height / 2;
    			const verticalMiddle = rect.width / 2;
    			this.x_rotate = (((top - horizontalMiddle) * 4) / horizontalMiddle) * -1;
    			this.y_rotate = ((left - verticalMiddle) * 4) / verticalMiddle;
    		},
    		stopRotateMap() {
    			setTimeout(() => {
    				this.x_rotate = 0;
    				this.y_rotate = 0;
    			}, 200);
    		},
    		selectLocation(iso) {
    			// Dont process click if not data available
    			const data = this.getDayCaseByType[iso];
    			if (typeof data === 'undefined') {
    				return;
    			}
    
    			// check if the data for this location has been loaded already
    			if (iso in this.getAllSeries) {
    				this.update_location(iso);
    				return;
    			}
    
    			// show loader
    			this.update_location_loading(true);
    
    			this.$store
    				.dispatch('loadFromBackend', {
    					endpoint: 'get-total-series',
    					request_data: { iso },
    					mutation_key: 'update_all_series'
    				})
    				.then(() => {
    					this.update_location(iso);
    					this.update_location_loading(false);
    				})
    				.catch(() => {
    					this.update_location_loading(false);
    				});
    		},
    		/**
    		 * Each additional decimal place means differnt range of lightness.
    		 * 100, 1000, 10000 and so on.
    		 * This function calculate the lightness within the range of the decimal places
    		 */
    		getLightRange(max, range) {
    			const split = max.toString().split('');
    			const l = split.length - 1;
    			return {
    				max: Math.round((50 / l) * range),
    				min: Math.round((50 / l) * range - 1)
    			};
    		},
    		/**
    		 * Get percentage number within a provided range
    		 */
    		getPercentageRangeNumber(min, max, percent) {
    			return Math.round(min + ((max - min) * percent) / 50);
    		},
    		/**
    		 * Get color of location based on its value
    		 * Darker means higher value
    		 */
    		getColor(value) {
    			// Get decimal places
    			const decimalPlaces = value.toString().split('').length;
    			const maxCount = this.getMaxCountPerDay;
    
    			// Get lightness percentage between 0 and 50
    			const lightnessPercent = Math.round((value * 50) / maxCount);
    			const range = this.getLightRange(maxCount, decimalPlaces);
    			const adjustedLightnessPercentage = this.getPercentageRangeNumber(
    				range.min,
    				range.max,
    				lightnessPercent
    			);
    
    			const hueColor = `${this.getCurrentHueColor()}deg`;
    			/*
    			 * return hsl color. 80  is used to reverse colors
    			 * to represent higher values with dark color accents and
    			 * lower values with light color accents
    			 */
    			return `hsl(${hueColor}, 70%, ${80 - adjustedLightnessPercentage}%)`;
    		},
    		/**
    		 * Handle mouse enter on specific location to show tooltip
    		 *
    		 * @param {object} event
    		 * @param {string} iso
    		 */
    		handleMoustEnter(event, iso) {
    			clearTimeout(this.show_tooltip_timer);
    			this.update_current_hover_location(iso);
    			this.$root.$emit('tooltip_on');
    		},
    		/**
    		 * Emit coordinates on mouse move to move tooltip
    		 *
    		 * @param {object} e Mouse event object
    		 */
    		handleMouseMove(e) {
    			this.$root.$emit('mouse_coord', { tooltip_x: e.pageX, tooltip_y: e.pageY });
    		},
    		/**
    		 * Hide tooltip on mouse out
    		 */
    		handleMoustOut() {
    			clearTimeout(this.show_tooltip_timer);
    			this.show_tooltip_timer = setTimeout(() => {
    				// this.show_tooltip = false;
    				this.$root.$emit('tooltip_off');
    			}, 100);
    		},
    
    		getCurrentHueColor() {
    			return getComputedStyle(document.documentElement).getPropertyValue('--current-hue');
    		}
    	},
    	computed: {
    		...mapGetters([
    			'getDayCaseByType',
    			'getWorldMapData',
    			'getMaxCountPerDay',
    			'getDisplayedCasesType',
    			'getCountriesList',
    			'getCurrentLocation',
    			'getAllSeries',
    			'getCurrentHoverLocation',
    			'getLocationLoading'
    		]),
    
    		getMapStyle() {
    			return {
    				'--map-rotate-x': `${this.x_rotate}deg`,
    				'--map-rotate-y': `${this.y_rotate}deg`
    			};
    		},
    		/**
    		 * Return world map data with choropleth hsl values
    		 */
    		getWorlMapWithColors() {
    			return Object.keys(this.getWorldMapData).reduce((acc, key) => {
    				acc[key] = this.getWorldMapData[key];
    				acc[key].color = this.getColor(acc[key].value);
    				return acc;
    			}, {});
    		},
    		getMaxCount() {
    			return Object.keys(this.getWorldMapData);
    		}
    	},
    	watch: {
    		getWorlMapWithColors() {
    			this.$nextTick(() => {});
    		},
    		getCurrentLocation(newLocationsIso) {
    			const iso = newLocationsIso;
    			// let viewbox = '0 0 700.9375 337.375';
    			let viewbox = '0 267.77886962890625 1000 400';
    
    			// get locations iso (if world is not selected)
    			if (iso !== 'WO' && this.map_svg != null) {
    				const { width, height, x, y } = document.querySelector(`#${iso}`).getBBox();
    				const halfWidth = width / 2;
    				const halfHeight = height / 2;
    				viewbox = `${x - halfWidth} ${y - halfHeight} ${width + width} ${height + height}`;
    			}
    			// animate viewbox for selected ISO
    			TweenLite.to(this.$data, {
    				duration: 1.5,
    				ease: 'expo.out',
    				viewbox: viewbox
    			});
    		}
    	}
    });
    
    Vue.component('series', {
    	template: '#series-template',
    	data() {
    		return {
    			chart: null,
    			chart_type: 'bar',
    			series_type: 'daily',
    			series_representation: 'change',
    			series_loading: true,
    			monthNames: [
    				'Jan',
    				'Feb',
    				'Mar',
    				'Apr',
    				'May',
    				'Jun',
    				'Jul',
    				'Aug',
    				'Sep',
    				'Oct',
    				'Nov',
    				'Dec'
    			]
    		};
    	},
    	mounted() {
    		// Check if there is data in localStorage and apply it
    		const keys = ['chart_type', 'series_type', 'series_representation'];
    		keys.forEach(k => {
    			const stateValue = localStorage.getItem(k);
    			if (stateValue != null) this[k] = stateValue;
    		});
    		/**
    		 * Show a dashed line vertically on line graphs
    		 */
    		Chart.plugins.register({
    			afterDatasetDraw: (chart, dataset) => {
    				if (chart.tooltip._active && chart.tooltip._active.length && dataset.meta.type === 'line') {
    					const activePoint = chart.tooltip._active[0];
    					const { ctx } = chart;
    					const yAxis = chart.scales['y-axis-0'];
    					const { x } = activePoint.tooltipPosition();
    					const topY = yAxis.top;
    					const bottomY = yAxis.bottom; // activePoint.tooltipPosition().y;
    
    					// Get current hue and darken it
    					const currentHue = this.getCurrentHueColor();
    
    					// draw line
    					ctx.save();
    					ctx.beginPath();
    					ctx.setLineDash([3, 3]);
    					ctx.moveTo(x, topY);
    					ctx.lineTo(x, bottomY);
    					ctx.lineWidth = 1;
    					ctx.strokeStyle = `hsla(${currentHue}deg, 100%, 15%, 0.8)`;
    					ctx.stroke();
    					ctx.restore();
    				}
    			}
    		});
    
    		// Setup chart
    		Chart.defaults.scale.gridLines.drawOnChartArea = false;
    		this.chart = new Chart(this.$refs.chart, {
    			type: 'bar',
    			data: {
    				labels: [],
    				datasets: [
    					{
    						label: 'Count',
    						backgroundColor: '#3e95cd',
    						hoverBackgroundColor: 'blue'
    					},
    					{
    						label: 'Count',
    						fill: false,
    						type: 'line',
    						pointRadius: 0,
    						pointHoverRadius: 6,
    						pointHoverBackgroundColor: 'red',
    						pointHoverBorderWidth: 0,
    						hidden: true
    					}
    				]
    			},
    			options: {
    				hover: {
    					mode: 'index',
    					intersect: false,
    					animationDuration: 0
    				},
    				tooltips: {
    					intersect: false,
    					enabled: false,
    					mode: 'index',
    					/**
    					 * Custom tooltip with div
    					 */
    					custom(tooltipModel) {
    						// Tooltip Element
    						const tooltipEl = document.querySelector('#chartjs-tooltip');
    						const title = tooltipEl.querySelector('.title');
    						const body = tooltipEl.querySelector('.count-total-number');
    
    						// Hide/show  tooltip
    						tooltipEl.style.opacity = tooltipModel.opacity;
    
    						// Set Text
    						if (tooltipModel.body) {
    							const titleLines = tooltipModel.title || [];
    							const bodyLines = tooltipModel.body.map(bodyItem => bodyItem.lines);
    							title.innerHTML = titleLines[0];
    							body.innerHTML = bodyLines[0];
    						}
    
    						tooltipEl.style.left = `${tooltipModel.caretX}px`;
    					},
    					callbacks: {
    						label: tooltipItem => {
    							let label = this.getDisplayedCasesType;
    
    							if (label) {
    								label += ': ';
    							}
    							label += tooltipItem.yLabel.toLocaleString('en-US');
    							return label;
    						}
    					}
    				},
    				maintainAspectRatio: false,
    				legend: { display: false },
    				scales: {
    					yAxes: [
    						{
    							ticks: {
    								beginAtZero: true,
    								callback: value => this.format(value)
    							}
    						}
    					],
    					xAxes: [
    						{
    							type: 'time',
    							offset: true
    						}
    					]
    				}
    			}
    		});
    
    		// check if the data for this location has been loaded already
    		if ('WO' in this.getAllSeries) {
    			this.update_location('WO');
    			this.series_loading = false;
    			return;
    		}
    
    		this.$store
    			.dispatch('loadFromBackend', {
    				endpoint: 'get-total-series',
    				request_data: { iso: 'WO' },
    				mutation_key: 'update_all_series'
    			})
    			.then(() => {
    				this.series_loading = false;
    				this.update_location('WO');
    				this.updateChart();
    			})
    			.catch(() => {
    				this.series_loading = false;
    			});
    	},
    	methods: {
    		...mapMutations(['update_location']),
    		/**
    		 * Format long numbers to display short numbers with B for billions,
    		 * M for millions and K for thousands
    		 */
    		format(num) {
    			const number = Math.abs(Number(num));
    			let formattedNumber = number;
    			// Nine Zeroes for Billions
    			switch (true) {
    				case number >= 1.0e9:
    					formattedNumber = `${Math.round(number) / 1.0e9} B`;
    					break;
    				case number >= 1.0e6:
    					formattedNumber = `${Math.round(number) / 1.0e6} M`;
    					break;
    				case number >= 1.0e3:
    					formattedNumber = `${Math.round(number) / 1.0e3} K`;
    					break;
    				default:
    					formattedNumber = number;
    					break;
    			}
    
    			return formattedNumber;
    		},
    		getCurrentHueColor() {
    			return getComputedStyle(document.documentElement).getPropertyValue('--current-hue');
    		},
    		/**
    		 * Update chart to reflect changes. FromTo daily and weekly. FromTo bar and line,
    		 * FromTo cumlative, change and log
    		 */
    		updateChart(enableAnimation = false) {
    			const newType = this.series_type;
    			const seriesData = this.getSeriesByCaseType;
    
    			if (seriesData.length === 0) return;
    
    			const data = [];
    			const labels = [];
    			let xAxes = {};
    			const rep = this.series_representation;
    			// if series type is set week, aggregate data
    			if (newType === 'weekly') {
    				let lastWeek = 0;
    				let count = 0;
    				seriesData.forEach(series => {
    					const currentWeek = moment(series.date).week();
    					count += rep === 'cumulative' ? parseInt(series.value) : parseInt(series.diff.value);
    					if (lastWeek !== currentWeek) {
    						labels.push(series.date);
    						data.push(count);
    						count = 0;
    						lastWeek = currentWeek;
    					}
    				});
    
    				xAxes = {
    					barPercentage: 1.1,
    					categoryPercentage: 1.2,
    					time: {
    						unit: 'week',
    						unitStepSize: 5,
    						displayFormats: { week: 'w - YYYY' }
    					}
    				};
    			} else {
    				seriesData.forEach(series => {
    					data.push(rep === 'cumulative' ? series.value : series.diff.value);
    					labels.push(series.date);
    				});
    				xAxes = {
    					barPercentage: 0.8,
    					categoryPercentage: 0.9,
    					time: {
    						unit: 'month',
    						unitStepSize: 1,
    						displayFormats: { month: 'MMM YYYY' }
    					}
    				};
    			}
    
    			// update x axes
    			this.chart.options.scales.xAxes[0] = { ...this.chart.options.scales.xAxes[0], ...xAxes };
    
    			// Show logarthmic or linear scale
    			let yAxesType = 'linear';
    			if (this.series_representation === 'log') yAxesType = 'logarithmic';
    			this.chart.options.scales.yAxes[0].type = yAxesType;
    
    			// update dataset
    			this.chart.data.datasets.forEach((dataset, i) => {
    				dataset.data = data;
    				// updte color baased on series selected
    				dataset.backgroundColor = `hsl(${this.getCurrentHueColor()}deg, 80%, 50%)`;
    				dataset.borderColor = `hsl(${this.getCurrentHueColor()}deg, 80%, 50%)`;
    
    				// Bar hover color
    				dataset.hoverBackgroundColor = `hsl(${this.getCurrentHueColor()}deg, 100%, 10%)`;
    
    				// line point (circle) background color and border color
    				dataset.pointHoverBackgroundColor = `hsl(${this.getCurrentHueColor()}deg, 80%, 50%)`;
    				dataset.pointHoverBorderColor = `hsl(${this.getCurrentHueColor()}deg, 80%, 50%)`;
    
    				// Hide/show dataset based on chart type
    				if (this.chart_type === 'bar') {
    					dataset.hidden = i !== 0;
    				} else {
    					dataset.hidden = i !== 1;
    				}
    			});
    			this.chart.data.labels = labels;
    			if (!enableAnimation) this.chart.update(0);
    			else this.chart.update();
    		}
    	},
    	computed: {
    		...mapGetters(['getSeriesByCaseType', 'getDisplayedCasesType', 'getAllSeries'])
    	},
    	watch: {
    		chart_type(newType) {
    			localStorage.setItem('chart_type', newType);
    			this.updateChart(true);
    		},
    		series_type(newType) {
    			localStorage.setItem('series_type', newType);
    			this.updateChart();
    		},
    		series_representation(newRepresentation) {
    			localStorage.setItem('series_representation', newRepresentation);
    			this.updateChart(true);
    		},
    		getDisplayedCasesType() {
    			// update chart
    			this.updateChart(true);
    		},
    		getSeriesByCaseType() {
    			this.updateChart(true);
    		}
    	}
    });
    new Vue({
    	el: '#app',
    	store,
    	data: {
    		show_countries_list: false,
    		confirmed: 0,
    		recovered: 0,
    		deaths: 0,
    		show_copyright: false,
    		is_full_screen: false,
    		copyright_data: {
    			'Covid Data': 'https://github.com/CSSEGISandData/COVID-19',
    			Flags: 'https://github.com/lipis/flag-icon-css',
    			Map: 'https://github.com/markmarkoh/datamaps',
    			FontAwesome: 'https://fontawesome.com/',
    			'Chart.js': 'https://www.chartjs.org/',
    			gsap: 'https://greensock.com/gsap/',
    			'moment.js': 'https://momentjs.com/',
    			'Subtle Patterns': 'https://www.toptal.com/designers/subtlepatterns/'
    		}
    	},
    	methods: {
    		...mapMutations({ changeCaseType: 'update_cases_type' }),
    		enterFullScreen() {
    			const element = document.querySelector('#app');
    			const requestFullScreen =
    				element.requestFullscreen ||
    				element.webkitRequestFullScreen ||
    				element.mozRequestFullScreen ||
    				element.msRequestFullScreen;
    			requestFullScreen.call(element);
    		},
    		exitFullScreen() {
    			const cancellFullScreen =
    				document.exitFullscreen ||
    				document.mozCancelFullScreen ||
    				document.webkitExitFullscreen ||
    				document.msExitFullscreen;
    			cancellFullScreen.call(document);
    		}
    	},
    	computed: {
    		...mapGetters([
    			'getDayCasesTotalCount',
    			'getDisplayedCasesType',
    			'getCurrentLocation',
    			'getCountriesList',
    			'getNotifyDetails'
    		]),
    		recoveredCount() {
    			return Number.isNaN(this.recovered) ? 'No Data' : this.recovered.toLocaleString('en-US');
    		},
    		deathsCount() {
    			return this.deaths.toLocaleString('en-US');
    		},
    		confirmedCount() {
    			return this.confirmed.toLocaleString('en-US');
    		}
    	},
    	watch: {
    		/**
    		 * Animate count change on every update
    		 */
    		getDayCasesTotalCount(newTotals) {
    			Object.keys(newTotals).forEach(caseType => {
    				TweenLite.to(this.$data, 1, {
    					[caseType]: newTotals[caseType],
    					roundProps: caseType,
    					ease: 'expo.out'
    				});
    			});
    		},
    		is_full_screen(newValue) {
    			if (newValue === true) this.enterFullScreen();
    			else this.exitFullScreen();
    		}
    	}
    });
      </script>