Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 158 additions & 0 deletions .js
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
const input = document.querySelector('.text_input');
const addButton = document.querySelector('.button-add');
const productList = document.querySelector('.block');
const initialProducts = ['Apple', 'Orange', 'Cheese'];

initialProducts.forEach(name => {
productList.appendChild(createProductItem(name));
});

function createProductItem(name) {
const productItem = document.createElement('span');
productItem.className = 'product-item';
productItem.innerHTML = `
<span class="product-name">${name}</span>
<div class="amount-block">
<button value="subtract" class="minus" data-tooltip="Subtract from number of the items you have planned">−</button>
<span class="amount">1</span>
<button value="add" class="plus" data-tooltip="Add to number of the items you have planned">+</button>
</div>
<button value="Done" class="button-bought" data-tooltip="The item is already bought">Bought</button>
<button value="Delete" class="button-del" data-tooltip="Delete item from the list">×</button>
`;
attachProductHandlers(productItem);
return productItem;
}

function attachProductHandlers(productItem) {
const nameSpan = productItem.querySelector('.product-name');
const deleteButton = productItem.querySelector('.button-del');
const boughtButton = productItem.querySelector('.button-bought');
const minusButton = productItem.querySelector('.minus');
const plusButton = productItem.querySelector('.plus');
const amountSpan = productItem.querySelector('.amount');

function updateAmountSymbolState() {
const currentAmount = Number(amountSpan.textContent);
minusButton.disabled = currentAmount <= 1;
plusButton.disabled = currentAmount >= 99;
}

updateAmountSymbolState();

nameSpan.addEventListener('click', () => {
if (!productItem.classList.contains('bought')) {
editProductName(nameSpan);
}
});

deleteButton.addEventListener('click', () => {
productItem.remove();
refreshStatistics();
});

plusButton.addEventListener('click', () => {
const currentAmount = Number(amountSpan.textContent);
amountSpan.textContent = currentAmount + 1;
updateAmountSymbolState();
refreshStatistics();
});

minusButton.addEventListener('click', () => {
const currentAmount = Number(amountSpan.textContent);
if (currentAmount > 1) {
amountSpan.textContent = currentAmount - 1;
updateAmountSymbolState();
refreshStatistics();
}
});

boughtButton.addEventListener('click', () => {
productItem.classList.toggle('bought');
boughtButton.textContent = productItem.classList.contains('bought') ? 'Undo' : 'Bought';
refreshStatistics();
});
}

function refreshStatistics() {
const leftContainer = document.getElementById('stats-left');
const boughtContainer = document.getElementById('stats-bought');
leftContainer.innerHTML = '';
boughtContainer.innerHTML = '';

document.querySelectorAll('.product-item').forEach(item => {
const name = item.querySelector('.product-name').textContent.trim();
const amount = item.querySelector('.amount').textContent.trim();
const statItem = document.createElement('div');
statItem.className = 'stats-item';
statItem.innerHTML = `
<span class="stats-product-name">${name}</span>
<span class="stats-amount">${amount}</span>
`;

if (item.classList.contains('bought')) {
boughtContainer.appendChild(statItem);
} else {
leftContainer.appendChild(statItem);
}
});
}


function editProductName(nameSpan) {
const currentName = nameSpan.textContent;
const input = document.createElement('input');
input.type = 'text';
input.className = 'product-name-edit';
input.value = currentName;

nameSpan.replaceWith(input);
input.focus();
input.select();

function saveEdit() {
const newName = input.value.trim() || currentName;
const newNameSpan = document.createElement('span');
newNameSpan.className = 'product-name';
newNameSpan.textContent = newName;

input.replaceWith(newNameSpan);
newNameSpan.addEventListener('click', () => {
if (!newNameSpan.closest('.product-item').classList.contains('bought')) {
editProductName(newNameSpan);
}
});
refreshStatistics();
}

input.addEventListener('blur', saveEdit);
input.addEventListener('keydown', event => {
if (event.key === 'Enter') {
input.blur();
}
});
}

function addProduct() {
const value = input.value.trim();
if (!value) {
input.value = '';
input.focus();
return;
}

productList.appendChild(createProductItem(value));
refreshStatistics();
input.value = '';
input.focus();
}

addButton.addEventListener('click', addProduct);
input.addEventListener('keydown', event => {
if (event.key === 'Enter') {
event.preventDefault();
addProduct();
}
});

refreshStatistics();
153 changes: 153 additions & 0 deletions bonus/my.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
let testInitial = [{row:1, column:1, value:1},
{row:1, column:2, value:2},
{row:1, column:3, value:3},
{row:1, column:4, value:4},
{row:2, column:1, value:5},
{row:2, column:2, value:6},
{row:2, column:3, value:7},
{row:2, column:4, value:8},
{row:3, column:1, value:9},
{row:3, column:2, value:10},
{row:3, column:3, value:11},
{row:3, column:4, value:12},
{row:4, column:1, value:13},
{row:4, column:2, value:14},
{row:4, column:3, value:" "},
{row:4, column:4, value:15}]

const size = 4;
const totalCells = 16;

let currentGrid = generateSolvableGrid();
//let currentGrid = testInitial;

var pivot = new WebDataRocks({
container: "#wdr-component",
toolbar: false,
height: 152,
width: 502,
report: {
dataSource: {data: currentGrid},
slice: {
rows:[{uniqueName: "row"}],
columns:[{uniqueName: "column"}],
measures: [{uniqueName: "value"}]},
options: {
configuratorButton: false,
drillThrough: false,
sorting: "off",
showHeaders: false,
showGrandTotals: "none",
showTotals: "none",
showHierarchyCaptions: false
}

}
});



function handleClick(cell) {
//console.log("1. row, col " + cell.rowIndex + " " + cell.columnIndex);
const emptyCell = currentGrid.find(c => c.value === " ");
if (cell.value === " ") return;
//console.log('cell:', cell);
//console.log('emptyCell:', emptyCell);

const rows = [1,2,3,4];
const columns = [1,2,3,4];
const clickedR = rows.indexOf(cell.rowIndex)+1;
const emptyR = emptyCell.row;
const clickedC = columns.indexOf(cell.columnIndex)+1;
const emptyC = emptyCell.column;
//console.log("2. row, col " + cell.rowIndex + " " + cell.columnIndex);
const isClose = ((Math.abs(clickedR - emptyR) === 1 && clickedC === emptyC) || (Math.abs(clickedC - emptyC) === 1 && clickedR === emptyR));
//console.log(isClose, clickedR, emptyR, clickedC , emptyC, Math.abs(clickedR - emptyR))
//console.log("3. row, col " + cell.rowIndex + " " + cell.columnIndex);

if(isClose) {
//console.log("cell aaaaaa " + cell.value)
//console.log("empty aaaaaa " + emptyCell.value)
emptyCell.value = cell.value;
//console.log("empty aaaaaa " + emptyCell.value)
//console.log("cell aaaaaa " + cell.value)
let record = currentGrid.find(item => item.row === clickedR && item.column === clickedC);
if (record) {
record.value = " ";
}

//console.log("4. row, col " + cell.rowIndex + " " + cell.columnIndex);

pivot.updateData({data: currentGrid});
checkWin(currentGrid);
//console.log("empty aaaaaa " + emptyCell.value)
//console.log("5. row, col " + cell.rowIndex + " " + cell.columnIndex);
}
//console.log("6. row, col " + cell.rowIndex + " " + cell.columnIndex);

};

function checkWin(data) {
for (let cell of data) {
const index = (cell.row - 1) * size + (cell.column - 1);
const expectedValue = (index === totalCells - 1) ? " " : index + 1;
if (cell.value !== expectedValue) return false;
}
console.log("You won");
alert("You have won!");
return true;
};

pivot.on('cellclick', handleClick);



function generateRandomGrid() {
const numbers = Array.from({ length: totalCells - 1 }, (_, i) => i + 1);
numbers.push(" ");

for (let i = numbers.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[numbers[i], numbers[j]] = [numbers[j], numbers[i]];
}

const grid = [];
for (let index = 0; index < totalCells; index++) {
const row = Math.floor(index / size) + 1;
const col = (index % size) + 1;
grid.push({
row: row,
column: col,
value: numbers[index]
});
}
return grid;
}

function isSolvable(grid) {
const arr = grid.map(c => c.value).filter(val => val !== "");
let invCount = 0;

for (let i = 0; i < arr.length - 1; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arr[i] > arr[j]) invCount++;
}
}

const blankIndex = grid.findIndex(c => c.value === " ");
const blankRow = Math.floor(blankIndex / size);

if (size % 2 !== 0) {
return invCount % 2 === 0;
} else {
return (invCount + blankRow) % 2 !== 0;
}
}

function generateSolvableGrid() {
let grid;
do {
grid = generateRandomGrid();
} while (!isSolvable(grid));
return grid;
}
19 changes: 19 additions & 0 deletions bonus/page.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>15-tiles</title>

<link href="webdatarocks.min.css" rel="stylesheet"/>
<link href="webdatarocks.css" rel="stylesheet"/>
</head>
<body>
<script src="webdatarocks.toolbar.min.js"></script>
<script src="webdatarocks.js"></script>

<div id="wdr-component"></div>


<script src="my.js"></script>
</body>
</html>
32 changes: 27 additions & 5 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,16 +1,38 @@
<!DOCTYPE html>
<html>
<head lang="uk">
<head lang="en">
<meta charset="UTF-8">
<title>My Page</title>


<link rel="stylesheet" type="text/css" href="main.css" />
</head>

<body>
<span class="product-item">
Apple
<span class="amount">4</span>
</span>
<div class="block">
<div class="add-product-item">
<input type="text" class="text_input" data-tooltip="Input item you want to add">
<button value="Save" class="button-add" data-tooltip="Button to add an item">Add</button>
</div>
</div>

<div class="stats-section">
<div class="stats-group">
<div class="stats-title">To Buy</div>
<div class="stats-list" id="stats-left"></div>
</div>
<div class="stats-divider"></div>
<div class="stats-group">
<div class="stats-title">Bought</div>
<div class="stats-list" id="stats-bought"></div>
</div>
</div>

<button class="badge" data-tooltip="badge">
<b>Buy List</b>
<span class="badge-by">Created by:</span>
<span class="badge-name">Jane K.</span>
</button>
<script src=".js"></script>
</body>
</html>
Loading