Skip to content

Instantly share code, notes, and snippets.

@Mazyod
Last active October 19, 2025 06:22
Show Gist options
  • Select an option

  • Save Mazyod/f40ab3859772f27beb6ea2b319e0e530 to your computer and use it in GitHub Desktop.

Select an option

Save Mazyod/f40ab3859772f27beb6ea2b319e0e530 to your computer and use it in GitHub Desktop.
TODO HTA App
<!DOCTYPE html>
<HTML>
<HEAD>
<HTA:APPLICATION
ID="TodoApp"
APPLICATIONNAME="Work TODO Manager"
BORDER="dialog"
BORDERSTYLE="normal"
CAPTION="yes"
ICON=""
MAXIMIZEBUTTON="yes"
MINIMIZEBUTTON="yes"
SHOWINTASKBAR="yes"
SINGLEINSTANCE="yes"
SYSMENU="yes"
WINDOWSTATE="normal"
/>
<meta http-equiv="x-ua-compatible" content="ie=9" />
<TITLE>Work TODO Manager</TITLE>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #667eea;
padding: 20px;
min-height: 100vh;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
border-radius: 12px;
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
overflow: hidden;
}
.header {
background: #667eea;
color: white;
padding: 30px;
text-align: center;
}
.header h1 {
font-size: 28px;
margin-bottom: 5px;
}
.header p {
opacity: 0.9;
font-size: 14px;
}
.input-section {
padding: 25px;
background: #f8f9fa;
border-bottom: 1px solid #dee2e6;
}
.input-group {
margin-bottom: 15px;
}
#todoInput {
width: 70%;
padding: 12px 15px;
border: 2px solid #dee2e6;
border-radius: 6px;
font-size: 14px;
}
#todoInput:focus {
outline: none;
border-color: #667eea;
}
.btn {
padding: 12px 24px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
font-weight: 600;
margin-left: 10px;
}
.btn-primary {
background: #667eea;
color: white;
}
.btn-primary:hover {
background: #5568d3;
}
.btn-secondary {
background: #6c757d;
color: white;
}
.btn-secondary:hover {
background: #5a6268;
}
.btn-danger {
background: #dc3545;
color: white;
padding: 6px 12px;
font-size: 12px;
}
.btn-danger:hover {
background: #c82333;
}
.priority-group {
margin-top: 10px;
}
.priority-group label {
font-size: 13px;
color: #495057;
font-weight: 600;
margin-right: 10px;
}
.priority-btn {
padding: 8px 16px;
border: 2px solid #dee2e6;
background: white;
border-radius: 6px;
cursor: pointer;
font-size: 12px;
margin-right: 5px;
}
.priority-btn.active {
border-color: #667eea;
background: #667eea;
color: white;
}
.filters {
padding: 15px 25px;
background: white;
border-bottom: 1px solid #dee2e6;
}
.filter-btn {
padding: 8px 16px;
border: 1px solid #dee2e6;
background: white;
border-radius: 20px;
cursor: pointer;
font-size: 13px;
margin-right: 5px;
}
.filter-btn.active {
background: #667eea;
color: white;
border-color: #667eea;
}
.stats {
padding: 15px 25px;
background: #f8f9fa;
font-size: 13px;
color: #6c757d;
}
.todo-list {
padding: 0;
max-height: 500px;
overflow-y: auto;
}
.todo-item {
padding: 18px 25px;
border-bottom: 1px solid #dee2e6;
}
.todo-item:hover {
background: #f8f9fa;
}
.todo-item.completed {
opacity: 0.6;
}
.todo-checkbox {
width: 20px;
height: 20px;
cursor: pointer;
vertical-align: middle;
margin-right: 15px;
}
.todo-text {
font-size: 15px;
color: #212529;
display: inline;
}
.todo-item.completed .todo-text {
text-decoration: line-through;
color: #6c757d;
}
.todo-meta {
font-size: 12px;
color: #6c757d;
margin-top: 5px;
}
.priority-badge {
display: inline-block;
padding: 3px 10px;
border-radius: 12px;
font-size: 11px;
font-weight: 600;
margin-right: 8px;
}
.priority-high {
background: #ffe5e5;
color: #dc3545;
}
.priority-medium {
background: #fff3cd;
color: #856404;
}
.priority-low {
background: #d1ecf1;
color: #0c5460;
}
.empty-state {
padding: 60px 25px;
text-align: center;
color: #6c757d;
}
.delete-btn-container {
float: right;
}
</style>
</HEAD>
<BODY>
<div class="container">
<div class="header">
<h1>Work TODO Manager</h1>
<p>Stay organized and productive</p>
</div>
<div class="input-section">
<div class="input-group">
<input type="text" id="todoInput" placeholder="What needs to be done?" />
<button class="btn btn-primary" onclick="addTodo()">Add Task</button>
</div>
<div class="priority-group">
<label>Priority:</label>
<button class="priority-btn" data-priority="low" onclick="setPriority('low')">Low</button>
<button class="priority-btn active" data-priority="medium" onclick="setPriority('medium')">Medium</button>
<button class="priority-btn" data-priority="high" onclick="setPriority('high')">High</button>
</div>
</div>
<div class="filters">
<button class="filter-btn active" onclick="filterTodos('all')">All</button>
<button class="filter-btn" onclick="filterTodos('active')">Active</button>
<button class="filter-btn" onclick="filterTodos('completed')">Completed</button>
<button class="filter-btn" onclick="filterTodos('high')">High Priority</button>
<button class="btn btn-secondary" onclick="clearCompleted()">Clear Completed</button>
</div>
<div class="stats">
<span id="stats"></span>
</div>
<div class="todo-list" id="todoList">
<div class="empty-state">
<p>No tasks yet. Add one above to get started!</p>
</div>
</div>
</div>
<script type="text/javascript">
var todos = [];
var currentPriority = 'medium';
var currentFilter = 'all';
var fso = new ActiveXObject("Scripting.FileSystemObject");
var shell = new ActiveXObject("WScript.Shell");
var dataFile = shell.ExpandEnvironmentStrings("%TEMP%") + "\\WorkTodos.json";
// Load todos from file on startup
function loadTodos() {
try {
if (fso.FileExists(dataFile)) {
var file = fso.OpenTextFile(dataFile, 1);
var content = file.ReadAll();
file.Close();
if (content) {
todos = JSON.parse(content);
}
}
} catch (e) {
// File doesn't exist or error reading, start fresh
todos = [];
}
renderTodos();
}
// Save todos to file
function saveTodos() {
try {
var file = fso.CreateTextFile(dataFile, true);
file.Write(JSON.stringify(todos));
file.Close();
} catch (e) {
alert("Error saving todos: " + e.message);
}
}
// Set priority
function setPriority(priority) {
currentPriority = priority;
var buttons = document.querySelectorAll('.priority-btn');
for (var i = 0; i < buttons.length; i++) {
var btn = buttons[i];
if (btn.getAttribute('data-priority') === priority) {
btn.className = 'priority-btn active';
} else {
btn.className = 'priority-btn';
}
}
}
// Add new todo
function addTodo() {
var input = document.getElementById('todoInput');
var text = input.value;
// Trim whitespace
text = text.replace(/^\s+|\s+$/g, '');
if (text === '') {
return;
}
var todo = {
id: new Date().getTime(),
text: text,
completed: false,
priority: currentPriority,
createdAt: new Date().toISOString()
};
todos.unshift(todo);
saveTodos();
renderTodos();
input.value = '';
input.focus();
}
// Toggle todo completion
function toggleTodo(id) {
for (var i = 0; i < todos.length; i++) {
if (todos[i].id === id) {
todos[i].completed = !todos[i].completed;
break;
}
}
saveTodos();
renderTodos();
}
// Delete todo
function deleteTodo(id) {
var newTodos = [];
for (var i = 0; i < todos.length; i++) {
if (todos[i].id !== id) {
newTodos.push(todos[i]);
}
}
todos = newTodos;
saveTodos();
renderTodos();
}
// Filter todos
function filterTodos(filter) {
currentFilter = filter;
var buttons = document.querySelectorAll('.filter-btn');
for (var i = 0; i < buttons.length; i++) {
buttons[i].className = 'filter-btn';
}
event.srcElement.className = 'filter-btn active';
renderTodos();
}
// Clear completed todos
function clearCompleted() {
var newTodos = [];
for (var i = 0; i < todos.length; i++) {
if (!todos[i].completed) {
newTodos.push(todos[i]);
}
}
todos = newTodos;
saveTodos();
renderTodos();
}
// Get filtered todos
function getFilteredTodos() {
var filtered = [];
for (var i = 0; i < todos.length; i++) {
var todo = todos[i];
var include = false;
if (currentFilter === 'all') {
include = true;
} else if (currentFilter === 'active') {
include = !todo.completed;
} else if (currentFilter === 'completed') {
include = todo.completed;
} else if (currentFilter === 'high') {
include = todo.priority === 'high';
}
if (include) {
filtered.push(todo);
}
}
return filtered;
}
// Render todos
function renderTodos() {
var listElement = document.getElementById('todoList');
var filtered = getFilteredTodos();
// Update stats
var total = todos.length;
var active = 0;
var completed = 0;
for (var i = 0; i < todos.length; i++) {
if (todos[i].completed) {
completed++;
} else {
active++;
}
}
var statsText = total + ' task' + (total !== 1 ? 's' : '') + ' | ' +
active + ' active | ' +
completed + ' completed';
document.getElementById('stats').innerHTML = statsText;
if (filtered.length === 0) {
var emptyMsg = todos.length === 0 ?
'No tasks yet. Add one above to get started!' :
'No tasks match this filter.';
listElement.innerHTML = '<div class="empty-state"><p>' + emptyMsg + '</p></div>';
return;
}
var html = '';
for (var i = 0; i < filtered.length; i++) {
var todo = filtered[i];
var date = new Date(todo.createdAt);
var dateStr = date.toLocaleDateString() + ' ' +
date.getHours() + ':' +
(date.getMinutes() < 10 ? '0' : '') + date.getMinutes();
var completedClass = todo.completed ? ' completed' : '';
var checked = todo.completed ? ' checked' : '';
html += '<div class="todo-item' + completedClass + '">';
html += '<input type="checkbox" class="todo-checkbox"' + checked + ' onchange="toggleTodo(' + todo.id + ')" />';
html += '<div style="display:inline-block; width: 70%;">';
html += '<div class="todo-text">' + escapeHtml(todo.text) + '</div>';
html += '<div class="todo-meta">';
html += '<span class="priority-badge priority-' + todo.priority + '">' + todo.priority.toUpperCase() + '</span>';
html += '<span>' + dateStr + '</span>';
html += '</div>';
html += '</div>';
html += '<div class="delete-btn-container">';
html += '<button class="btn btn-danger" onclick="deleteTodo(' + todo.id + ')">Delete</button>';
html += '</div>';
html += '<div style="clear:both;"></div>';
html += '</div>';
}
listElement.innerHTML = html;
}
// Escape HTML to prevent issues
function escapeHtml(text) {
var div = document.createElement('div');
div.appendChild(document.createTextNode(text));
return div.innerHTML;
}
// Handle Enter key in input
function setupEnterKey() {
var input = document.getElementById('todoInput');
input.onkeypress = function(e) {
e = e || window.event;
var keyCode = e.keyCode || e.which;
if (keyCode === 13) {
addTodo();
return false;
}
};
}
// Initialize on load
window.onload = function() {
window.resizeTo(850, 700);
loadTodos();
setupEnterKey();
};
</script>
</BODY>
</HTML>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment