Created
June 9, 2022 21:15
-
-
Save batazo/1c3bfc63ba475eb237beb0f4c1d8b899 to your computer and use it in GitHub Desktop.
EASY Tetris - v52-Unpublished
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <div class="overlay" id="paneloverlay"> | |
| <audio id="myAudio"> | |
| <source src="https://bzozoo.github.io/Tetris-Basic/tetrisTheme.mp3" type="audio/mpeg"> | |
| Your browser does not support the audio element. | |
| </audio> | |
| <div id="rewardContainer"> | |
| <div id="rewardPicDiv"> | |
| </div> | |
| </div> | |
| <div id="gameOverDiv" style="display: none;"> | |
| <div id="overScore">0000</div> | |
| </div> | |
| <div class="container"> | |
| <div class="grid-bg"></div> | |
| <div class="grid"> | |
| </div><!-- GRID DIV END--> | |
| <div class="sidebar"> | |
| <div id="scoreBox"> | |
| <p> | |
| <strong> | |
| S C O R E | |
| </strong> | |
| </p> | |
| <p id="scoreDisplay">0</p> | |
| </div> | |
| <div class="mini-grid"> | |
| <div class="first-in-minirow"></div> | |
| <div><strong>N</strong></div> | |
| <div><strong>E</strong></div> | |
| <div><strong>X</strong></div> | |
| <div><strong>T</strong></div> | |
| <div></div> | |
| <div class="first-in-minirow"></div> | |
| <div></div> | |
| <div></div> | |
| <div></div> | |
| <div></div> | |
| <div></div> | |
| <div class="first-in-minirow"></div> | |
| <div></div> | |
| <div></div> | |
| <div></div> | |
| <div></div> | |
| <div></div> | |
| <div class="first-in-minirow"></div> | |
| <div></div> | |
| <div></div> | |
| <div></div> | |
| <div></div> | |
| <div></div> | |
| <div class="first-in-minirow"></div> | |
| <div></div> | |
| <div></div> | |
| <div></div> | |
| <div></div> | |
| <div></div> | |
| <div class="first-in-minirow"></div> | |
| <div></div> | |
| <div></div> | |
| <div></div> | |
| <div></div> | |
| <div></div> | |
| </div> | |
| <div id="speedBox"> | |
| <strong>SPEED</strong><span id="speedcounter">0</span> | |
| </div> | |
| <div class="actions"> | |
| <p> | |
| <button class="actionBtn" id="loginBtn">⚡ LOGIN</button> | |
| <button class="actionBtn hidden" id="profileBtn">👤 PROFILE</button> | |
| </p> | |
| <p> | |
| <button class="actionBtn" id="start-button">▶ START</button> | |
| </p> | |
| <p> | |
| <button class="actionBtn" id="muteButton">🔇 MUTE</button> | |
| </p> | |
| <p> | |
| <button class="actionBtn" id="resetButton">↺ RESET GAME</button> | |
| </p> | |
| <p> | |
| <button class="actionBtn" id="optionsButton">⚙️ OPTIONS</button> | |
| </p> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="logo"> | |
| Bzozoo Tetris Basic <span id="version">{{ version }}</span> | |
| </div> | |
| <div class="controlls" id="controllButtonsSection"> | |
| <p> | |
| <button class="gombBtn" id="leftMove"> ◄ </button> | |
| <button class="gombBtn" id="rightMove"> ► </button> | |
| <button class="gombBtn" id="downMove">▼</button> | |
| <button class="gombBtn" id="rotation">🔄</button> | |
| </p> | |
| </div> | |
| </div> | |
| <div id="highscore" class="modal hidden flexcolumn"> | |
| <div class="navbar"> | |
| <div class="title">HIGHSCORE</div> | |
| <div class="navbtns"><button class="actionBtn" id="closeHighScore">X</button></div> | |
| </div> | |
| <div id="highscorecontent" class="panel"> | |
| <!-- {{ HIGH SCORE }} --> | |
| </div> | |
| </div> | |
| <div id="userzone" class="modal hidden"> | |
| <div class="navbar"> | |
| <div class="title">USER ZONE</div> | |
| <div class="navbtns"><button class="actionBtn" id="closeUserZone">X</button></div> | |
| </div> | |
| <div id="login" class="panel"> | |
| <!-- {{ IF USER NOT LOGGED IN }} --> | |
| </div> | |
| <div id="usercontainer" class="panel"> | |
| <!-- {{ IF USER LOGGED IN }} --> | |
| </div> | |
| </div> | |
| <div id="optionspanel" class="modal hidden"> | |
| <div class="navbar"> | |
| <div class="title">OPTIONS</div> | |
| <div class="navbtns"><button class="actionBtn" id="closeOPtions">X</button></div> | |
| </div> | |
| <div id="optionscontainer"> | |
| <div class="actions"> | |
| <p> | |
| <input type="checkbox" name="effect" id="effect" checked /><label for="effect">BOOM EFFECT</label> | |
| </p> | |
| <p> | |
| <input type="checkbox" name="invert" id="invert" /> <label for="invert">INVERT ¿</label> | |
| </p> | |
| <p> | |
| <input type="checkbox" name="reward" id="reward" checked /> <label for="reward">REWARD</label> | |
| </p> | |
| <p> | |
| <input type="checkbox" name="weird" id="weird" /> <label for="weird">WEIRDMOD</label> | |
| </p> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="scoresavedbox" class="modal hidden"> | |
| SCORE SAVED | |
| </div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // IIFE DISABLED (function () { | |
| const application = { name: "TETRIS BASIC", version: "v52-Unpublished" }; | |
| const gameSettings = { | |
| host: "https://tetris.ga", | |
| rerenderMode: "onelinebased", // usage: [onelinebased, squarebased, old] | |
| rerenderable: true, | |
| width: 10, | |
| speed: 1, | |
| gridNumbers: 250, | |
| lineNumbers: () => { | |
| return gameSettings.gridNumbers / gameSettings.width; | |
| }, | |
| controllButtonsDeactivable: true, | |
| tetrominoDropable: true, | |
| displayWidth: 6, | |
| displayIndex: 1, | |
| boomm: | |
| "https://bzozoo.github.io/Tetris-Basic//images/boomm.gif", | |
| rewardExtraPics: [ | |
| "https://i.imgur.com/awaQZST.jpg", | |
| "https://i.imgur.com/psZNoKt.jpg", | |
| "https://i.imgur.com/uCvHYUX.jpg", | |
| "https://i.imgur.com/rW0gv4H.jpg", | |
| "https://i.imgur.com/TpZDy0N.jpg", | |
| "https://i.imgur.com/2EjNoQG.jpg", | |
| "https://i.imgur.com/KBY1sRA.jpg", | |
| "https://i.imgur.com/h8SWCow.jpg", | |
| "https://i.imgur.com/UkUQbSO.jpg", | |
| "https://i.imgur.com/YEcYcxl.jpg", | |
| "https://i.imgur.com/voXqUm3.jpg", | |
| "https://i.imgur.com/cTMV0N2.jpg", | |
| "https://i.imgur.com/QQfe4tR.jpg", | |
| "https://i.imgur.com/eaIsfFZ.jpg", | |
| "https://i.imgur.com/whs4Oze.jpg", | |
| "https://i.imgur.com/5EvLQKA.jpg", | |
| "https://i.imgur.com/XMr4syr.jpg", | |
| "https://i.imgur.com/CuC6EMI.jpg", | |
| "https://i.imgur.com/uw8zEr8.jpg", | |
| "https://i.imgur.com/eUgVtPe.jpg" | |
| ] | |
| }; | |
| // MAIIN FUNCTION DISABLED main(gameSettings); function main(gameSettings){ | |
| const { | |
| host, | |
| rerenderMode, | |
| controllButtonsDeactivable, | |
| gridNumbers, | |
| width, | |
| speed, | |
| displayWidth, | |
| displayIndex, | |
| lineNumbers, | |
| rewardExtraPics, | |
| boomm | |
| } = gameSettings; | |
| console.log("RENDER MODE ::: " + rerenderMode); | |
| //Declare DOM elements | |
| const grid = document.querySelector(".grid"); | |
| const miniSquares = Array.from(document.querySelectorAll(".mini-grid div")); | |
| const miniGrid = document.querySelector(".mini-grid"); | |
| const startBtn = document.querySelector("#start-button"); | |
| const invertCheckBox = document.querySelector("#invert"); | |
| const rewardCheckBox = document.querySelector("#reward"); | |
| const displaySquares = document.querySelectorAll(".mini-grid div"); | |
| const gameTimer = new IntervalEncapsulator(tryFreeze, 500); | |
| const speeder = new IntervalEncapsulator(tryFreeze, 100); | |
| const musicInterval = new IntervalEncapsulator(playMusic, 1); | |
| const run = backcounter(3); | |
| let underEffect = false; | |
| const currents = { | |
| random: null, | |
| nextRandom: 0, | |
| currentPosition: 4, | |
| currentRotation: 0, | |
| nextRotation: this.currentRotation + 1, | |
| current: null, | |
| nextRotatedCurrent: null | |
| }; | |
| let { | |
| random, | |
| nextRandom, | |
| currentPosition, | |
| currentRotation, | |
| nextRotation, | |
| current, | |
| nextRotatedCurrent | |
| } = currents; | |
| let score = 0; | |
| //The Tetrominoes | |
| /* lTetronimo is the example * | |
| 0 1 2 0 1 2 0 1 2 0 1 2 | |
| |-------------------------------- | |
| 0 | X X X | |
| width | X X X X X X | |
| 2 * width | X X X X X X X | |
| */ | |
| const lTetromino = [ | |
| [1, width + 1, width * 2 + 1, 2], | |
| [width, width + 1, width + 2, width * 2 + 2], | |
| [1, width + 1, width * 2 + 1, width * 2], | |
| [width, width * 2, width * 2 + 1, width * 2 + 2] | |
| ]; | |
| const zTetromino = [ | |
| [0, width, width + 1, width * 2 + 1], | |
| [width + 1, width + 2, width * 2, width * 2 + 1], | |
| [0, width, width + 1, width * 2 + 1], | |
| [width + 1, width + 2, width * 2, width * 2 + 1] | |
| ]; | |
| const tTetromino = [ | |
| [1, width, width + 1, width + 2], | |
| [1, width + 1, width + 2, width * 2 + 1], | |
| [width, width + 1, width + 2, width * 2 + 1], | |
| [1, width, width + 1, width * 2 + 1] | |
| ]; | |
| //The Tetrominoes | |
| /* oTetronimo is the example * | |
| 0 1 2 0 1 2 0 1 2 0 1 2 | |
| |-------------------------------- | |
| 0 |X X X X X X X X | |
| width |X X X X X X X X | |
| 2 * width | | |
| */ | |
| const oTetromino = [ | |
| [0, 1, width, width + 1], | |
| [0, 1, width, width + 1], | |
| [0, 1, width, width + 1], | |
| [0, 1, width, width + 1] | |
| ]; | |
| const iTetromino = [ | |
| [1, width + 1, width * 2 + 1, width * 3 + 1], | |
| [width - 1, width, width + 1, width + 2], | |
| [1, width + 1, width * 2 + 1, width * 3 + 1], | |
| [width - 1, width, width + 1, width + 2] | |
| ]; | |
| const liTetromino = [ | |
| [0, 1, width + 1, width * 2 + 1], | |
| [2, width, width + 1, width + 2], | |
| [0, width, width * 2, width * 2 + 1], | |
| [0, 1, 2, width] | |
| ]; | |
| const ziTetromino = [ | |
| [1, width, width + 1, width * 2], | |
| [0, 1, width + 1, width + 2], | |
| [1, width, width + 1, width * 2], | |
| [0, 1, width + 1, width + 2] | |
| ]; | |
| //Tetromino pair with colors arrays | |
| const theTetrominoes = [ | |
| lTetromino, | |
| zTetromino, | |
| tTetromino, | |
| oTetromino, | |
| iTetromino, | |
| liTetromino, | |
| ziTetromino | |
| ]; | |
| const tetrominoNames = ["L", "Z", "T", "O", "I", "L-INVERT", "Z-INVERT"]; | |
| const colors = [ | |
| "orange", | |
| "red", | |
| "purple", | |
| "green", | |
| "blue", | |
| "brown", | |
| "turquoise" | |
| ]; | |
| //the Tetrominos without rotations | |
| const upNextTetrominoes = [ | |
| [ | |
| 2 * displayWidth + 1, | |
| 2 * displayWidth + 2, | |
| 3 * displayWidth + 1, | |
| 4 * displayWidth + 1 | |
| ], //lTetromino | |
| [ | |
| 2 * displayWidth + 1, | |
| 3 * displayWidth + 1, | |
| 3 * displayWidth + 2, | |
| 4 * displayWidth + 2 | |
| ], //zTetromino | |
| [ | |
| 2 * displayWidth + 1, | |
| 3 * displayWidth, | |
| 3 * displayWidth + 1, | |
| 3 * displayWidth + 2 | |
| ], //tTetromino | |
| [ | |
| 2 * displayWidth + 1, | |
| 2 * displayWidth + 2, | |
| 3 * displayWidth + 1, | |
| 3 * displayWidth + 2 | |
| ], //oTetromino | |
| [ | |
| 1 * displayWidth + 1, | |
| 2 * displayWidth + 1, | |
| 3 * displayWidth + 1, | |
| 4 * displayWidth + 1 | |
| ], //iTetromino | |
| [ | |
| 2 * displayWidth + 1, | |
| 2 * displayWidth + 2, | |
| 3 * displayWidth + 2, | |
| 4 * displayWidth + 2 | |
| ], // liTetromino | |
| [ | |
| 2 * displayWidth + 2, | |
| 3 * displayWidth + 1, | |
| 3 * displayWidth + 2, | |
| 4 * displayWidth + 1 | |
| ] // ziTetromino | |
| ]; | |
| //InitGame | |
| initRender(); | |
| initGame(); | |
| //// | |
| ///InitDevFunctions | |
| //numberisedSquares(); | |
| //numberisedOneline(); | |
| //makeTestLines() | |
| //arrToArg([230, 238]) | |
| //checkCurrent() | |
| //// | |
| function initRender() { | |
| highscorecontent.innerHTML = LoadingComponent(); | |
| tryLoginRender() | |
| } | |
| function initGame() { | |
| console.log("Init Game"); | |
| version.innerText = application.version; | |
| grid.innerHTML = TemplateForGrid(); //Init Grid template | |
| miniSquaresInit(); | |
| gameOverDiv.style.display = "none"; | |
| scoreInit(); | |
| gameTimer.stop(); | |
| currentPosition = 4; | |
| currentRotation = 0; | |
| random = Math.floor(Math.random() * theTetrominoes.length); | |
| nextRandom = Math.floor(Math.random() * theTetrominoes.length); | |
| current = theTetrominoes[random][currentRotation]; | |
| nextRotatedCurrent = theTetrominoes[random][nextRotation]; | |
| startBtn.innerHTML = "▶ START"; | |
| deactivateGameButtons(); | |
| rewardPicDivSetHeight(0); | |
| rewardPicDivSetBackground(); | |
| rewardCheckBox.checked = checkRewardExtra(); | |
| weird.checked = checkWeirdMode(); | |
| } | |
| function checkWeirdMode() { | |
| return localStorage.getItem("storedWeirdMode") === null | |
| ? false | |
| : JSON.parse(localStorage.getItem("storedWeirdMode")); | |
| } | |
| function checkRewardExtra() { | |
| return localStorage.getItem("storedReward") === null | |
| ? true | |
| : JSON.parse(localStorage.getItem("storedReward")); | |
| } | |
| function rewardPicDivSetBackground() { | |
| randomReward = Math.floor(Math.random() * rewardExtraPics.length); | |
| rewardPicDiv.style.backgroundImage = | |
| "url(" + rewardExtraPics[randomReward] + ")"; | |
| } | |
| function scoreInit() { | |
| score = 0; | |
| scoreDisplay.innerHTML = score; | |
| } | |
| function miniSquaresInit() { | |
| miniSquares.forEach(function (miniSquare, sqkey) { | |
| miniSquares[sqkey].style = ""; | |
| miniSquares[sqkey].classList.remove("tetromino"); | |
| }); | |
| } | |
| function draw() { | |
| const { squares } = getDOMElements(); | |
| current.forEach((index) => { | |
| squares[currentPosition + index].classList.add("tetromino"); | |
| squares[currentPosition + index].style.backgroundColor = colors[random]; | |
| }); | |
| } | |
| function undraw() { | |
| const { squares } = getDOMElements(); | |
| current.forEach((index) => { | |
| squares[currentPosition + index].classList.remove("tetromino"); | |
| squares[currentPosition + index].style.backgroundColor = ""; | |
| }); | |
| } | |
| function moveLeft() { | |
| undraw(); | |
| const { squares } = getDOMElements(); | |
| const isAtLeftEdge = current.some( | |
| (index) => (currentPosition + index) % width === 0 | |
| ); | |
| if (!isAtLeftEdge) currentPosition -= 1; | |
| if ( | |
| current.some((index) => | |
| squares[currentPosition + index].classList.contains("taken") | |
| ) | |
| ) { | |
| currentPosition += 1; | |
| } | |
| draw(); | |
| } | |
| function moveRight() { | |
| undraw(); | |
| const { squares } = getDOMElements(); | |
| const isAtRightEdge = current.some( | |
| (index) => (currentPosition + index) % width === width - 1 | |
| ); | |
| if (!isAtRightEdge) currentPosition += 1; | |
| if ( | |
| current.some((index) => | |
| squares[currentPosition + index].classList.contains("taken") | |
| ) | |
| ) { | |
| currentPosition -= 1; | |
| } | |
| draw(); | |
| } | |
| function moveDown() { | |
| undraw(); | |
| currentPosition += width; | |
| draw(); | |
| } | |
| function tryFreeze() { | |
| lockCheck() === true && doThisIfLockable(); | |
| lockCheck() === false && moveDown(); | |
| } | |
| function lockCheck() { | |
| return checkCurrentInSomeInNextRow() ? true : false; | |
| } | |
| function checkCurrentInSomeInNextRow() { | |
| const { squares } = getDOMElements(); | |
| return current.some((index) => | |
| squares[currentPosition + index + width].classList.contains("taken") | |
| ); | |
| } | |
| function doThisIfLockable() { | |
| //console.log("doThisIfLockable") | |
| addCurrentToTaken(); //Lock current | |
| tryGameOver(); | |
| //let score = 0; | |
| let rowsInTaken = checkRowsInTaken(); | |
| rowsInTaken.length && doThisIfRowInTaken(rowsInTaken); | |
| setRewardPic(); | |
| !checkGameOver() && dropNewTetromino(); | |
| } | |
| function addCurrentToTaken() { | |
| const { squares } = getDOMElements(); | |
| current.forEach((index) => | |
| squares[currentPosition + index].classList.add("taken") | |
| ); | |
| } | |
| async function doThisIfRowInTaken(rowsInTaken) { | |
| fasterDownStop(); | |
| tryEffect(rowsInTaken); | |
| await breakBeforeRender(1000); | |
| let rendered = doRender(rowsInTaken); | |
| rendered && addScore(rowsInTaken.length); | |
| } | |
| //OLD Try Effect | |
| function tryEffectOLD(rowsInTaken) { | |
| console.log("TRYING EFFECT....") | |
| run.getActualCount() === run.getDefaultCount && doEffect(rowsInTaken); | |
| } | |
| // | |
| // | |
| function tryEffect(rowsInTaken) { | |
| console.log("TRYING EFFECT...."); | |
| (!underEffect) && doEffect(rowsInTaken); | |
| } | |
| function doEffect(rowsInTaken) { | |
| console.log("Do EFFECT ::: "); | |
| let colorizeThis = | |
| rerenderMode === "squarebased" | |
| ? rowsInTaken.map((rowInTaken) => [squareToOnelineNum(rowInTaken[1])]) | |
| : rowsInTaken; | |
| console.log(colorizeThis); | |
| colorizeThis.map((rowInTaken) => | |
| getOneline(rowInTaken).map( | |
| (cell) => (cell.style.backgroundImage = `url("${boomm}")`) | |
| ) | |
| ); | |
| return true; | |
| } | |
| ////OLD BREAKCOUNTER | |
| function breakBeforeRenderOLD() { | |
| console.log("ACTUAL BREAKCOUNT ::: " + run.getActualCount()); | |
| if (run.getActualCount() > 0) { | |
| gameSettings.rerenderable = false; | |
| gameSettings.tetrominoDropable = false; | |
| run.doBackCount(); | |
| } | |
| if (run.getActualCount() === 0) { | |
| console.log("REACTIVATE... Renderable and Tetromino dropable..."); | |
| gameSettings.rerenderable = true; | |
| gameSettings.tetrominoDropable = true; | |
| run.restartBackCount(); | |
| } | |
| //console.log('BEAKCOUNT ::: ' + run.getActualCount()) | |
| } | |
| /// | |
| ////NEWEST BREAKCOUNTER (2022-06-09) | |
| function breakBeforeRender(time) { | |
| console.log("BREAK TIME..."); | |
| gameTimer.stop(); | |
| underEffect = true; | |
| return new Promise((resolve)=>{ | |
| setTimeout(()=>{ | |
| gameTimer.start(); | |
| underEffect = false; | |
| resolve(true) | |
| }, time) | |
| }) | |
| } | |
| /// | |
| function doRender(rowsInTaken) { | |
| //console.log("DO RENDER") | |
| if (gameSettings.rerenderable) { | |
| switch (rerenderMode) { | |
| case "onelinebased": | |
| //OnelineBasedRerender | |
| rerenderOnelines(rowsInTaken); | |
| return true; | |
| break; | |
| case "squarebased": | |
| //SquareBasedRerender | |
| rerenderSquares(rowsInTaken); | |
| return true; | |
| break; | |
| case "old": | |
| //OldRerender | |
| rerenderGrids(); | |
| return true; | |
| break; | |
| default: | |
| return false; | |
| } | |
| } | |
| return false; | |
| } | |
| function checkRowsInTaken() { | |
| switch (rerenderMode) { | |
| case "onelinebased": | |
| //OnelineBased checker | |
| return whichOnelinesInTaken(); | |
| break; | |
| case "squarebased": | |
| //SquareBased checker | |
| return whichSquareInTaken(); | |
| break; | |
| case "old": | |
| //Old no checker! | |
| return false; | |
| break; | |
| default: | |
| return false; | |
| } | |
| } | |
| function addScore(lines) { | |
| score += lines * 10; | |
| scoreDisplay.innerHTML = score; | |
| trySaveTheScore(score); | |
| } | |
| async function trySaveTheScore(score){ | |
| const isUserLoggedIn = checkUserIsLoggedIn(); | |
| const newScoreIsBigger = parseInt(localStorage.maxscore) < score; | |
| const renderableTheSave = (isUserLoggedIn && newScoreIsBigger)? doSaveScore() : false; | |
| console.log('Renderable the Save? ', renderableTheSave); | |
| if(renderableTheSave){ | |
| eventAtScoreSavedToServer(); | |
| CreateUserMaxScore(score); | |
| console.log('Stop save score : ', score); | |
| } | |
| } | |
| async function doSaveScore(){ | |
| console.log('Start save score : ', score); | |
| const response = await sendDataUpdate('score'); | |
| const data = (response.status === 200) ? response.json() : false; | |
| const savesatus = (data)? savesatus.isScoreUptate : 'false'; | |
| return savesatus; | |
| } | |
| function setRewardPic() { | |
| checkRewardExtra() && rewardPicDivSetHeight(score / 3); | |
| } | |
| function rewardPicDivSetHeight(value) { | |
| rewardPicDiv.style.height = value + "%"; | |
| } | |
| function dropNewTetromino() { | |
| if (gameSettings.tetrominoDropable === true) { | |
| random = nextRandom; | |
| nextRandom = Math.floor(Math.random() * theTetrominoes.length); | |
| current = theTetrominoes[random][currentRotation]; | |
| currentPosition = 4; | |
| draw(); | |
| displayShape(); | |
| } | |
| } | |
| //OnelineBasedRerender | |
| function rerenderOnelines(whichOnelinesInTaken) { | |
| whichOnelinesInTaken.map((oneline) => { | |
| removeOnelineFromTaken(oneline); | |
| !checkWeirdMode() && jumpOnelineToFirst(oneline); | |
| removeOnelineFromTetromino(oneline); | |
| }); | |
| return whichOnelinesInTaken.length; | |
| } | |
| function removeOnelineFromTaken(oneline) { | |
| [...grid.querySelectorAll(`[data-oneline="${oneline}"]`)].map((cell) => | |
| cell.classList.remove("taken") | |
| ); | |
| } | |
| function removeOnelineFromTetromino(oneline) { | |
| [...grid.querySelectorAll(`[data-oneline="${oneline}"]`)].map((cell) => { | |
| cell.classList.remove("tetromino"); | |
| cell.style = ""; | |
| }); | |
| } | |
| function jumpOnelineToFirst(oneline) { | |
| let firstSquare = getDOMElements().firstSquare(); | |
| getOneline(oneline).map((cell) => | |
| firstSquare.insertAdjacentElement("beforebegin", cell) | |
| ); | |
| //syncSuqares(); | |
| } | |
| function whichOnelinesInTaken() { | |
| //Check only in Activegameplace! | |
| let takenLineList = []; | |
| for (let oneline = 4; oneline < lineNumbers(); oneline++) { | |
| let result = checkOnlelineInTaken(oneline); | |
| result && takenLineList.push(oneline); | |
| } | |
| return takenLineList; | |
| } | |
| function checkOnlelineInTaken(oneline) { | |
| return [ | |
| ...grid.querySelectorAll(`[data-oneline="${oneline}"]`) | |
| ].every((cell) => cell.classList.contains("taken")); | |
| } | |
| function getOneline(oneline) { | |
| return [...grid.querySelectorAll(`[data-oneline="${oneline}"]`)].map( | |
| (cell) => cell | |
| ); | |
| } | |
| function getActivegameplaceOneline(oneline) { | |
| return [ | |
| ...grid.querySelectorAll(`.activegameplace[data-oneline="${oneline}"]`) | |
| ].map((cell) => cell); | |
| } | |
| //SquareBasedRerender | |
| function rerenderSquares(rows) { | |
| rows.map((row) => { | |
| uncolorizeRow(row); | |
| !checkWeirdMode() && jumpSquaresToFirst(row); | |
| }); | |
| return rows.length; | |
| } | |
| function whichSquareInTaken() { | |
| const { squares } = getDOMElements(); | |
| let takenLineList = []; | |
| for (let i = 0; i < squares.length - width - 1; i += width) { | |
| const row = [ | |
| i, | |
| i + 1, | |
| i + 2, | |
| i + 3, | |
| i + 4, | |
| i + 5, | |
| i + 6, | |
| i + 7, | |
| i + 8, | |
| i + 9 | |
| ]; | |
| if (row.every((index) => squares[index].classList.contains("taken"))) { | |
| takenLineList.push(row); | |
| } | |
| } | |
| return takenLineList; | |
| } | |
| function uncolorizeRow(row) { | |
| const { squares } = getDOMElements(); | |
| row.forEach((index) => { | |
| squares[index].classList.remove("taken"); | |
| squares[index].classList.remove("tetromino"); | |
| squares[index].style.backgroundColor = ""; | |
| }); | |
| } | |
| function jumpSquaresToFirst(row) { | |
| const { squares } = getDOMElements(); | |
| const firstSquare = getDOMElements().firstSquare(); | |
| row.forEach((index) => { | |
| firstSquare.insertAdjacentElement("beforebegin", squares[index]); | |
| }); | |
| } | |
| //OldRerender | |
| function rerenderGrids() { | |
| const { squares } = getDOMElements(); | |
| let count = 0; | |
| for (let i = 0; i < 229; i += width) { | |
| const row = [ | |
| i, | |
| i + 1, | |
| i + 2, | |
| i + 3, | |
| i + 4, | |
| i + 5, | |
| i + 6, | |
| i + 7, | |
| i + 8, | |
| i + 9 | |
| ]; | |
| if (row.every((index) => squares[index].classList.contains("taken"))) { | |
| console.log("ROW :" + row); | |
| count += 1; | |
| //Remove Classes and color from removed SQUARES | |
| row.forEach((index) => { | |
| squares[index].classList.remove("taken"); | |
| squares[index].classList.remove("tetromino"); | |
| squares[index].style.backgroundColor = ""; | |
| }); | |
| if (!checkWeirdMode()) { | |
| //Remove Full Squares | |
| const squaresRemoved = squares.splice(i, width); | |
| //Remove hidden SQUARES from Line0-Line1 | |
| const hiddenSquaresRemoved = squares.splice(0, width * 3); | |
| //Re-add to SQUARES the removed SQUARES | |
| squares = squaresRemoved.concat(squares); | |
| squares = hiddenSquaresRemoved.concat(squares); | |
| //Render new Squares | |
| squares.forEach((cell, key) => createNewGridLine(cell, key)); | |
| } | |
| } | |
| } | |
| return count; | |
| } | |
| function createNewGridLine(cell, key) { | |
| //console.log("CELL IN createNewGridLine ::: ") | |
| //console.log(cell) | |
| grid.appendChild(cell); | |
| } | |
| ///FIX ROTATION OF TETROMINOS A THE EDGE | |
| function isAtRight() { | |
| return current.some((index) => (currentPosition + index + 1) % width === 0); | |
| } | |
| function isAtLeft() { | |
| return current.some((index) => (currentPosition + index) % width === 0); | |
| } | |
| //Rotate functions | |
| function rotate() { | |
| undraw(); | |
| if (nextRotationInCollision()) { | |
| console.log("I CAN NOT TO ROTATE"); | |
| } else { | |
| currentRotation++; | |
| if (currentRotation === current.length) { | |
| //if the current rotation gets to 4, make it go back to 0 | |
| currentRotation = 0; | |
| } | |
| current = theTetrominoes[random][currentRotation]; | |
| rotationcorrection(); | |
| } | |
| draw(); | |
| } | |
| function rotationcorrection(P) { | |
| //console.log("CHECK ROTATED POSITION"); | |
| //console.log(P); | |
| P = P || currentPosition; //get current position. Then, check if the piece is near the left side. | |
| if ((P + 1) % width < 4) { | |
| //add 1 because the position index can be 1 less than where the piece is (with how they are indexed). | |
| if (isAtRight()) { | |
| //use actual position to check if it's flipped over to right side | |
| currentPosition += 1; //if so, add one to wrap it back around | |
| rotationcorrection(P); //check again. Pass position from start, since long block might need to move more. | |
| } | |
| } else if (P % width > 5) { | |
| if (isAtLeft()) { | |
| currentPosition -= 1; | |
| } | |
| } | |
| } | |
| function nextRotationInCollision() { | |
| return checkNextRotationInTaken() ? true : false; | |
| } | |
| function checkNextRotationInTaken() { | |
| const { squares } = getDOMElements(); | |
| nextRotation = currentRotation === 3 ? 0 : currentRotation + 1; | |
| nextRotatedCurrent = theTetrominoes[random][nextRotation]; | |
| return nextRotatedCurrent.some((index) => | |
| squares[currentPosition + index].classList.contains("taken") | |
| ) | |
| ? true | |
| : false; | |
| } | |
| ///////// | |
| //display the shape in the mini-grid display | |
| function displayShape() { | |
| displaySquares.forEach((square) => { | |
| square.classList.remove("tetromino"); | |
| square.style.backgroundColor = ""; | |
| }); | |
| upNextTetrominoes[nextRandom].forEach((index) => { | |
| displaySquares[displayIndex + index].classList.add("tetromino"); | |
| displaySquares[displayIndex + index].style.backgroundColor = | |
| colors[nextRandom]; | |
| }); | |
| } | |
| //Game Over functions | |
| function tryGameOver() { | |
| checkGameOver() && doItAtGameOver(); | |
| } | |
| function checkGameOver() { | |
| const { squares } = getDOMElements(); | |
| return ( | |
| squares[34].classList.contains("taken") || | |
| squares[35].classList.contains("taken") || | |
| squares[36].classList.contains("taken") | |
| ); | |
| } | |
| function doItAtGameOver() { | |
| actionsAtGameOver(); | |
| renderAtGameOver(); | |
| } | |
| function actionsAtGameOver() { | |
| stopTimers(); | |
| deactivateGameButtons(); | |
| } | |
| function stopTimers() { | |
| gameTimer.stop(); | |
| speeder.stop(); | |
| } | |
| function renderAtGameOver() { | |
| overScore.innerHTML = "SCORE : " + score; | |
| gameOverDiv.style.display = "block"; | |
| console.log("GAME OVERED"); | |
| } | |
| /// | |
| //TEMPLATES - Template Components | |
| // Grid template components | |
| function TemplateForGrid() { | |
| let gridDivs = ""; | |
| for (let count = 0; gridNumbers > count; count++) { | |
| let classnames = gridClassCalculator(gridNumbers, count); | |
| gridDivs += TemplateForGridDiv( | |
| classnames, | |
| count, | |
| Math.ceil((count + 1) / 10) | |
| ); | |
| } | |
| return ` | |
| ${gridDivs} | |
| `; | |
| } | |
| function gridClassCalculator(gridNumbers, count) { | |
| let classArray = []; | |
| count <= 29 && classArray.push("hidden"); | |
| gridNumbers - width <= count && classArray.push("taken"); | |
| gridNumbers - width > count && | |
| width * 3 <= count && | |
| classArray.push("activegameplace"); | |
| divisible(count, width) === count && classArray.push("first-in-row"); | |
| numberLastCharacter(count) === 9 && classArray.push("last-in-row"); | |
| let classnames = classArray.join(" "); | |
| return classnames; | |
| } | |
| function TemplateForGridDiv(classnames, count, oneline) { | |
| return ` | |
| <div class="${classnames}" data-serialnumber="${count}" data-oneline="${oneline}"></div> | |
| `; | |
| } | |
| // Grid template components END | |
| //HIGH-SCORE Template Component | |
| function HighScoreComponent(datas){ | |
| const highScores = datas.map(({UserName, UserScore}, item) =>{ | |
| return ` | |
| <tr><td>${item+1}.</td><td>${UserName}</td><td>${UserScore}</td></tr> | |
| `; | |
| }).join(' '); | |
| return ` | |
| <div id="highscoreinside"> | |
| <table id="scorelist"> | |
| <tbody> | |
| <tr> | |
| <th>Placed</th> | |
| <th>Name</th> | |
| <th>Score</th> | |
| </tr> | |
| ${highScores} | |
| </tbody> | |
| </table> | |
| </div> | |
| `; | |
| } | |
| //HIGH-SCORE Template Component END | |
| //LOADING Component Template | |
| function LoadingComponent(){ | |
| return ` | |
| <div class="fullcenter"> | |
| <img src="https://bzozoo.github.io/Tetris-Basic//images/loading.gif" alt="loading"> | |
| </div> | |
| `; | |
| } | |
| //LOADING Component Template END | |
| // LOGIN / REGISTER Template components | |
| function LogRegComponent() { | |
| return ` | |
| <form id="loginform"> | |
| <fieldset> | |
| <div id="loginformbox"> | |
| <div class="navbar"><div class="title">LOGIN</div></div> | |
| <p><label for="username">Username</labe> | |
| <input id="username" name="username" placeholder="Yourname"/></p> | |
| <p><label for="passwd">Password</label> | |
| <input id="passwd" name="passwd" type="password" placeholder="8 character"/></p> | |
| <div class="fullcenter"> | |
| <button id="loginsend" class="actionBtn">LOGIN</button> | |
| </div> | |
| </div> | |
| </fieldset> | |
| </form> | |
| <form id="regform" autocomplete="off"> | |
| <fieldset> | |
| <div id="regformbox"> | |
| <div class="navbar"><div class="title">REGISTRATION</div></div> | |
| <p><label for="regusername">Username</labe> | |
| <input id="regusername" name="regusername" placeholder="Yourname" autocomplete="off" /></p> | |
| <p><label for="regpasswd">Password (min 8 character)</label> | |
| <input id="regpasswd" name="regpasswd" type="password" placeholder="8 character" autocomplete="new-password" /></p> | |
| <p><label for="regpasswdagain">Password-again</label> | |
| <input id="regpasswdagain" name="regpasswdagain" type="password" placeholder="8 character" /></p> | |
| <div class="fullcenter"> | |
| <button id="regsend"class="actionBtn">REGISTER</button> | |
| </div> | |
| </div> | |
| </fieldset> | |
| </form> | |
| `; | |
| } | |
| // LOGIN / REGISTER Template components END | |
| //USER PROFILE Template Components | |
| function UserContainerComponent({ UserName, UserScore, UserAvatar, ExpiredTimeStamp }){ | |
| const avatar = UserAvatar === null? '<img src="https://bzozoo.github.io/Tetris-Basic/images/defprofpic.jpg" />' : `<img src="${UserAvatar}" />`; | |
| const ExpiredTime = new Date(ExpiredTimeStamp*1000).toLocaleString(); | |
| return ` | |
| <div class="navbar"> | |
| <div class="title">Hi, ${UserName}</div> | |
| </div> | |
| <fieldset> | |
| <div id="userpanel"> | |
| <div id="userprofilepicture"> | |
| ${avatar} | |
| </div> | |
| <div id="userpersonaldatas"> | |
| <p>Your own record</p> | |
| <h2>${UserScore} point</h2> | |
| </div> | |
| </div> | |
| <hr /> | |
| <div class="fullcenter"> | |
| <button id="logoutBtn" class="actionBtn">LOGOUT</button> | |
| <div class="smallfont mt-05rem">Automatical logout at: ${ExpiredTime}</div> | |
| </div> | |
| </fieldset> | |
| `; | |
| } | |
| //USER PROFILE Template Components END | |
| // TEMPLATES END - Template components END | |
| ////HELPERS / Checkers | |
| function divisible(dividend, divisor) { | |
| if (dividend % divisor == 0) { | |
| return dividend; | |
| } else { | |
| var num = dividend + (divisor - (dividend % divisor)); | |
| return num; | |
| } | |
| } | |
| function numberLastCharacter(number) { | |
| let string = number.toString(); | |
| return parseInt(string[string.length - 1]); | |
| } | |
| function recurs(num, max, recurses = []) { | |
| if (max >= num) { | |
| return recurs(num + 1, max, [...recurses, num]); | |
| } | |
| return recurses; | |
| } | |
| function IntervalEncapsulator(fn, time) { | |
| let timer = false; | |
| this.start = function () { | |
| timer = !this.status() ? setInterval(fn, time) : timer; | |
| }; | |
| this.stop = function () { | |
| clearInterval(timer); | |
| timer = false; | |
| }; | |
| this.setTime = function (newTime) { | |
| if (!isNaN(newTime) && newTime != undefined && newTime) { | |
| console.log("SET NEW TIME ::: " + newTime); | |
| const oldStatus = this.status(); | |
| this.stop(); | |
| time = newTime; | |
| oldStatus && this.start(); | |
| } | |
| }; | |
| this.status = function () { | |
| return timer !== false; | |
| }; | |
| this.checkInterval = function () { | |
| return time; | |
| }; | |
| this.showDefault = time; | |
| } | |
| function backcounter(count) { | |
| return { | |
| doBackCount: doBackCount(), | |
| getActualCount: getActualCount(), | |
| getDefaultCount: getDefaultCount(), | |
| restartBackCount: restartBackCount(count) | |
| }; | |
| function doBackCount() { | |
| return function () { | |
| return (count = count === 0 ? 0 : count - 1); | |
| }; | |
| } | |
| function getActualCount() { | |
| return function () { | |
| return count; | |
| }; | |
| } | |
| function getDefaultCount() { | |
| return count; | |
| } | |
| function restartBackCount(recount) { | |
| return function () { | |
| return (count = recount); | |
| }; | |
| } | |
| } | |
| //COMMANDS for Backcounter | |
| //run.doBackCount() | |
| //run.getActualCount() | |
| //run.getDefaultCount | |
| //run.restartBackCount() | |
| // | |
| function getDOMElements() { | |
| return { | |
| squares: Array.from(document.querySelectorAll(".grid div")), | |
| firstSquare: function () { | |
| return this.squares[30]; | |
| }, | |
| squaresInActiveGameplace: Array.from( | |
| grid.querySelectorAll(".activegameplace") | |
| ), | |
| firstSquareInRow: document.querySelectorAll(".first-in-row"), | |
| lastSquareInRow: document.querySelectorAll(".last-in-row"), | |
| music: document.getElementById("myAudio") | |
| }; | |
| } | |
| function checkUserIsLoggedIn() { | |
| return ( | |
| localStorage.hasOwnProperty("UserName") && | |
| localStorage.hasOwnProperty("UserJWT") && | |
| localStorage.hasOwnProperty("maxscore") | |
| ); | |
| } | |
| function CreateAllUserInformations(username, usertoken){ | |
| localStorage.setItem("UserName", username); | |
| localStorage.setItem("UserJWT", usertoken); | |
| } | |
| function CreateUserMaxScore(score){ | |
| localStorage.setItem('maxscore', score); | |
| } | |
| function deleteAllUserInformations(){ | |
| localStorage.removeItem("UserName"); | |
| localStorage.removeItem("UserJWT"); | |
| localStorage.removeItem("maxscore"); | |
| return true; | |
| } | |
| function regdatasValidator(){ | |
| const username = regform.regusername.value; | |
| const passwd = regform.regpasswd.value; | |
| const passwdagain = regform.regpasswdagain.value; | |
| const usernameNotEmpty = (username !== ''); | |
| const usernameIsClean = username.match(/^[a-zA-Z0-9)\(]+$/g) !== null ? true : false; | |
| const passPower = passwd.length >= 8; | |
| const passMatch = (passwd === passwdagain); | |
| const isValid = ( usernameIsClean && passPower && passMatch && usernameNotEmpty); | |
| return { | |
| usernameIsClean, | |
| usernameNotEmpty, | |
| passPower, | |
| passMatch, | |
| isValid | |
| } | |
| } | |
| //HELPERS / Checkers END | |
| //EVENTS | |
| function fasterDown() { | |
| speeder.start(); | |
| } | |
| function fasterDownStop() { | |
| speeder.stop(); | |
| } | |
| function extraFastDown() { | |
| if (!lockCheck()) { | |
| tryFreeze(); | |
| setTimeout(function () { | |
| extraFastDown(); | |
| }, 25); | |
| } | |
| } | |
| function control(e) { | |
| e.keyCode === 37 && moveLeft(); | |
| e.keyCode === 38 && rotate(); | |
| e.keyCode === 39 && moveRight(); | |
| e.keyCode === 35 && extraFastDown(); | |
| } | |
| function controlDown(e) { | |
| e.keyCode === 40 && fasterDown(); | |
| document.removeEventListener("keydown", controlDown); | |
| } | |
| function controlUp(e) { | |
| e.keyCode === 40 && fasterDownStop(); | |
| document.addEventListener("keydown", controlDown); | |
| } | |
| function activateGameButtons() { | |
| document.addEventListener("keydown", control); | |
| document.addEventListener("keydown", controlDown); | |
| document.addEventListener("keyup", controlUp); | |
| leftMove.addEventListener("mousedown", moveLeft); | |
| rightMove.addEventListener("mousedown", moveRight); | |
| downMove.addEventListener("click", tryFreeze); | |
| downMove.addEventListener("touchstart", fasterDown); | |
| downMove.addEventListener("touchend", fasterDownStop); | |
| downMove.addEventListener("mousedown", fasterDown); | |
| downMove.addEventListener("mouseup", fasterDownStop); | |
| rotation.addEventListener("mousedown", rotate); | |
| resetButton.addEventListener("click", initGame); | |
| console.log("GAME BUTTONS ACTIVATED"); | |
| } | |
| function deactivateGameButtons() { | |
| if (controllButtonsDeactivable) { | |
| document.removeEventListener("keydown", control); | |
| document.removeEventListener("keydown", controlDown); | |
| document.removeEventListener("keyup", controlUp); | |
| controllButtonsSection.innerHTML = controllButtonsSection.innerHTML; | |
| console.log("GAME BUTTONS DEACTIVATED"); | |
| } | |
| } | |
| //scoreBox Open Event | |
| scoreBox.addEventListener("click", async () => { | |
| highscorecontent.innerHTML = ''; | |
| highscore.classList.remove("hidden"); | |
| const datas = await getHighScoreSorted(); | |
| const highscorecontentstring = (datas.error === undefined)? await HighScoreComponent(datas) : 'Server error! Try again later!'; | |
| highscorecontent.innerHTML = highscorecontentstring; | |
| }); | |
| //scoreBox Close Event | |
| closeHighScore.addEventListener("click", () => { | |
| highscore.classList.add("hidden"); | |
| }); | |
| //Login Button Event | |
| loginBtn.addEventListener("click", () => { | |
| userzone.classList.remove("hidden"); | |
| }); | |
| //UserZone Close Button Event | |
| closeUserZone.addEventListener("click", () => { | |
| userzone.classList.add("hidden"); | |
| }); | |
| // Profile Button Events | |
| profileBtn.addEventListener('click', ()=>{ | |
| openUserZone(); | |
| reloadUserZone(); | |
| }) | |
| function openUserZone(){ | |
| userzone.classList.remove("hidden"); | |
| } | |
| async function reloadUserZone(){ | |
| const userdatas = await getUserDatas(); | |
| if(userdatas.UserName !== undefined && userdatas.UserScore !== undefined){ | |
| usercontainer.innerHTML = UserContainerComponent(userdatas); | |
| logoutBtn.addEventListener('click', doLogout); | |
| } | |
| if(userdatas.responsestatus === 401 || (userdatas.UserName !== undefined && userdatas.UserName !== localStorage.UserName)){ | |
| Swal.fire({ | |
| position: 'top-end', | |
| icon: 'error', | |
| title: 'Invalid identifiers! <br />You have been logged out!', | |
| showConfirmButton: false, | |
| timer: 3000 | |
| }); | |
| doLogout(); | |
| } | |
| if(localStorage.maxscore === undefined){ | |
| Swal.fire({ | |
| position: 'top-end', | |
| icon: 'error', | |
| title: 'Maxscore datas was removed! <br />You have been logged out!', | |
| showConfirmButton: false, | |
| timer: 5000 | |
| }); | |
| doLogout(); | |
| } | |
| (userdatas.servererror === true) && | |
| Swal.fire({ | |
| position: 'top-end', | |
| icon: 'error', | |
| title: 'Server error!', | |
| showConfirmButton: false, | |
| timer: 3000 | |
| }); | |
| } | |
| // Profile Button Events END | |
| //START/PAUSE button EVENT | |
| startBtn.addEventListener("click", () => { | |
| let gameTimerStatus = gameTimer.status(); | |
| !gameTimerStatus && activateGameButtons(); | |
| gameTimerStatus && deactivateGameButtons(); | |
| displayShape(); | |
| startpauseSwitcher(gameTimer.status()); | |
| startpauseButtonSwitcher(gameTimer.status()); | |
| }); | |
| function startpauseSwitcher(gameTimerStatus) { | |
| console.log(" SWITCH START / PAUSE "); | |
| !gameTimerStatus && gameTimer.start(); | |
| gameTimerStatus && gameTimer.stop(); | |
| } | |
| function startpauseButtonSwitcher(gameTimerStatus) { | |
| startBtn.innerHTML = !gameTimerStatus ? "▶ RE-START" : "⏸ PAUSE"; | |
| } | |
| ///// | |
| //Mute button event | |
| muteButton.addEventListener("click", () => { | |
| muteSwitcher(musicInterval.status()); | |
| muteButtonSwitcher(musicInterval.status()); | |
| }); | |
| function muteSwitcher(musicIntervalStatus) { | |
| console.log("MUTE ON / OFF"); | |
| musicIntervalStatus === false && musicInterval.start(); | |
| musicIntervalStatus === true && musicInterval.stop(); | |
| getDOMElements().music.pause(); | |
| } | |
| function muteButtonSwitcher(musicIntervalStatus) { | |
| muteButton.innerHTML = musicIntervalStatus === false ? "🔇 MUTE" : "🔈 MUTE"; | |
| } | |
| function playMusic() { | |
| getDOMElements().music.play(); | |
| } | |
| /// | |
| ///Options Button events | |
| document.addEventListener("keydown", panelcontrol); | |
| optionsButton.addEventListener("click", toggleOptionPanel); | |
| closeOPtions.addEventListener("click", toggleOptionPanel); | |
| function panelcontrol(e) { | |
| //e.ctrlKey | |
| (e.altKey && e.keyCode === 79) && toggleOptionPanel(); | |
| } | |
| function toggleOptionPanel() { | |
| optionspanel.classList.toggle("hidden"); | |
| paneloverlay.classList.toggle("blured"); | |
| } | |
| /// | |
| ///Panel Overlay Events | |
| function closeAllModalsAndOverlay() { | |
| console.log("CLOSE ALL MODALS"); | |
| paneloverlay.classList.remove("blured"); | |
| [...document.querySelectorAll(".modal")].map((modals) => | |
| modals.classList.add("hidden") | |
| ); | |
| } | |
| /// | |
| //Invert chkbox event | |
| invertCheckBox.addEventListener("change", transformTheGrid); | |
| function transformTheGrid() { | |
| grid.style.transform = checkGridInTransform() ? "" : "rotate(180deg)"; | |
| } | |
| function checkGridInTransform() { | |
| return grid.style.transform === "" ? false : true; | |
| } | |
| /// | |
| //Reward chkbox event | |
| rewardCheckBox.addEventListener("change", () => { | |
| rewardFunctionSwitch(checkRewardExtra()); | |
| }); | |
| function rewardFunctionSwitch(checkRewardExtra) { | |
| checkRewardExtra && doItIfRewardExtra(); | |
| !checkRewardExtra && doItIfNotRewardExtra(); | |
| console.log(`ACTUAL REWARD: ${localStorage.getItem("storedReward")}`); | |
| } | |
| function doItIfRewardExtra() { | |
| localStorage.setItem("storedReward", false); | |
| rewardPicDivSetHeight(0); | |
| } | |
| function doItIfNotRewardExtra() { | |
| localStorage.setItem("storedReward", true); | |
| setRewardPic(); | |
| } | |
| //// | |
| //WeirdMode checkbox event | |
| weird.addEventListener("change", () => { | |
| localStorage.setItem("storedWeirdMode", weird.checked); | |
| }); | |
| /// | |
| //Login Logout Process Event | |
| async function loginProcess(){ | |
| console.log('Login process...'); | |
| const loginDatas = await getLoginDatas(); | |
| const everythingIsGood = (loginDatas.error === undefined && loginDatas.responsestatus === undefined); | |
| everythingIsGood && doLogin(loginDatas.UserName, loginDatas.UTOK, loginDatas.UserScore); | |
| (loginDatas.responsestatus === 401) && | |
| Swal.fire({ | |
| position: 'top-end', | |
| icon: 'error', | |
| title: 'Wrong username or password!', | |
| showConfirmButton: false, | |
| timer: 3000 | |
| }); | |
| (loginDatas.servererror === true) && | |
| Swal.fire({ | |
| position: 'top-end', | |
| icon: 'error', | |
| title: 'Server error!', | |
| showConfirmButton: false, | |
| timer: 3000 | |
| }); | |
| } | |
| function doLogin(username, usertoken, maxscore){ | |
| CreateAllUserInformations(username, usertoken); | |
| CreateUserMaxScore(maxscore); | |
| tryLoginRender(); | |
| } | |
| function doLogout(){ | |
| const deleteSuccess = deleteAllUserInformations() | |
| deleteSuccess && emptyPanels(); | |
| deleteSuccess && logoutRender(); | |
| } | |
| //Login Logout Process Event END | |
| // Register Events | |
| async function registerProcess(){ | |
| console.log('Register...'); | |
| regsend.disabled = true; | |
| const validator = regdatasValidator(); | |
| if(!validator.isValid){ | |
| !validator.passMatch && Swal.fire({ | |
| position: 'top-end', | |
| icon: 'error', | |
| title: 'The two passwords do not match!', | |
| showConfirmButton: false, | |
| timer: 3000 | |
| }); | |
| !validator.passPower && Swal.fire({ | |
| position: 'top-end', | |
| icon: 'error', | |
| title: 'Min 8 characters!', | |
| showConfirmButton: false, | |
| timer: 3000 | |
| }); | |
| !validator.usernameIsClean && Swal.fire({ | |
| position: 'top-end', | |
| icon: 'error', | |
| title: 'Special characters are not allowed in username!', | |
| showConfirmButton: false, | |
| timer: 3000 | |
| }); | |
| !validator.usernameNotEmpty && Swal.fire({ | |
| position: 'top-end', | |
| icon: 'error', | |
| title: 'Username field is empty!', | |
| showConfirmButton: false, | |
| timer: 3000 | |
| }); | |
| } | |
| if(validator.isValid){ | |
| const regdata = await registrationDataSender(); | |
| regdata.responsestatus === 409 && Swal.fire({ | |
| position: 'top-end', | |
| icon: 'error', | |
| title: 'User is exist!<br />Choose another name!', | |
| showConfirmButton: false, | |
| timer: 3000 | |
| }); | |
| regdata.servererror && Swal.fire({ | |
| position: 'top-end', | |
| icon: 'error', | |
| title: 'Server Error!', | |
| showConfirmButton: false, | |
| timer: 3000 | |
| }); | |
| regdata.Registration === 'Success' && Swal.fire({ | |
| position: 'top-end', | |
| icon: 'success', | |
| title: 'Registration is success!<br /> You can login now ', | |
| showConfirmButton: false, | |
| timer: 3000 | |
| }); | |
| } | |
| emptyRegdataFields(); | |
| regsend.disabled = false; | |
| } | |
| // Register Events END | |
| //EVENT RENDERS | |
| //Login / Logout Event Renders | |
| function tryLoginRender(){ | |
| emptyPanels(); | |
| const isUserLoggedIn = checkUserIsLoggedIn(); | |
| if(!isUserLoggedIn){ | |
| document.querySelector("#login").insertAdjacentHTML("afterbegin", LogRegComponent()) | |
| loginform.addEventListener('submit', ()=>{ | |
| event.preventDefault();loginProcess(); | |
| }); | |
| regform.addEventListener('submit', ()=>{ | |
| event.preventDefault(),registerProcess(); | |
| }); | |
| } | |
| if(isUserLoggedIn){ | |
| reloadUserZone(); | |
| toggleLoginButtonToProfileButton(); | |
| } | |
| } | |
| function logoutRender(){ | |
| toggleLoginButtonToProfileButton() | |
| document.querySelector("#login").insertAdjacentHTML("afterbegin", LogRegComponent()); | |
| loginform.addEventListener('submit', ()=>{ | |
| event.preventDefault();loginProcess(); | |
| }); | |
| regform.addEventListener('submit', ()=>{ | |
| event.preventDefault(),registerProcess(); | |
| }); | |
| } | |
| function toggleLoginButtonToProfileButton(){ | |
| document.querySelector('#loginBtn').classList.toggle('hidden'); | |
| document.querySelector('#profileBtn').classList.toggle('hidden'); | |
| } | |
| //Login /Logout Event Renders END | |
| //Empty Panels renders | |
| function emptyPanels(){ | |
| const panels = document.querySelectorAll('.panel'); | |
| [...panels].map(panel => panel.innerHTML = ''); | |
| } | |
| //Empty Panels renders END | |
| //Empty regdatas | |
| function emptyRegdataFields(){ | |
| const regforminput = document.querySelectorAll('#regform input'); | |
| [...regforminput].map(regforminput => regforminput.value = ''); | |
| } | |
| //Empty regdatas END | |
| //Event at score saved to server | |
| function eventAtScoreSavedToServer(){ | |
| scoresavedbox.classList.remove('hidden'); | |
| setTimeout(()=>{ | |
| scoresavedbox.classList.add('hidden'); | |
| }, 3000) | |
| } | |
| // | |
| //EVENT RENDERS | |
| //EVENTS END | |
| ///FETCH DATA FUNCTIONS | |
| async function getHighScore(){ | |
| try { | |
| const response = await fetch(`${host}/api/userscore`); | |
| const data = await (response.status === 200) ? response.json() : { 'error': `Response staus ::: ${response.status}`, 'responsestatus': response.status }; | |
| return data; | |
| }catch(e){ | |
| return { 'error': e, 'servererror':true } | |
| } | |
| } | |
| async function getHighScoreSorted(){ | |
| const data = await getHighScore(); | |
| if(data.error === undefined){ | |
| let dataByScore = data.slice(0); | |
| dataByScore.sort(function (a, b) { | |
| return b.UserScore - a.UserScore; | |
| }); | |
| return dataByScore; | |
| } | |
| return false; | |
| } | |
| async function getLoginDatas() { | |
| const username = loginform.username.value; | |
| const passwd = loginform.passwd.value; | |
| const formData = new FormData(); | |
| formData.append("nameField", username); | |
| formData.append("passField", passwd); | |
| const options = { | |
| method: "POST", | |
| body: formData | |
| }; | |
| try { | |
| const response = await fetch(`${host}/api/login`, options); | |
| const data = await (response.status === 200) ? response.json() : { 'error': `Response staus ::: ${response.status}`, 'responsestatus': response.status }; | |
| return data; | |
| }catch(e){ | |
| return { 'error': e, 'servererror':true } | |
| } | |
| } | |
| async function registrationDataSender(){ | |
| const username = regform.regusername.value; | |
| const passwd = regform.regpasswd.value; | |
| const formData = new FormData(); | |
| formData.append("reguser", username); | |
| formData.append("regpwd", passwd); | |
| const options = { | |
| method: "POST", | |
| body: formData | |
| }; | |
| try { | |
| const response = await fetch(`${host}/api/register`, options); | |
| const data = await (response.status === 201) ? response.json() : { 'error': `Response staus ::: ${response.status}`, 'responsestatus': response.status }; | |
| return data; | |
| }catch(e){ | |
| return { 'error': e, 'servererror':true } | |
| } | |
| } | |
| async function getUserDatas(){ | |
| const options = { | |
| method: "POST", | |
| headers: { | |
| Authorization: `Bearer ${localStorage.UserJWT}` | |
| }, | |
| }; | |
| try { | |
| const response = await fetch(`${host}/api/user`, options); | |
| const data = await (response.status === 200) ? response.json() : { 'error': `Response staus ::: ${response.status}`, 'responsestatus': response.status }; | |
| return data; | |
| }catch(e){ | |
| return { 'error': e, 'servererror':true } | |
| } | |
| } | |
| async function sendDataUpdate(type){ | |
| let data = ''; | |
| if(type === 'score'){ | |
| const grid = document.querySelector('.grid').innerHTML; | |
| data = `score=${score}&grid=${grid}`; | |
| } | |
| const options = { | |
| method: "POST", | |
| headers: { | |
| 'Content-Type':'application/x-www-form-urlencoded', | |
| Authorization: `Bearer ${localStorage.UserJWT}` | |
| }, | |
| body: data | |
| }; | |
| const response = await fetch(`${host}/api/user/update`, options); | |
| const datas = await response.json(); | |
| return datas; | |
| } | |
| ///FETCH DATA FUNCTIONS END | |
| //DevFunctions | |
| function numberisedSquares() { | |
| let counter = 0; | |
| getDOMElements().squares.map((square) => (square.innerHTML = counter++)); | |
| } | |
| function numberisedOneline() { | |
| getDOMElements().squares.map( | |
| (square) => (square.innerHTML = square.dataset.oneline) | |
| ); | |
| } | |
| function squareToOneline(square) { | |
| const { squares } = getDOMElements(); | |
| return squares[square].dataset.oneline; | |
| } | |
| function squareToOnelineNum(square) { | |
| return parseInt(squareToOneline(square)); | |
| } | |
| function addOnelineToTaken(oneline) { | |
| [...grid.querySelectorAll(`[data-oneline="${oneline}"]`)].map((cell) => | |
| cell.classList.add("taken") | |
| ); | |
| } | |
| function addToTakenToSquares(squaresStart, squaresMax) { | |
| return recurs(squaresStart, squaresMax).map( | |
| (item) => (squares[item].className += " taken tetromino") | |
| ); | |
| } | |
| function squaresInOneline(oneline) { | |
| return getOneline(oneline).map((cell) => | |
| parseInt(cell.dataset.serialnumber) | |
| ); | |
| } | |
| function makeTestLines() { | |
| addToTakenToSquares(200, 208); | |
| addToTakenToSquares(210, 218); | |
| addToTakenToSquares(220, 228); | |
| addToTakenToSquares(230, 238); | |
| } | |
| function arrToArg(squaresArray) { | |
| return squaresArray.map((squareArray) => squareArray); | |
| } | |
| function addOnelineToTakenAndColorizeThat(oneline) { | |
| addOnelineToTaken(oneline); | |
| turnToPinkAllTakensOnActiveGameplace(); | |
| } | |
| function removeAllTakenFromActiveGameplace() { | |
| const { squaresInActiveGameplace } = getDOMElements(); | |
| squaresInActiveGameplace.map((square) => { | |
| square.classList.remove("taken"); | |
| turnToPinkAllTakensOnActiveGameplace(); | |
| }); | |
| } | |
| function removeOneline(oneline) { | |
| getOneline(oneline).map((cell) => cell.remove()); | |
| } | |
| function getAllActiveGameplaces() { | |
| return [...grid.querySelectorAll(".activegameplace")]; | |
| } | |
| function turnToPinkActiveGameplace() { | |
| getAllActiveGameplaces().map( | |
| (cell) => (cell.style.backgroundColor = "pink") | |
| ); | |
| } | |
| function turnToPinkAllTakensOnActiveGameplace() { | |
| getAllActiveGameplaces().map( | |
| (cell) => | |
| (cell.style.backgroundColor = cell.classList.contains("taken") | |
| ? "pink" | |
| : "") | |
| ); | |
| } | |
| function removeOnelineFromTakenAndUnColorizeThat(oneline) { | |
| removeOnelineFromTaken(oneline); | |
| turnToPinkAllTakensOnActiveGameplace(); | |
| } | |
| function getOnelineNodes(oneline) { | |
| return grid.querySelectorAll(`.activegameplace[data-oneline="${oneline}"]`); | |
| } | |
| const getCurrentInSquare = () => [ | |
| parseInt(currentPosition) + parseInt(current[0]), | |
| parseInt(currentPosition) + parseInt(current[1]), | |
| parseInt(currentPosition) + parseInt(current[2]), | |
| parseInt(currentPosition) + parseInt(current[3]) | |
| ]; | |
| const getNextRotatedCurrentInSquare = () => [ | |
| parseInt(currentPosition) + parseInt(nextRotatedCurrent[0]), | |
| parseInt(currentPosition) + parseInt(nextRotatedCurrent[1]), | |
| parseInt(currentPosition) + parseInt(nextRotatedCurrent[2]), | |
| parseInt(currentPosition) + parseInt(nextRotatedCurrent[3]) | |
| ]; | |
| function checkCurrent() { | |
| const { squares } = getDOMElements(); | |
| console.log( | |
| "CURRENT TETRROMINO: " + | |
| tetrominoNames[random] + | |
| " - ACTUAL RANDOM: " + | |
| random + | |
| " - PROFILE: " + | |
| current + | |
| "CURRENT POSITION: " + | |
| currentPosition | |
| ); | |
| // Show actual current divlist on Console | |
| current.forEach((index) => { | |
| console.log(squares[currentPosition + index]); | |
| }); | |
| console.log("SQUARES NUMBERS : " + getCurrentInSquare().join(" - ") + " ! "); | |
| nextRotation = currentRotation === 3 ? 0 : currentRotation + 1; | |
| nextRotatedCurrent = theTetrominoes[random][nextRotation]; | |
| console.log("Next Rotation: " + nextRotation); | |
| console.log( | |
| "NEXT ROTATED SQUARES NUMBERS: " + | |
| getNextRotatedCurrentInSquare().join(" - ") + | |
| " ! " | |
| ); | |
| // Show next rotation divlist on Console | |
| nextRotatedCurrent.forEach((index) => { | |
| console.log(squares[currentPosition + index]); | |
| }); | |
| } | |
| // } //MAIN END })(); //IIFE END |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| body { | |
| font-family: sans-serif; | |
| margin: 5px; | |
| background-color: #00a8f3; | |
| height: 99%; | |
| width: 400px; | |
| overflow: hidden; | |
| touch-action: manipulation; | |
| -webkit-touch-callout: none; /* iOS Safari */ | |
| -webkit-user-select: none; /* Safari */ | |
| -khtml-user-select: none; /* Konqueror HTML */ | |
| -moz-user-select: none; /* Old versions of Firefox */ | |
| -ms-user-select: none; /* Internet Explorer/Edge */ | |
| user-select: none;*/ /* Non-prefixed version, currently | |
| supported by Chrome, Edge, Opera and Firefox */ | |
| } | |
| :root { | |
| --placeholder-color: #1d4762; | |
| --bluetext-color: #3f48cc; | |
| --lcdpanel-color: #bbdaf7; | |
| } | |
| * { | |
| outline: none; | |
| } | |
| #scoresavedbox { | |
| z-index: 11; | |
| position: absolute; | |
| margin-top: 0.2rem; | |
| left: 17.3rem; | |
| font-size: 0.9rem; | |
| font-weight: bold; | |
| color: var(--bluetext-color); | |
| background-color: var(--lcdpanel-color); | |
| } | |
| .container { | |
| margin: 5px; | |
| display: flex; | |
| min-width: 392px; | |
| } | |
| #gameOverDiv { | |
| background: url(https://bzozoo.github.io/Tetris-Basic/images/gameover.jpg); | |
| min-width: 200px; | |
| width: 250px; | |
| height: 526px; | |
| margin-top: 2px; | |
| margin-left: 7px; | |
| position: absolute; | |
| z-index: 1; | |
| font-family: sans-serif; | |
| /*display: none;*/ | |
| } | |
| .activegameplace { | |
| /*background-image: url("https://raw.githubusercontent.com/bzozoo/Tetris-Basic/master/images/boomm.gif");*/ | |
| background-size: contain; | |
| background-repeat: no-repeat; | |
| } | |
| #rewardContainer { | |
| /* background: green; */ | |
| min-width: 200px; | |
| width: 251px; | |
| height: 526px; | |
| margin-top: 5px; | |
| margin-left: 7px; | |
| position: absolute; | |
| /*display: none;*/ | |
| z-index: -1; | |
| } | |
| #rewardPicDiv { | |
| background: yellow; | |
| /* opacity: 0.6; */ | |
| height: 0%; | |
| max-height: 100%; | |
| width: 100%; | |
| background-repeat: no-repeat; | |
| background-size: 100% 526px; | |
| } | |
| #scoreDisplay { | |
| font-size: 30px; | |
| color: red; | |
| text-align: center; | |
| margin-top: 2px; | |
| margin-bottom: 2px; | |
| font-family: sans-serif; | |
| } | |
| #scoreBox { | |
| font-family: sans-serif; | |
| margin-bottom: 15px; | |
| border: 2px black solid; | |
| padding: 0px; | |
| width: 100%; | |
| height: 60px; | |
| background-color: #bbdaf7; | |
| box-shadow: 5px 5px 10px 5px grey; | |
| text-align: center; | |
| color: #3f48cc; | |
| } | |
| #scoreBox p { | |
| margin: 1px; | |
| } | |
| #overScore { | |
| margin-top: 340px; | |
| width: 100%; | |
| text-align: center; | |
| color: blue; | |
| font-size: 30px; | |
| } | |
| #speedBox { | |
| font-family: sans-serif; | |
| margin-bottom: 15px; | |
| border: 2px black solid; | |
| padding: 0px; | |
| width: 100%; | |
| height: 1rem; | |
| background-color: #bbdaf7; | |
| box-shadow: 5px 5px 10px 5px grey; | |
| text-align: left; | |
| color: #3f48cc; | |
| } | |
| #speedBox strong{ | |
| margin-right: 8px; | |
| } | |
| .actions { | |
| text-align: left; | |
| } | |
| .actions button { | |
| width: 115px; | |
| text-align: center; | |
| } | |
| .controlls { | |
| margin-left: 30px; | |
| padding-top: 0px; | |
| } | |
| .gombBtn { | |
| background-color: #3f48cc; | |
| padding: 15px; | |
| border-radius: 50%; | |
| box-shadow: 5px 5px 10px 5px grey; | |
| margin-right: 15px; | |
| border-width: 10px; | |
| font-size: 20px; | |
| } | |
| .actionBtn { | |
| box-shadow:inset 0px 1px 0px 0px #bbdaf7; | |
| background:linear-gradient(to bottom, #79bbff 5%, #378de5 100%); | |
| background-color:#79bbff; | |
| border-radius:6px; | |
| border:1px solid #84bbf3; | |
| cursor:pointer; | |
| color:#ffffff; | |
| font-family:Arial; | |
| font-size:13px; | |
| font-weight:bold; | |
| padding:6px 24px; | |
| text-decoration:none; | |
| text-shadow:0px 1px 0px #528ecc; | |
| } | |
| .actionBtn:hover { | |
| background:linear-gradient(to bottom, #378de5 5%, #79bbff 100%); | |
| background-color:#378de5; | |
| } | |
| .actionBtn:active { | |
| position:relative; | |
| top:1px; | |
| } | |
| button:active{ | |
| background-color:red; | |
| box-shadow: none; | |
| } | |
| .grid { | |
| /* transform: rotate(180deg); | |
| */ | |
| border: 2px black solid; | |
| min-width: 200px; | |
| width: 250px; | |
| height: 525px; | |
| display: flex; | |
| flex-wrap: wrap; | |
| /* background-color: #d0f5a9;*/ | |
| /* box-shadow: 5px 5px 10px 5px grey; */ | |
| } | |
| .grid-bg { | |
| border: 2px black solid; | |
| min-width: 200px; | |
| width: 250px; | |
| height: 524px; | |
| flex-wrap: wrap; | |
| background-color: #bbdaf7; | |
| box-shadow: 5px 5px 10px 5px grey; | |
| position: absolute; | |
| z-index: -2; | |
| } | |
| .transformed { | |
| box-shadow: -5px -5px 10px 5px grey; | |
| } | |
| .grid div { | |
| height: 25px; | |
| width: 25px; | |
| font-size: 10px; | |
| } | |
| .tetromino { | |
| background-color: blue; | |
| opacity: 0.6; | |
| } | |
| .sidebar { | |
| margin-left: 10px; | |
| width: 116px; | |
| } | |
| .mini-grid { | |
| font-family: sans-serif; | |
| margin-bottom: 15px; | |
| border: 2px black solid; | |
| padding: 0px; | |
| width: 100%; | |
| height: 120px; | |
| display: flex; | |
| flex-wrap: wrap; | |
| background-color: #bbdaf7; | |
| box-shadow: 5px 5px 10px 5px grey; | |
| text-align: center; | |
| color: #3f48cc; | |
| font-weight: bold; | |
| } | |
| .mini-grid div { | |
| height: 20px; | |
| width: 19px; | |
| } | |
| button:focus { | |
| outline: none; | |
| } | |
| #userzone { | |
| position: fixed; | |
| background: #00a8f3; | |
| border: 5px solid #2b577d; | |
| z-index: 11; | |
| top: 0; | |
| right: 0; | |
| bottom: 0; | |
| left: 0; | |
| padding: 3px; | |
| margin: 6px; | |
| color: white; | |
| } | |
| #highscore { | |
| position: fixed; | |
| background: #00a8f3; | |
| border: 5px solid #2b577d; | |
| z-index: 11; | |
| top: 0; | |
| right: 0; | |
| bottom: 0; | |
| left: 0; | |
| padding: 3px; | |
| margin: 6px; | |
| color: white; | |
| } | |
| #highscorecontent { | |
| overflow: auto; | |
| } | |
| .overlay { | |
| position: fixed; | |
| z-index: 10; | |
| top: 0; | |
| right: 0; | |
| bottom: 0; | |
| left: 0; | |
| transition: all 1s linear; | |
| } | |
| .blured { | |
| pointer-events:none; | |
| filter: blur(8px); | |
| -webkit-filter: blur(8px); | |
| } | |
| #optionspanel { | |
| height: auto; | |
| min-width: 180px; | |
| max-width: 300px; | |
| position: fixed; | |
| background: #00a8f3; | |
| border: 5px solid #2b577d; | |
| z-index: 12; | |
| top: 0; | |
| right: 0; | |
| left: 0; | |
| padding: 3px; | |
| margin: 40px; | |
| margin-top: 100px; | |
| color: white; | |
| } | |
| .navbar { | |
| background: #4452985e; | |
| height: 30px; | |
| padding: 5px; | |
| font-size: larger; | |
| margin-bottom: 5px; | |
| } | |
| .title { | |
| float: left; | |
| padding: 3px; | |
| } | |
| .navbtns { | |
| float: right; | |
| } | |
| #logo { | |
| color: #3f48cc; | |
| font-size: inherit; | |
| /* margin: 5px; */ | |
| padding-top: 8px; | |
| text-align: center; | |
| max-width: 400px; | |
| } | |
| .fullcenter { | |
| width: 100%; | |
| height: 100%; | |
| text-align: center; | |
| } | |
| .fullcenter img { | |
| width: 30%; | |
| margin: 0; | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| } | |
| #scorelist { | |
| font-family: Arial, Helvetica, sans-serif; | |
| width: 100%; | |
| } | |
| #scorelist td, #scorelist th { | |
| border: 1px solid #ddd; | |
| padding: 8px; | |
| } | |
| #scorelist td { | |
| max-width: 100px; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| white-space: nowrap; | |
| } | |
| #scorelist tr:nth-child(even){background-color: #0e81bb;} | |
| #scorelist tr:nth-child(2n+1){background-color: #646f9f;} | |
| #scorelist tr:hover {background-color: red;} | |
| #scorelist th { | |
| padding-top: 12px; | |
| padding-bottom: 12px; | |
| text-align: left; | |
| background-color: #4452985e; | |
| color: white; | |
| } | |
| #userzone input { | |
| width: -webkit-fill-available; | |
| width: -moz-available; | |
| background: #123fe31f; | |
| padding: 0.5rem; | |
| border: none; | |
| } | |
| #userpanel { | |
| display: flex; | |
| } | |
| #userprofilepicture{ | |
| width: 50%; | |
| padding-right: 0.5rem; | |
| } | |
| #userprofilepicture img { | |
| box-shadow: 4px 6px 7px 0px #0000ff47; | |
| width: 100%; | |
| max-width: 35rem; | |
| } | |
| ::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */ | |
| color: var(--placeholder-color); | |
| opacity: 1; /* Firefox */ | |
| } | |
| :-ms-input-placeholder { /* Internet Explorer 10-11 */ | |
| color: var(--placeholder-color); | |
| } | |
| ::-ms-input-placeholder { /* Microsoft Edge */ | |
| color: var(--placeholder-color); | |
| } | |
| .smallfont { | |
| font-size: 0.6rem; | |
| } | |
| .mt-05rem { | |
| margin-top: 0.5rem; | |
| } | |
| fieldset { | |
| margin-bottom: 1rem; | |
| background-color: #00008017; | |
| border: none; | |
| } | |
| hr { | |
| height: 12px; | |
| border: 0; | |
| box-shadow: inset 0 6px 12px -12px rgba(0, 0, 0, 0.5); | |
| } | |
| .flexcolumn { | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| .hidden { | |
| display: none; | |
| } | |
| .height0{ | |
| height: 0px; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment