PageSourceSearch

https://www.alinma.com/-/media/Themes/AlinmaNew/Portal/AlinmaNew/Scripts/puzzle-game.js

js alinma.com collected 2026-09-24 10:08:35 UTC 4,387 bytes, 139 lines download raw bytes

1const gameContainer = document.getElementById('gameContainer');
2const startButton = document.getElementById('startButton');
3const playAgainButton = document.getElementById('playAgainButton');
4const timerDisplay = document.getElementById('timer');
5const defaultImage = document.getElementById('defaultImage');
6
7let pieces = [];
8let selectedIndex = null;
9let startTime;
10let timerInterval;
11
12const img = new Image();
13
14// --- Null check for defaultImage before accessing .src ---
15if (defaultImage && defaultImage.src) {
16    img.src = defaultImage.src;
17    img.onload = function () {
18        createPuzzle(img, false); // show solved puzzle initially
19    };
20} else {
21    console.warn('defaultImage element not found or has no src; puzzle will not initialize.');
22}
23
24// --- Safely add event listeners only if the buttons exist ---
25if (startButton) {
26    startButton.addEventListener('click', () => {
27        shuffleArray(pieces);
28        renderPuzzle();
29        startTime = new Date();
30        startButton.style.display = 'none';
31        startTimer();
32    });
33} else {
34    console.warn('startButton element not found.');
35}
36
37if (playAgainButton) {
38    playAgainButton.addEventListener('click', () => {
39        shuffleArray(pieces);
40        renderPuzzle();
41        startTime = new Date();
42        startButton.style.display = 'none';
43        startTimer();
44    });
45} else {
46    console.warn('playAgainButton element not found.');
47}
48
49function createPuzzle(img, shuffle = true) {
50    pieces = [];
51    gameContainer.innerHTML = '';
52
53    const canvas = document.createElement('canvas');
54    const ctx = canvas.getContext('2d');
55    canvas.width = 260;
56    canvas.height = 260;
57    ctx.drawImage(img, 0, 0, 260, 260);
58
59    for (let y = 0; y < 4; y++) {
60        for (let x = 0; x < 4; x++) {
61            const pieceCanvas = document.createElement('canvas');
62            pieceCanvas.width = 65;
63            pieceCanvas.height = 65;
64            const pieceCtx = pieceCanvas.getContext('2d');
65            pieceCtx.drawImage(canvas, x * 65, y * 65, 65, 65, 0, 0, 65, 65);
66            pieces.push({
67                correctIndex: y * 4 + x,
68                canvas: pieceCanvas
69            });
70        }
71    }
72
73    if (shuffle) shuffleArray(pieces);
74    renderPuzzle();
75}
76
77function renderPuzzle() {
78    gameContainer.innerHTML = '';
79    pieces.forEach((piece, index) => {
80        const div = document.createElement('div');
81        div.classList.add('piece');
82        div.appendChild(piece.canvas);
83        if (index === selectedIndex) {
84            div.classList.add('selected');
85        }
86        div.addEventListener('click', () => handlePieceClick(index));
87        gameContainer.appendChild(div);
88    });
89}
90
91function handlePieceClick(index) {
92    if (!startButton || startButton.style.display !== 'none') return; // prevent interaction before start
93    if (selectedIndex === null) {
94        selectedIndex = index;
95    } else {
96        [pieces[selectedIndex], pieces[index]] = [pieces[index], pieces[selectedIndex]];
97        selectedIndex = null;
98        renderPuzzle();
99        checkWin();
100    }
101    renderPuzzle();
102}
103
104function checkWin() {
105    const isSolved = pieces.every((piece, index) => piece.correctIndex === index);
106    if (isSolved) {
107        clearInterval(timerInterval);
108        const endTime = new Date();
109        const timeTakenSec = Math.floor((endTime - startTime) / 1000);
110        const minutes = Math.floor(timeTakenSec / 60);
111        const seconds = timeTakenSec % 60;
112        const formattedTime = `${minutes}:${seconds}`;
113
114        document.getElementById('winModalTime').textContent = `${formattedTime}`;
115
116        const winModal = new bootstrap.Modal(document.getElementById('winModal'));
117        winModal.show();
118
119        // show share button
120        document.getElementById("shareBtn").style.display = "inline-flex";
121    }
122}
123
124function startTimer() {
125    timerInterval = setInterval(() => {
126        const now = new Date();
127        const timeTakenSec = Math.floor((now - startTime) / 1000);
128        const minutes = Math.floor(timeTakenSec / 60);
129        const seconds = timeTakenSec % 60;
130        timerDisplay.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
131    }, 1000);
132}
133
134function shuffleArray(array) {
135    for (let i = array.length - 1; i > 0; i--) {
136        const j = Math.floor(Math.random() * (i + 1));
137        [array[i], array[j]] = [array[j], array[i]];
138    }
139}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.