mirror of
https://github.com/morris/vanilla-todo.git
synced 2025-08-21 05:11:20 +02:00
refactor save on blur
This commit is contained in:
@@ -33,7 +33,6 @@
|
|||||||
<script src="scripts/AppFlip.js"></script>
|
<script src="scripts/AppFlip.js"></script>
|
||||||
<script src="scripts/AppFps.js"></script>
|
<script src="scripts/AppFps.js"></script>
|
||||||
<script src="scripts/AppIcon.js"></script>
|
<script src="scripts/AppIcon.js"></script>
|
||||||
<script src="scripts/AppLateBlur.js"></script>
|
|
||||||
<script src="scripts/AppSortable.js"></script>
|
<script src="scripts/AppSortable.js"></script>
|
||||||
<script src="scripts/TodoApp.js"></script>
|
<script src="scripts/TodoApp.js"></script>
|
||||||
<script src="scripts/TodoCustomList.js"></script>
|
<script src="scripts/TodoCustomList.js"></script>
|
||||||
|
@@ -17,14 +17,8 @@ VT.AppDraggable = function (el, options) {
|
|||||||
var imageX, imageY;
|
var imageX, imageY;
|
||||||
var currentTarget;
|
var currentTarget;
|
||||||
|
|
||||||
if (window.navigator.pointerEnabled) {
|
|
||||||
el.addEventListener('pointerdown', start);
|
|
||||||
} else if (window.navigator.msPointerEnabled) {
|
|
||||||
el.addEventListener('MSPointerDown', start);
|
|
||||||
} else {
|
|
||||||
el.addEventListener('mousedown', start);
|
|
||||||
el.addEventListener('touchstart', start);
|
el.addEventListener('touchstart', start);
|
||||||
}
|
el.addEventListener('mousedown', start);
|
||||||
|
|
||||||
// maybe prevent click
|
// maybe prevent click
|
||||||
el.addEventListener(
|
el.addEventListener(
|
||||||
@@ -90,7 +84,6 @@ VT.AppDraggable = function (el, options) {
|
|||||||
|
|
||||||
function end(e) {
|
function end(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopImmediatePropagation();
|
|
||||||
|
|
||||||
if (!dragging) {
|
if (!dragging) {
|
||||||
e.target.click();
|
e.target.click();
|
||||||
@@ -110,33 +103,17 @@ VT.AppDraggable = function (el, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function startListening() {
|
function startListening() {
|
||||||
if (window.navigator.pointerEnabled) {
|
|
||||||
el.addEventListener('pointermove', move);
|
|
||||||
el.addEventListener('pointerup', end);
|
|
||||||
} else if (window.navigator.msPointerEnabled) {
|
|
||||||
el.addEventListener('MSPointerMove', move);
|
|
||||||
el.addEventListener('MSPointerUp', end);
|
|
||||||
} else {
|
|
||||||
window.addEventListener('mousemove', move);
|
|
||||||
window.addEventListener('mouseup', end);
|
|
||||||
el.addEventListener('touchmove', move);
|
el.addEventListener('touchmove', move);
|
||||||
el.addEventListener('touchend', end);
|
el.addEventListener('touchend', end);
|
||||||
}
|
window.addEventListener('mousemove', move);
|
||||||
|
window.addEventListener('mouseup', end);
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopListening() {
|
function stopListening() {
|
||||||
if (window.navigator.pointerEnabled) {
|
|
||||||
el.removeEventListener('pointermove', move);
|
|
||||||
el.removeEventListener('pointerup', end);
|
|
||||||
} else if (window.navigator.msPointerEnabled) {
|
|
||||||
el.removeEventListener('MSPointerMove', move);
|
|
||||||
el.removeEventListener('MSPointerUp', end);
|
|
||||||
} else {
|
|
||||||
window.removeEventListener('mousemove', move);
|
|
||||||
window.removeEventListener('mouseup', end);
|
|
||||||
el.removeEventListener('touchmove', move);
|
el.removeEventListener('touchmove', move);
|
||||||
el.removeEventListener('touchend', end);
|
el.removeEventListener('touchend', end);
|
||||||
}
|
window.removeEventListener('mousemove', move);
|
||||||
|
window.removeEventListener('mouseup', end);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@@ -1,39 +0,0 @@
|
|||||||
/* global VT */
|
|
||||||
window.VT = window.VT || {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables `lateBlur` events on the target element.
|
|
||||||
* After an actual `blur` event, subsequent interactions with the window
|
|
||||||
* (e.g. focus, select, mouseup etc.) will dispatch a `lateBlur` event.
|
|
||||||
*/
|
|
||||||
VT.AppLateBlur = function (el) {
|
|
||||||
el.addEventListener('blur', function () {
|
|
||||||
window.addEventListener('focus', dispatch);
|
|
||||||
window.addEventListener('select', dispatch);
|
|
||||||
|
|
||||||
if (window.navigator.pointerEnabled) {
|
|
||||||
window.addEventListener('pointerup', dispatch);
|
|
||||||
} else if (window.navigator.msPointerEnabled) {
|
|
||||||
window.addEventListener('MSPointerUp', dispatch);
|
|
||||||
} else {
|
|
||||||
window.addEventListener('mouseup', dispatch);
|
|
||||||
window.addEventListener('touchend', dispatch);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function dispatch() {
|
|
||||||
window.removeEventListener('focus', dispatch);
|
|
||||||
window.removeEventListener('select', dispatch);
|
|
||||||
|
|
||||||
if (window.navigator.pointerEnabled) {
|
|
||||||
window.removeEventListener('pointerup', dispatch);
|
|
||||||
} else if (window.navigator.msPointerEnabled) {
|
|
||||||
window.removeEventListener('MSPointerUp', dispatch);
|
|
||||||
} else {
|
|
||||||
window.removeEventListener('mouseup', dispatch);
|
|
||||||
window.removeEventListener('touchend', dispatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
el.dispatchEvent(new CustomEvent('lateBlur', { bubbles: true }));
|
|
||||||
}
|
|
||||||
};
|
|
@@ -6,7 +6,8 @@ VT.TodoCustomList = function (el) {
|
|||||||
list: null,
|
list: null,
|
||||||
editing: false,
|
editing: false,
|
||||||
};
|
};
|
||||||
var focus = false;
|
var startEditing = false;
|
||||||
|
var saveOnBlur = true;
|
||||||
|
|
||||||
el.innerHTML = [
|
el.innerHTML = [
|
||||||
'<div class="header">',
|
'<div class="header">',
|
||||||
@@ -26,31 +27,35 @@ VT.TodoCustomList = function (el) {
|
|||||||
VT.AppDraggable(titleEl, {
|
VT.AppDraggable(titleEl, {
|
||||||
dropSelector: '.todo-frame.-custom .container',
|
dropSelector: '.todo-frame.-custom .container',
|
||||||
});
|
});
|
||||||
VT.AppLateBlur(inputEl);
|
|
||||||
VT.TodoList(el.querySelector('.todo-list'));
|
VT.TodoList(el.querySelector('.todo-list'));
|
||||||
el.querySelectorAll('.app-icon').forEach(VT.AppIcon);
|
el.querySelectorAll('.app-icon').forEach(VT.AppIcon);
|
||||||
|
|
||||||
titleEl.addEventListener('click', function () {
|
titleEl.addEventListener('click', function () {
|
||||||
focus = true;
|
startEditing = true;
|
||||||
update({ editing: true });
|
update({ editing: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
inputEl.addEventListener('input', function () {
|
deleteEl.addEventListener('touchstart', function () {
|
||||||
el.dispatchEvent(
|
saveOnBlur = false;
|
||||||
new CustomEvent('saveList', {
|
|
||||||
detail: { list: state.list, title: inputEl.value.trim() },
|
|
||||||
bubbles: true,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
inputEl.addEventListener('lateBlur', function () {
|
deleteEl.addEventListener('mousedown', function () {
|
||||||
update({ editing: false });
|
saveOnBlur = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
inputEl.addEventListener('keypress', function (e) {
|
inputEl.addEventListener('blur', function () {
|
||||||
if (e.keyCode === 13) {
|
if (saveOnBlur) save();
|
||||||
update({ editing: false });
|
saveOnBlur = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
inputEl.addEventListener('keyup', function (e) {
|
||||||
|
switch (e.keyCode) {
|
||||||
|
case 13: // enter
|
||||||
|
save();
|
||||||
|
break;
|
||||||
|
case 27: // escape
|
||||||
|
cancelEdit();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -103,11 +108,26 @@ VT.TodoCustomList = function (el) {
|
|||||||
update: update,
|
update: update,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
el.dispatchEvent(
|
||||||
|
new CustomEvent('saveList', {
|
||||||
|
detail: { list: state.list, title: inputEl.value.trim() },
|
||||||
|
bubbles: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
update({ editing: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelEdit() {
|
||||||
|
saveOnBlur = false;
|
||||||
|
update({ editing: false });
|
||||||
|
}
|
||||||
|
|
||||||
function update(next) {
|
function update(next) {
|
||||||
Object.assign(state, next);
|
Object.assign(state, next);
|
||||||
|
|
||||||
titleEl.innerText = state.list.title || '...';
|
titleEl.innerText = state.list.title || '...';
|
||||||
inputEl.value = state.list.title;
|
|
||||||
el.querySelector('.todo-list').todoList.update({ items: state.list.items });
|
el.querySelector('.todo-list').todoList.update({ items: state.list.items });
|
||||||
el.querySelector('.todo-list > .todo-item-input').setAttribute(
|
el.querySelector('.todo-list > .todo-item-input').setAttribute(
|
||||||
'data-key',
|
'data-key',
|
||||||
@@ -116,10 +136,11 @@ VT.TodoCustomList = function (el) {
|
|||||||
|
|
||||||
el.classList.toggle('-editing', state.editing);
|
el.classList.toggle('-editing', state.editing);
|
||||||
|
|
||||||
if (state.editing && focus) {
|
if (state.editing && startEditing) {
|
||||||
|
inputEl.value = state.list.title;
|
||||||
inputEl.focus();
|
inputEl.focus();
|
||||||
inputEl.select();
|
inputEl.select();
|
||||||
focus = false;
|
startEditing = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -6,7 +6,8 @@ VT.TodoItem = function (el) {
|
|||||||
item: null,
|
item: null,
|
||||||
editing: false,
|
editing: false,
|
||||||
};
|
};
|
||||||
var focus = false;
|
var startEditing = false;
|
||||||
|
var saveOnBlur = true;
|
||||||
|
|
||||||
el.innerHTML = [
|
el.innerHTML = [
|
||||||
'<div class="checkbox">',
|
'<div class="checkbox">',
|
||||||
@@ -19,17 +20,28 @@ VT.TodoItem = function (el) {
|
|||||||
'</p>',
|
'</p>',
|
||||||
].join('\n');
|
].join('\n');
|
||||||
|
|
||||||
var inputEl = el.querySelector('.input');
|
var checkboxEl = el.querySelector('.checkbox');
|
||||||
var labelEl = el.querySelector('.label');
|
var labelEl = el.querySelector('.label');
|
||||||
|
var inputEl = el.querySelector('.input');
|
||||||
|
var saveEl = el.querySelector('.save');
|
||||||
|
|
||||||
VT.AppDraggable(el, {
|
VT.AppDraggable(el, {
|
||||||
dropSelector: '.todo-list > .items',
|
dropSelector: '.todo-list > .items',
|
||||||
});
|
});
|
||||||
VT.AppLateBlur(inputEl);
|
|
||||||
|
|
||||||
el.querySelectorAll('.app-icon').forEach(VT.AppIcon);
|
el.querySelectorAll('.app-icon').forEach(VT.AppIcon);
|
||||||
|
|
||||||
el.querySelector('.checkbox').addEventListener('click', function () {
|
checkboxEl.addEventListener('touchstart', function () {
|
||||||
|
saveOnBlur = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
checkboxEl.addEventListener('mousedown', function () {
|
||||||
|
saveOnBlur = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
checkboxEl.addEventListener('click', function () {
|
||||||
|
if (state.editing) save();
|
||||||
|
|
||||||
el.dispatchEvent(
|
el.dispatchEvent(
|
||||||
new CustomEvent('checkItem', {
|
new CustomEvent('checkItem', {
|
||||||
detail: {
|
detail: {
|
||||||
@@ -42,23 +54,32 @@ VT.TodoItem = function (el) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
labelEl.addEventListener('click', function () {
|
labelEl.addEventListener('click', function () {
|
||||||
focus = true;
|
startEditing = true;
|
||||||
update({ editing: true });
|
update({ editing: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
el.querySelector('.save').addEventListener('click', function () {
|
inputEl.addEventListener('keyup', function (e) {
|
||||||
|
switch (e.keyCode) {
|
||||||
|
case 13: // enter
|
||||||
save();
|
save();
|
||||||
|
break;
|
||||||
|
case 27: // escape
|
||||||
|
cancelEdit();
|
||||||
|
break;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
inputEl.addEventListener('keypress', function (e) {
|
inputEl.addEventListener('blur', function () {
|
||||||
if (e.keyCode === 13) save();
|
if (saveOnBlur) save();
|
||||||
|
saveOnBlur = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
inputEl.addEventListener('lateBlur', function () {
|
saveEl.addEventListener('mousedown', function () {
|
||||||
save();
|
saveOnBlur = false;
|
||||||
update({ editing: false });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
saveEl.addEventListener('click', save);
|
||||||
|
|
||||||
el.addEventListener('draggableStart', function (e) {
|
el.addEventListener('draggableStart', function (e) {
|
||||||
e.detail.data.item = state.item;
|
e.detail.data.item = state.item;
|
||||||
e.detail.data.key = state.item.id;
|
e.detail.data.key = state.item.id;
|
||||||
@@ -95,21 +116,27 @@ VT.TodoItem = function (el) {
|
|||||||
update({ editing: false });
|
update({ editing: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cancelEdit() {
|
||||||
|
saveOnBlur = false;
|
||||||
|
update({ editing: false });
|
||||||
|
}
|
||||||
|
|
||||||
function update(next) {
|
function update(next) {
|
||||||
// TODO optimize
|
// TODO optimize
|
||||||
Object.assign(state, next);
|
Object.assign(state, next);
|
||||||
|
|
||||||
el.classList.toggle('-done', state.item.done);
|
el.classList.toggle('-done', state.item.done);
|
||||||
el.querySelector('.checkbox > input').checked = state.item.done;
|
checkboxEl.querySelector('input').checked = state.item.done;
|
||||||
labelEl.innerText = state.item.label;
|
labelEl.innerText = state.item.label;
|
||||||
inputEl.value = state.item.label;
|
|
||||||
el.classList.toggle('-editing', state.editing);
|
el.classList.toggle('-editing', state.editing);
|
||||||
el.classList.toggle('_nodrag', state.editing);
|
el.classList.toggle('_nodrag', state.editing);
|
||||||
|
|
||||||
if (state.editing && focus) {
|
if (state.editing && startEditing) {
|
||||||
el.querySelector('.input').focus();
|
inputEl.value = state.item.label;
|
||||||
el.querySelector('.input').select();
|
inputEl.focus();
|
||||||
focus = false;
|
inputEl.select();
|
||||||
|
startEditing = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -2,6 +2,8 @@
|
|||||||
window.VT = window.VT || {};
|
window.VT = window.VT || {};
|
||||||
|
|
||||||
VT.TodoItemInput = function (el) {
|
VT.TodoItemInput = function (el) {
|
||||||
|
var saveOnBlur = true;
|
||||||
|
|
||||||
el.innerHTML = [
|
el.innerHTML = [
|
||||||
'<input class="input" type="text">',
|
'<input class="input" type="text">',
|
||||||
'<button class="app-button save"><i class="app-icon" data-id="plus-24"></i></button>',
|
'<button class="app-button save"><i class="app-icon" data-id="plus-24"></i></button>',
|
||||||
@@ -10,10 +12,9 @@ VT.TodoItemInput = function (el) {
|
|||||||
var inputEl = el.querySelector('.input');
|
var inputEl = el.querySelector('.input');
|
||||||
var saveEl = el.querySelector('.save');
|
var saveEl = el.querySelector('.save');
|
||||||
|
|
||||||
VT.AppLateBlur(inputEl);
|
|
||||||
el.querySelectorAll('.app-icon').forEach(VT.AppIcon);
|
el.querySelectorAll('.app-icon').forEach(VT.AppIcon);
|
||||||
|
|
||||||
inputEl.addEventListener('keypress', function (e) {
|
inputEl.addEventListener('keyup', function (e) {
|
||||||
switch (e.keyCode) {
|
switch (e.keyCode) {
|
||||||
case 13: // enter
|
case 13: // enter
|
||||||
save();
|
save();
|
||||||
@@ -24,7 +25,14 @@ VT.TodoItemInput = function (el) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
inputEl.addEventListener('lateBlur', save);
|
inputEl.addEventListener('blur', function () {
|
||||||
|
if (saveOnBlur) save();
|
||||||
|
saveOnBlur = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
saveEl.addEventListener('mousedown', function () {
|
||||||
|
saveOnBlur = false;
|
||||||
|
});
|
||||||
|
|
||||||
saveEl.addEventListener('click', function () {
|
saveEl.addEventListener('click', function () {
|
||||||
save();
|
save();
|
||||||
|
@@ -53,6 +53,7 @@
|
|||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
line-height: 1.5em;
|
line-height: 1.5em;
|
||||||
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.todo-item > .form > .save {
|
.todo-item > .form > .save {
|
||||||
|
Reference in New Issue
Block a user