Compare commits
	
		
			5 Commits
		
	
	
		
			9dfc567d5c
			...
			translatio
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| a886d6575f | |||
| 8124b08b88 | |||
| e80902e965 | |||
| c078eaa6c5 | |||
| 75a6df9d9d | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						@@ -0,0 +1,2 @@
 | 
			
		||||
node_modules/
 | 
			
		||||
public/bundle.js*
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,11 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
steps:
 | 
			
		||||
 | 
			
		||||
  build:
 | 
			
		||||
    image: node:latest
 | 
			
		||||
    commands:
 | 
			
		||||
      - npm install
 | 
			
		||||
      - npm run build
 | 
			
		||||
  deploy:
 | 
			
		||||
    image: appleboy/drone-scp
 | 
			
		||||
    settings:
 | 
			
		||||
@@ -14,6 +18,6 @@ steps:
 | 
			
		||||
        from_secret: ssh_user
 | 
			
		||||
      target:
 | 
			
		||||
        from_secret: path
 | 
			
		||||
      source: src/
 | 
			
		||||
      source: public/
 | 
			
		||||
      key:
 | 
			
		||||
        from_secret: ssh_key
 | 
			
		||||
							
								
								
									
										10
									
								
								i18next-parser.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,10 @@
 | 
			
		||||
module.exports = {
 | 
			
		||||
    defaultNamespace: 'translation',
 | 
			
		||||
    lexers: {
 | 
			
		||||
        js: ['JsxLexer'], // we're writing jsx inside .js files
 | 
			
		||||
        default: ['JavascriptLexer'],
 | 
			
		||||
    },
 | 
			
		||||
    locales: ['en', 'de'],
 | 
			
		||||
    output: 'public/lang/$LOCALE.json',
 | 
			
		||||
    input: [ 'src/*.js', 'public/*.html', ],
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5269
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										31
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,31 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "kaefigrechner",
 | 
			
		||||
  "version": "0.0.1",
 | 
			
		||||
  "description": "Ein Rechner für die minimale Größe eines Rattenkäfigs nach Standard des VdRD e.V.",
 | 
			
		||||
  "main": "index.js",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "start": "webpack-dev-server --config webpack.config.js",
 | 
			
		||||
    "ex-trans": "i18next -c i18next-parser.config.js",
 | 
			
		||||
    "build": "webpack --config webpack.config.js"
 | 
			
		||||
  },
 | 
			
		||||
  "repository": {
 | 
			
		||||
    "type": "git",
 | 
			
		||||
    "url": "https://git.hyteck.de/moanos/RattenheimRechner"
 | 
			
		||||
  },
 | 
			
		||||
  "keywords": [
 | 
			
		||||
    "animal",
 | 
			
		||||
    "welfare"
 | 
			
		||||
  ],
 | 
			
		||||
  "author": "Julian-Samuel Gebühr",
 | 
			
		||||
  "license": "AGPL-3.0-or-later",
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "webpack": "^5.93.0",
 | 
			
		||||
    "webpack-cli": "^5.1.4",
 | 
			
		||||
    "webpack-dev-server": "^5.0.4"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "i18next": "^23.12.2",
 | 
			
		||||
    "i18next-browser-languagedetector": "^8.0.0",
 | 
			
		||||
    "i18next-http-backend": "^2.5.2"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB  | 
| 
		 Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB  | 
| 
		 Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB  | 
| 
		 Before Width: | Height: | Size: 432 B After Width: | Height: | Size: 432 B  | 
| 
		 Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB  | 
| 
		 Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB  | 
| 
		 Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB  | 
							
								
								
									
										1
									
								
								public/assets/img/info.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1 @@
 | 
			
		||||
<svg class="text-grey-dark" width="18" height="18" viewBox="0 0 18 18" fill="none" stroke="currentColor"><path d="M9.00026 12.6C9.00026 12.6 9.00026 12.1224 9.00026 11.5333V8.86666C9.00026 8.57211 8.76148 8.33333 8.46693 8.33333H7.93359" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M8.73346 5.26666C8.58619 5.26666 8.4668 5.38605 8.4668 5.53333C8.4668 5.68061 8.58619 5.8 8.73346 5.8C8.88074 5.8 9.00013 5.68061 9.00013 5.53333C9.00013 5.38605 8.88074 5.26666 8.73346 5.26666V5.26666" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M9 17C13.4183 17 17 13.4183 17 9C17 4.58172 13.4183 1 9 1C4.58172 1 1 4.58172 1 9C1 13.4183 4.58172 17 9 17Z" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 834 B  | 
| 
		 Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB  | 
| 
		 Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB  | 
| 
		 Before Width: | Height: | Size: 546 B After Width: | Height: | Size: 546 B  | 
| 
		 Before Width: | Height: | Size: 3.2 MiB After Width: | Height: | Size: 3.2 MiB  | 
| 
		 Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB  | 
| 
		 Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB  | 
| 
		 Before Width: | Height: | Size: 639 B After Width: | Height: | Size: 639 B  | 
							
								
								
									
										121
									
								
								public/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,121 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en" xmlns="http://www.w3.org/1999/html" xmlns="http://www.w3.org/1999/html">
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="UTF-8">
 | 
			
		||||
    <title>Käfigrechner</title>
 | 
			
		||||
    <link rel="stylesheet" href="assets/css/style.css">
 | 
			
		||||
    <script src="assets/js/calculator.js"></script>
 | 
			
		||||
 | 
			
		||||
    <link rel="apple-touch-icon" sizes="180x180" href="assets/favicon/apple-touch-icon.png">
 | 
			
		||||
    <link rel="icon" type="image/png" sizes="32x32" href="assets/favicon/favicon-32x32.png">
 | 
			
		||||
    <link rel="icon" type="image/png" sizes="16x16" href="assets/favicon/favicon-16x16.png">
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
 | 
			
		||||
<div class="navigation-sticky">
 | 
			
		||||
    <a href="https://notfellchen.org">
 | 
			
		||||
        <b data-i18n-key="back-to-home">zurück zur Homepage</b>
 | 
			
		||||
    </a>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<img src="img/translation-icon@2x.png" class="translation-icon" /   >
 | 
			
		||||
<select data-i18n-switcher class="locale-switcher">
 | 
			
		||||
    <option value="en">English</option>
 | 
			
		||||
    <option value="de">Deutsch</option>
 | 
			
		||||
</select>
 | 
			
		||||
 | 
			
		||||
<div class="content">
 | 
			
		||||
    <h1 data-i18n-key="app-name">Käfigrechner</h1>
 | 
			
		||||
    <div class="container-form">
 | 
			
		||||
        <div class="cards">
 | 
			
		||||
            <div class="card" id="card-SavicSuiteRoyaleXL">
 | 
			
		||||
                <label for="SavicSuiteRoyaleXL">
 | 
			
		||||
                    <input type="checkbox" id="SavicSuiteRoyaleXL"/>
 | 
			
		||||
                    <div class="card-photo">
 | 
			
		||||
                        <img src="assets/img/savic-xl.jpeg">
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="info-container">
 | 
			
		||||
                        <h4><b>Savic Suite Royale XL</b></h4>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </label>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="card" id="card-SavicSuiteRoyale95Double">
 | 
			
		||||
                <label for="SavicSuiteRoyale95Double">
 | 
			
		||||
                    <input type="checkbox" id="SavicSuiteRoyale95Double"/>
 | 
			
		||||
                    <div class="card-photo">
 | 
			
		||||
                        <div>
 | 
			
		||||
                            <img src="assets/img/savic-95-double.jpg">
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div class="info-container">
 | 
			
		||||
                            <h4><b>Savic Suite Royale 95 Double</b></h4>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </label>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="card" id="card-TiakiKleintierkäfigEtagere">
 | 
			
		||||
                <label for="TiakiKleintierkäfigEtagere">
 | 
			
		||||
                    <input type="checkbox" id="TiakiKleintierkäfigEtagere"/>
 | 
			
		||||
                    <div class="card-photo">
 | 
			
		||||
                        <img src="assets/img/tiaki.jpeg">
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="info-container">
 | 
			
		||||
                        <h4><b>TIAKI Kleintierkäfig Étagère</b></h4>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </label>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="card" id="card-ManualMeasurements">
 | 
			
		||||
                <label for="form-cage-measurements">Käfigmaße</label>
 | 
			
		||||
                <form id="form-cage-measurements" class="form-measurements">
 | 
			
		||||
                    <div class="input-measurement">
 | 
			
		||||
                        <label for="width" data-i18n-key="width-cm">Breite (cm)</label>
 | 
			
		||||
                        <input class="measurement" type="number" id="width">
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="input-measurement">
 | 
			
		||||
                        <label for="depth" data-i18n-key="depth-cm">Tiefe (cm)</label>
 | 
			
		||||
                        <input class="measurement" type="number" id="depth">
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="input-measurement">
 | 
			
		||||
                        <label for="height" data-i18n-key="height-cm">Höhe (cm)</label>
 | 
			
		||||
                        <input class="measurement" type="number" id="height">
 | 
			
		||||
                    </div>
 | 
			
		||||
                </form>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="container-inputs">
 | 
			
		||||
        <div class="input-element">
 | 
			
		||||
            <label for="numFullFloors" data-i18n-key="full-floors">Vollebenen</label>
 | 
			
		||||
            <div class="tooltip">
 | 
			
		||||
                <svg class="text-grey-dark" width="18" height="18" viewBox="0 0 18 18" fill="none" stroke="currentColor"><path d="M9.00026 12.6C9.00026 12.6 9.00026 12.1224 9.00026 11.5333V8.86666C9.00026 8.57211 8.76148 8.33333 8.46693 8.33333H7.93359" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M8.73346 5.26666C8.58619 5.26666 8.4668 5.38605 8.4668 5.53333C8.4668 5.68061 8.58619 5.8 8.73346 5.8C8.88074 5.8 9.00013 5.68061 9.00013 5.53333C9.00013 5.38605 8.88074 5.26666 8.73346 5.26666V5.26666" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M9 17C13.4183 17 17 13.4183 17 9C17 4.58172 13.4183 1 9 1C4.58172 1 1 4.58172 1 9C1 13.4183 4.58172 17 9 17Z" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>
 | 
			
		||||
                <span class="tooltiptext" data-i18n-key="full-floors-tooltip">Als Vollebenen zählen alle Ebenen die größer als 0.5m² sind, inklusive des Käfigbodens.</span>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="ncontainer">
 | 
			
		||||
                <div class="input-group">
 | 
			
		||||
                    <button id="decreaseFloorNum">-</button>
 | 
			
		||||
                    <input type="text" id="numFullFloors" value="3" readonly>
 | 
			
		||||
                    <button id="increaseFloorNum">+</button>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="input-element">
 | 
			
		||||
            <div class="slidecontainer">
 | 
			
		||||
                <label for="numRats" id="labelNumRats" data-i18n-key="number-of-rats">Anzahl an Ratten ?</label>
 | 
			
		||||
                <input type="range" min="3" max="15" value="4" class="slider" id="numRats">
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="container output-element" id="resultsDiv">
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<script src="./bundle.js"></script>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										10
									
								
								public/lang/de.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,10 @@
 | 
			
		||||
{
 | 
			
		||||
  "back-to-home": "Zurück zur Homepage",
 | 
			
		||||
  "app-name": "Käfigrechner",
 | 
			
		||||
  "number-of-rats": "Anzahl an Ratten",
 | 
			
		||||
  "full-floors": "Vollebenen",
 | 
			
		||||
  "width-cm": "Breite (cm)",
 | 
			
		||||
  "depth-cm": "Tiefe (cm)",
 | 
			
		||||
  "height-cm": "Höhe (cm)",
 | 
			
		||||
  "full-floors-tooltip": "Als Vollebenen zählen alle Ebenen die größer als 0.5m² sind, inklusive des Käfigbodens."
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								public/lang/en.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,10 @@
 | 
			
		||||
{
 | 
			
		||||
  "back-to-home": "Back to home",
 | 
			
		||||
  "app-name": "Cage Calculator",
 | 
			
		||||
  "number-of-rats": "Number of Rats",
 | 
			
		||||
  "full-floors": "Full floors",
 | 
			
		||||
  "width-cm": "Width (cm)",
 | 
			
		||||
  "depth-cm": "Depth (cm)",
 | 
			
		||||
  "height-cm": "Height (cm)",
 | 
			
		||||
  "full-floors-tooltip": "A full floor is each floor with a area greater than 0.5m², including the bottom of the cage."
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										252
									
								
								src/index.html
									
									
									
									
									
								
							
							
						
						@@ -1,252 +0,0 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en" xmlns="http://www.w3.org/1999/html" xmlns="http://www.w3.org/1999/html">
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="UTF-8">
 | 
			
		||||
    <title>Käfigrechner</title>
 | 
			
		||||
    <link rel="stylesheet" href="assets/css/style.css">
 | 
			
		||||
    <script src="assets/calculator.js"></script>
 | 
			
		||||
 | 
			
		||||
    <link rel="apple-touch-icon" sizes="180x180" href="assets/favicon/apple-touch-icon.png">
 | 
			
		||||
    <link rel="icon" type="image/png" sizes="32x32" href="assets/favicon/favicon-32x32.png">
 | 
			
		||||
    <link rel="icon" type="image/png" sizes="16x16" href="assets/favicon/favicon-16x16.png">
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
 | 
			
		||||
<div class="navigation-sticky">
 | 
			
		||||
    <a href="https://notfellchen.org">
 | 
			
		||||
        <b>zurück zur Homepage</b>
 | 
			
		||||
    </a>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<div class="content">
 | 
			
		||||
    <h1>Käfigrechner</h1>
 | 
			
		||||
    <div class="container-form">
 | 
			
		||||
        <div class="cards">
 | 
			
		||||
            <div class="card" id="card-SavicSuiteRoyaleXL">
 | 
			
		||||
                <label for="SavicSuiteRoyaleXL">
 | 
			
		||||
                    <input type="checkbox" id="SavicSuiteRoyaleXL"/>
 | 
			
		||||
                    <div class="card-photo">
 | 
			
		||||
                        <img src="assets/img/savic-xl.jpeg">
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="info-container">
 | 
			
		||||
                        <h4><b>Savic Suite Royale XL</b></h4>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </label>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="card" id="card-SavicSuiteRoyale95Double">
 | 
			
		||||
                <label for="SavicSuiteRoyale95Double">
 | 
			
		||||
                    <input type="checkbox" id="SavicSuiteRoyale95Double"/>
 | 
			
		||||
                    <div class="card-photo">
 | 
			
		||||
                        <div>
 | 
			
		||||
                            <img src="assets/img/savic-95-double.jpg">
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div class="info-container">
 | 
			
		||||
                            <h4><b>Savic Suite Royale 95 Double</b></h4>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </label>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="card" id="card-TiakiKleintierkäfigEtagere">
 | 
			
		||||
                <label for="TiakiKleintierkäfigEtagere">
 | 
			
		||||
                    <input type="checkbox" id="TiakiKleintierkäfigEtagere"/>
 | 
			
		||||
                    <div class="card-photo">
 | 
			
		||||
                        <img src="assets/img/tiaki.jpeg">
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="info-container">
 | 
			
		||||
                        <h4><b>TIAKI Kleintierkäfig Étagère</b></h4>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </label>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="card" id="card-ManualMeasurements">
 | 
			
		||||
                <label for="form-cage-measurements">Käfigmaße</label>
 | 
			
		||||
                <form id="form-cage-measurements" class="form-measurements">
 | 
			
		||||
                    <div class="input-measurement">
 | 
			
		||||
                        <label for="width">Breite (cm)</label>
 | 
			
		||||
                        <input class="measurement" type="number" id="width">
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="input-measurement">
 | 
			
		||||
                        <label for="depth">Tiefe (cm)</label>
 | 
			
		||||
                        <input class="measurement" type="number" id="depth">
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="input-measurement">
 | 
			
		||||
                        <label for="height">Höhe (cm)</label>
 | 
			
		||||
                        <input class="measurement" type="number" id="height">
 | 
			
		||||
                    </div>
 | 
			
		||||
                </form>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="container-inputs">
 | 
			
		||||
        <div class="input-element">
 | 
			
		||||
            <label for="numFullFloors">Vollebenen</label>
 | 
			
		||||
            <div class="tooltip">
 | 
			
		||||
                <svg class="text-grey-dark" width="18" height="18" viewBox="0 0 18 18" fill="none" stroke="currentColor"><path d="M9.00026 12.6C9.00026 12.6 9.00026 12.1224 9.00026 11.5333V8.86666C9.00026 8.57211 8.76148 8.33333 8.46693 8.33333H7.93359" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M8.73346 5.26666C8.58619 5.26666 8.4668 5.38605 8.4668 5.53333C8.4668 5.68061 8.58619 5.8 8.73346 5.8C8.88074 5.8 9.00013 5.68061 9.00013 5.53333C9.00013 5.38605 8.88074 5.26666 8.73346 5.26666V5.26666" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M9 17C13.4183 17 17 13.4183 17 9C17 4.58172 13.4183 1 9 1C4.58172 1 1 4.58172 1 9C1 13.4183 4.58172 17 9 17Z" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>
 | 
			
		||||
                <span class="tooltiptext">Als Vollebenen zählen alle Ebenen die größer als 0.5m² sind, inklusive des Käfigbodens.</span>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="ncontainer">
 | 
			
		||||
                <div class="input-group">
 | 
			
		||||
                    <button onclick="decreaseFloorNum()">-</button>
 | 
			
		||||
                    <input type="text" id="numFullFloors" value="3" readonly>
 | 
			
		||||
                    <button onclick="increaseFloorNum()">+</button>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="input-element">
 | 
			
		||||
            <div class="slidecontainer">
 | 
			
		||||
                <label for="numRats" id="labelNumRats">Anzahl an Ratten ?</label>
 | 
			
		||||
                <input type="range" min="3" max="15" value="4" class="slider" id="numRats">
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="container output-element" id="resultsDiv">
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
</div>
 | 
			
		||||
<script>
 | 
			
		||||
 | 
			
		||||
    const inputWidth = document.getElementById("width");
 | 
			
		||||
    inputWidth.onchange = updateViaManualMeasurements;
 | 
			
		||||
    const inputDepth = document.getElementById("depth");
 | 
			
		||||
    inputDepth.onchange = updateViaManualMeasurements;
 | 
			
		||||
    const inputHeight = document.getElementById("height");
 | 
			
		||||
    inputHeight.onchange = updateViaManualMeasurements;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    const selectSavicSuiteRoyaleXL = document.getElementById("SavicSuiteRoyaleXL");
 | 
			
		||||
    const selectSavicSuiteRoyale95Double = document.getElementById("SavicSuiteRoyale95Double");
 | 
			
		||||
    const selectTiakiKleintierkäfigEtagere = document.getElementById("TiakiKleintierkäfigEtagere");
 | 
			
		||||
 | 
			
		||||
    const cardSavicSuiteRoyaleXL = document.getElementById("card-SavicSuiteRoyaleXL");
 | 
			
		||||
    const cardSavicSuiteRoyale95Double = document.getElementById("card-SavicSuiteRoyale95Double");
 | 
			
		||||
    const cardTiakiKleintierkäfigEtagere = document.getElementById("card-TiakiKleintierkäfigEtagere");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    function markActiveCage(cageName) {
 | 
			
		||||
 | 
			
		||||
        cardSavicSuiteRoyaleXL.classList.remove("card-active");
 | 
			
		||||
        cardSavicSuiteRoyale95Double.classList.remove("card-active");
 | 
			
		||||
        cardTiakiKleintierkäfigEtagere.classList.remove("card-active");
 | 
			
		||||
        if (cageName != "") {
 | 
			
		||||
            const activeCage = document.getElementById("card-" + cageName);
 | 
			
		||||
            activeCage.classList.add("card-active")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function updateCage(event) {
 | 
			
		||||
        selectSavicSuiteRoyaleXL.checked = false;
 | 
			
		||||
        selectSavicSuiteRoyale95Double.checked = false;
 | 
			
		||||
        selectTiakiKleintierkäfigEtagere.checked = false;
 | 
			
		||||
        const selectedCage = event.currentTarget
 | 
			
		||||
        selectedCage.checked = true;
 | 
			
		||||
        const cageName = selectedCage.id;
 | 
			
		||||
 | 
			
		||||
        console.log(cageName);
 | 
			
		||||
        var dim = getCageDimensions(cageName);
 | 
			
		||||
        inputWidth.value = dim.width;
 | 
			
		||||
        inputDepth.value = dim.depth;
 | 
			
		||||
        inputHeight.value = dim.height;
 | 
			
		||||
 | 
			
		||||
        markActiveCage(cageName);
 | 
			
		||||
 | 
			
		||||
        update();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    selectSavicSuiteRoyaleXL.onchange = updateCage;
 | 
			
		||||
    selectSavicSuiteRoyale95Double.onchange = updateCage;
 | 
			
		||||
    selectTiakiKleintierkäfigEtagere.onchange = updateCage;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    var labelNumRats = document.getElementById("labelNumRats");
 | 
			
		||||
 | 
			
		||||
    var ratSlider = document.getElementById("numRats");
 | 
			
		||||
 | 
			
		||||
    labelNumRats.innerHTML = `Anzahl an Ratten: ` + ratSlider.value;
 | 
			
		||||
 | 
			
		||||
    ratSlider.oninput = function () {
 | 
			
		||||
        labelNumRats.innerHTML = `Anzahl an Ratten: ` + this.value;
 | 
			
		||||
        update();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Full floor functions
 | 
			
		||||
    var fullFloorNum = document.getElementById("numFullFloors");
 | 
			
		||||
 | 
			
		||||
    function getCageDimensions(cageName) {
 | 
			
		||||
        console.log(cageName);
 | 
			
		||||
        if (cageName == "SavicSuiteRoyaleXL") {
 | 
			
		||||
            return new Dimensions(115, 67.5, 153);
 | 
			
		||||
        }
 | 
			
		||||
        if (cageName == "SavicSuiteRoyale95Double") {
 | 
			
		||||
            return new Dimensions(95, 63, 120);
 | 
			
		||||
        }
 | 
			
		||||
        if (cageName == "TiakiKleintierkäfigEtagere") {
 | 
			
		||||
            return new Dimensions(93.5, 63, 141.2);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getResultFromChecks(checks) {
 | 
			
		||||
        console.log(checks.length)
 | 
			
		||||
        if (Object.keys(checks).length > 0) {
 | 
			
		||||
            const ul = document.createElement('ul');
 | 
			
		||||
            for (const key in checks) {
 | 
			
		||||
                const li = document.createElement('li');
 | 
			
		||||
                li.textContent = `❌` + checks[key];
 | 
			
		||||
                ul.appendChild(li);
 | 
			
		||||
            }
 | 
			
		||||
            return ul;
 | 
			
		||||
        } else {
 | 
			
		||||
            const p = document.createElement('p');
 | 
			
		||||
            p.innerHTML = "✅ Der Käfig erfüllt alle Kriterien!"
 | 
			
		||||
            return p;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function updateViaManualMeasurements() {
 | 
			
		||||
        markActiveCage("ManualMeasurements");
 | 
			
		||||
        update();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function update() {
 | 
			
		||||
        const width = inputWidth.value
 | 
			
		||||
        const depth = inputDepth.value
 | 
			
		||||
        const height = inputHeight.value
 | 
			
		||||
        const dimensions = new Dimensions(width / 100, depth / 100, height / 100);
 | 
			
		||||
        const failed_checks = cageCheck(dimensions, ratSlider.value, fullFloorNum.value);
 | 
			
		||||
        console.log(failed_checks);
 | 
			
		||||
        let resultsDiv = document.getElementById("resultsDiv");
 | 
			
		||||
        resultsDiv.innerHTML = `<strong>Ergebnis</strong>`;
 | 
			
		||||
 | 
			
		||||
        const result = getResultFromChecks(failed_checks);
 | 
			
		||||
 | 
			
		||||
        resultsDiv.appendChild(result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    function decreaseFloorNum() {
 | 
			
		||||
        var input = document.getElementById('numFullFloors');
 | 
			
		||||
        var value = parseInt(input.value);
 | 
			
		||||
        if (value > 0) {
 | 
			
		||||
            input.value = value - 1;
 | 
			
		||||
        }
 | 
			
		||||
        update();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function increaseFloorNum() {
 | 
			
		||||
        var input = document.getElementById('numFullFloors');
 | 
			
		||||
        var value = parseInt(input.value);
 | 
			
		||||
        input.value = value + 1;
 | 
			
		||||
        update();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    update();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										196
									
								
								src/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,196 @@
 | 
			
		||||
const inputDecreaseFloorNum = document.getElementById("decreaseFloorNum");
 | 
			
		||||
inputDecreaseFloorNum.onclick = decreaseFloorNum;
 | 
			
		||||
 | 
			
		||||
const inputIncreaseFloorNum = document.getElementById("increaseFloorNum");
 | 
			
		||||
inputIncreaseFloorNum.onclick = increaseFloorNum;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const inputWidth = document.getElementById("width");
 | 
			
		||||
inputWidth.onchange = updateViaManualMeasurements;
 | 
			
		||||
const inputDepth = document.getElementById("depth");
 | 
			
		||||
inputDepth.onchange = updateViaManualMeasurements;
 | 
			
		||||
const inputHeight = document.getElementById("height");
 | 
			
		||||
inputHeight.onchange = updateViaManualMeasurements;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const selectSavicSuiteRoyaleXL = document.getElementById("SavicSuiteRoyaleXL");
 | 
			
		||||
const selectSavicSuiteRoyale95Double = document.getElementById("SavicSuiteRoyale95Double");
 | 
			
		||||
const selectTiakiKleintierkäfigEtagere = document.getElementById("TiakiKleintierkäfigEtagere");
 | 
			
		||||
 | 
			
		||||
const cardSavicSuiteRoyaleXL = document.getElementById("card-SavicSuiteRoyaleXL");
 | 
			
		||||
const cardSavicSuiteRoyale95Double = document.getElementById("card-SavicSuiteRoyale95Double");
 | 
			
		||||
const cardTiakiKleintierkäfigEtagere = document.getElementById("card-TiakiKleintierkäfigEtagere");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function markActiveCage(cageName) {
 | 
			
		||||
 | 
			
		||||
    cardSavicSuiteRoyaleXL.classList.remove("card-active");
 | 
			
		||||
    cardSavicSuiteRoyale95Double.classList.remove("card-active");
 | 
			
		||||
    cardTiakiKleintierkäfigEtagere.classList.remove("card-active");
 | 
			
		||||
    if (cageName != "") {
 | 
			
		||||
        const activeCage = document.getElementById("card-" + cageName);
 | 
			
		||||
        activeCage.classList.add("card-active")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function updateCage(event) {
 | 
			
		||||
    selectSavicSuiteRoyaleXL.checked = false;
 | 
			
		||||
    selectSavicSuiteRoyale95Double.checked = false;
 | 
			
		||||
    selectTiakiKleintierkäfigEtagere.checked = false;
 | 
			
		||||
    const selectedCage = event.currentTarget
 | 
			
		||||
    selectedCage.checked = true;
 | 
			
		||||
    const cageName = selectedCage.id;
 | 
			
		||||
 | 
			
		||||
    console.log(cageName);
 | 
			
		||||
    var dim = getCageDimensions(cageName);
 | 
			
		||||
    inputWidth.value = dim.width;
 | 
			
		||||
    inputDepth.value = dim.depth;
 | 
			
		||||
    inputHeight.value = dim.height;
 | 
			
		||||
 | 
			
		||||
    markActiveCage(cageName);
 | 
			
		||||
 | 
			
		||||
    update();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
selectSavicSuiteRoyaleXL.onchange = updateCage;
 | 
			
		||||
selectSavicSuiteRoyale95Double.onchange = updateCage;
 | 
			
		||||
selectTiakiKleintierkäfigEtagere.onchange = updateCage;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
var labelNumRats = document.getElementById("labelNumRats");
 | 
			
		||||
 | 
			
		||||
var ratSlider = document.getElementById("numRats");
 | 
			
		||||
 | 
			
		||||
labelNumRats.innerHTML = `Anzahl an Ratten: ` + ratSlider.value;
 | 
			
		||||
 | 
			
		||||
ratSlider.oninput = function () {
 | 
			
		||||
    labelNumRats.innerHTML = `Anzahl an Ratten: ` + this.value;
 | 
			
		||||
    update();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Full floor functions
 | 
			
		||||
var fullFloorNum = document.getElementById("numFullFloors");
 | 
			
		||||
 | 
			
		||||
function getCageDimensions(cageName) {
 | 
			
		||||
    console.log(cageName);
 | 
			
		||||
    if (cageName == "SavicSuiteRoyaleXL") {
 | 
			
		||||
        return new Dimensions(115, 67.5, 153);
 | 
			
		||||
    }
 | 
			
		||||
    if (cageName == "SavicSuiteRoyale95Double") {
 | 
			
		||||
        return new Dimensions(95, 63, 120);
 | 
			
		||||
    }
 | 
			
		||||
    if (cageName == "TiakiKleintierkäfigEtagere") {
 | 
			
		||||
        return new Dimensions(93.5, 63, 141.2);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getResultFromChecks(checks) {
 | 
			
		||||
    console.log(checks.length)
 | 
			
		||||
    if (Object.keys(checks).length > 0) {
 | 
			
		||||
        const ul = document.createElement('ul');
 | 
			
		||||
        for (const key in checks) {
 | 
			
		||||
            const li = document.createElement('li');
 | 
			
		||||
            li.textContent = `❌` + checks[key];
 | 
			
		||||
            ul.appendChild(li);
 | 
			
		||||
        }
 | 
			
		||||
        return ul;
 | 
			
		||||
    } else {
 | 
			
		||||
        const p = document.createElement('p');
 | 
			
		||||
        p.innerHTML = "✅ Der Käfig erfüllt alle Kriterien!"
 | 
			
		||||
        return p;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function updateViaManualMeasurements() {
 | 
			
		||||
    markActiveCage("ManualMeasurements");
 | 
			
		||||
    update();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function update() {
 | 
			
		||||
    const width = inputWidth.value
 | 
			
		||||
    const depth = inputDepth.value
 | 
			
		||||
    const height = inputHeight.value
 | 
			
		||||
    const dimensions = new Dimensions(width / 100, depth / 100, height / 100);
 | 
			
		||||
    const failed_checks = cageCheck(dimensions, ratSlider.value, fullFloorNum.value);
 | 
			
		||||
    console.log(failed_checks);
 | 
			
		||||
    let resultsDiv = document.getElementById("resultsDiv");
 | 
			
		||||
    resultsDiv.innerHTML = `<strong>Ergebnis</strong>`;
 | 
			
		||||
 | 
			
		||||
    const result = getResultFromChecks(failed_checks);
 | 
			
		||||
 | 
			
		||||
    resultsDiv.appendChild(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function decreaseFloorNum() {
 | 
			
		||||
    var input = document.getElementById('numFullFloors');
 | 
			
		||||
    var value = parseInt(input.value);
 | 
			
		||||
    if (value > 0) {
 | 
			
		||||
        input.value = value - 1;
 | 
			
		||||
    }
 | 
			
		||||
    update();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function increaseFloorNum() {
 | 
			
		||||
    var input = document.getElementById('numFullFloors');
 | 
			
		||||
    var value = parseInt(input.value);
 | 
			
		||||
    input.value = value + 1;
 | 
			
		||||
    update();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
update();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import i18next from "i18next";
 | 
			
		||||
import LanguageDetector from "i18next-browser-languagedetector";
 | 
			
		||||
import HttpApi from "i18next-http-backend";
 | 
			
		||||
 | 
			
		||||
async function initI18next() {
 | 
			
		||||
    // We use() the backend and await it to load
 | 
			
		||||
    // the translations from the network
 | 
			
		||||
    await i18next
 | 
			
		||||
        .use(HttpApi)
 | 
			
		||||
        .use(LanguageDetector)
 | 
			
		||||
        .init({
 | 
			
		||||
            lng: "en",
 | 
			
		||||
            supportedLngs: ["en", "de"],
 | 
			
		||||
            nonExplicitSupportedLngs: true,
 | 
			
		||||
            fallbackLng: "en",
 | 
			
		||||
            debug: true,
 | 
			
		||||
            backend: {
 | 
			
		||||
                loadPath: "/lang/{{lng}}.json",
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function translatePageElements() {
 | 
			
		||||
    const translatableElements = document.querySelectorAll(
 | 
			
		||||
        "[data-i18n-key]",
 | 
			
		||||
    );
 | 
			
		||||
    translatableElements.forEach((el) => {
 | 
			
		||||
        const key = el.getAttribute("data-i18n-key");
 | 
			
		||||
        el.innerHTML = i18next.t(key);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
// ...
 | 
			
		||||
 | 
			
		||||
function bindLocaleSwitcher(initialValue) {
 | 
			
		||||
    const switcher = document.querySelector(
 | 
			
		||||
        "[data-i18n-switcher]",
 | 
			
		||||
    );
 | 
			
		||||
    switcher.value = initialValue;
 | 
			
		||||
    switcher.onchange = (e) => {
 | 
			
		||||
        i18next
 | 
			
		||||
            .changeLanguage(e.target.value)
 | 
			
		||||
            .then(translatePageElements);
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
(async function () {
 | 
			
		||||
    await initI18next();
 | 
			
		||||
    translatePageElements();
 | 
			
		||||
    bindLocaleSwitcher(i18next.resolvedLanguage);
 | 
			
		||||
})();
 | 
			
		||||
							
								
								
									
										25
									
								
								webpack.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,25 @@
 | 
			
		||||
const path = require("path");
 | 
			
		||||
 | 
			
		||||
const port = 3000;
 | 
			
		||||
const openBrowser = true;
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    entry: {
 | 
			
		||||
        app: ["./src/index.js"],
 | 
			
		||||
    },
 | 
			
		||||
    output: {
 | 
			
		||||
        filename: "bundle.js",
 | 
			
		||||
        path: path.resolve(__dirname, "public"),
 | 
			
		||||
        publicPath: "/",
 | 
			
		||||
    },
 | 
			
		||||
    mode: "development",
 | 
			
		||||
    devtool: "source-map",
 | 
			
		||||
    devServer: {
 | 
			
		||||
        port: port,
 | 
			
		||||
        open: openBrowser,
 | 
			
		||||
        historyApiFallback: {
 | 
			
		||||
            index: "index.html",
 | 
			
		||||
        },
 | 
			
		||||
        static: "public",
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||