Skip to content

Commit 5c1a045

Browse files
Daniel-Hugsindresorhus
authored andcommitted
Close tastejsGH-862: Vanilla js improvements.
1 parent 67b8062 commit 5c1a045

File tree

3 files changed

+105
-122
lines changed

3 files changed

+105
-122
lines changed

vanilla-examples/vanillajs/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ <h1>todos</h1>
2020
<span id="todo-count"></span>
2121
<ul id="filters">
2222
<li>
23-
<a href="#/">All</a>
23+
<a href="#/" class="selected">All</a>
2424
</li>
2525
<li>
2626
<a href="#/active">Active</a>

vanilla-examples/vanillajs/js/helpers.js

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22
(function (window) {
33
'use strict';
44

5-
// Cache the querySelector/All for easier and faster reuse
6-
window.$ = document.querySelectorAll.bind(document);
7-
window.$$ = document.querySelector.bind(document);
5+
// Get element(s) by CSS selector:
6+
window.qs = function (selector, scope) {
7+
return (scope || document).querySelector(selector);
8+
};
9+
window.qsa = function (selector, scope) {
10+
return (scope || document).querySelectorAll(selector);
11+
};
812

913
// Register events on elements that may or may not exist yet:
1014
// $live('div a', 'click', function (event) {});
@@ -15,11 +19,11 @@
1519
var targetElement = event.target;
1620

1721
eventRegistry[event.type].forEach(function (entry) {
18-
var potentialElements = document.querySelectorAll(entry.selector);
22+
var potentialElements = window.qsa(entry.selector);
1923
var hasMatch = Array.prototype.indexOf.call(potentialElements, targetElement) >= 0;
2024

2125
if (hasMatch) {
22-
entry.handler(event);
26+
entry.handler.call(targetElement, event);
2327
}
2428
});
2529
}
@@ -38,7 +42,7 @@
3842
}());
3943

4044
// Find the element's parent with the given tag name:
41-
// $parent($$('a'), 'div');
45+
// $parent(qs('a'), 'div');
4246
window.$parent = function (element, tagName) {
4347
if (!element.parentNode) {
4448
return;
@@ -50,6 +54,6 @@
5054
};
5155

5256
// Allow for looping on nodes by chaining:
53-
// $('.foo').forEach(function () {})
57+
// qsa('.foo').forEach(function () {})
5458
NodeList.prototype.forEach = Array.prototype.forEach;
5559
})(window);

vanilla-examples/vanillajs/js/view.js

Lines changed: 93 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*global $, $$, $parent, $live */
1+
/*global qs, qsa, $parent, $live */
22

33
(function (window) {
44
'use strict';
@@ -18,17 +18,17 @@
1818
this.ENTER_KEY = 13;
1919
this.ESCAPE_KEY = 27;
2020

21-
this.$todoList = $$('#todo-list');
22-
this.$todoItemCounter = $$('#todo-count');
23-
this.$clearCompleted = $$('#clear-completed');
24-
this.$main = $$('#main');
25-
this.$footer = $$('#footer');
26-
this.$toggleAll = $$('#toggle-all');
27-
this.$newTodo = $$('#new-todo');
21+
this.$todoList = qs('#todo-list');
22+
this.$todoItemCounter = qs('#todo-count');
23+
this.$clearCompleted = qs('#clear-completed');
24+
this.$main = qs('#main');
25+
this.$footer = qs('#footer');
26+
this.$toggleAll = qs('#toggle-all');
27+
this.$newTodo = qs('#new-todo');
2828
}
2929

3030
View.prototype._removeItem = function (id) {
31-
var elem = $$('[data-id="' + id + '"]');
31+
var elem = qs('[data-id="' + id + '"]');
3232

3333
if (elem) {
3434
this.$todoList.removeChild(elem);
@@ -41,19 +41,12 @@
4141
};
4242

4343
View.prototype._setFilter = function (currentPage) {
44-
// Remove all other selected states. We loop through all of them in case the
45-
// UI gets in a funky state with two selected.
46-
$('#filters .selected').forEach(function (item) {
47-
item.className = '';
48-
});
49-
50-
$('#filters [href="#/' + currentPage + '"]').forEach(function (item) {
51-
item.className = 'selected';
52-
});
44+
qs('#filters .selected').className = '';
45+
qs('#filters [href="#/' + currentPage + '"]').className = 'selected';
5346
};
5447

5548
View.prototype._elementComplete = function (id, completed) {
56-
var listItem = $$('[data-id="' + id + '"]');
49+
var listItem = qs('[data-id="' + id + '"]');
5750

5851
if (!listItem) {
5952
return;
@@ -62,11 +55,11 @@
6255
listItem.className = completed ? 'completed' : '';
6356

6457
// In case it was toggled from an event and not by clicking the checkbox
65-
listItem.querySelector('input').checked = completed;
58+
qs('input', listItem).checked = completed;
6659
};
6760

6861
View.prototype._editItem = function (id, title) {
69-
var listItem = $$('[data-id="' + id + '"]');
62+
var listItem = qs('[data-id="' + id + '"]');
7063

7164
if (!listItem) {
7265
return;
@@ -83,154 +76,140 @@
8376
};
8477

8578
View.prototype._editItemDone = function (id, title) {
86-
var listItem = $$('[data-id="' + id + '"]');
79+
var listItem = qs('[data-id="' + id + '"]');
8780

8881
if (!listItem) {
8982
return;
9083
}
9184

92-
var input = listItem.querySelector('input.edit');
85+
var input = qs('input.edit', listItem);
9386
listItem.removeChild(input);
9487

9588
listItem.className = listItem.className.replace('editing', '');
9689

97-
listItem.querySelectorAll('label').forEach(function (label) {
90+
qsa('label', listItem).forEach(function (label) {
9891
label.textContent = title;
9992
});
10093
};
10194

10295
View.prototype.render = function (viewCmd, parameter) {
10396
var that = this;
10497
var viewCommands = {
105-
showEntries: function () {
106-
that.$todoList.innerHTML = that.template.show(parameter);
107-
},
108-
removeItem: function () {
109-
that._removeItem(parameter);
110-
},
111-
updateElementCount: function () {
112-
that.$todoItemCounter.innerHTML = that.template.itemCounter(parameter);
113-
},
114-
clearCompletedButton: function () {
115-
that._clearCompletedButton(parameter.completed, parameter.visible);
116-
},
117-
contentBlockVisibility: function () {
118-
that.$main.style.display = that.$footer.style.display = parameter.visible ? 'block' : 'none';
119-
},
120-
toggleAll: function () {
121-
that.$toggleAll.checked = parameter.checked;
122-
},
123-
setFilter: function () {
124-
that._setFilter(parameter);
125-
},
126-
clearNewTodo: function () {
127-
that.$newTodo.value = '';
128-
},
129-
elementComplete: function () {
130-
that._elementComplete(parameter.id, parameter.completed);
131-
},
132-
editItem: function () {
133-
that._editItem(parameter.id, parameter.title);
134-
},
135-
editItemDone: function () {
136-
that._editItemDone(parameter.id, parameter.title);
137-
}
138-
};
98+
showEntries: function () {
99+
that.$todoList.innerHTML = that.template.show(parameter);
100+
},
101+
removeItem: function () {
102+
that._removeItem(parameter);
103+
},
104+
updateElementCount: function () {
105+
that.$todoItemCounter.innerHTML = that.template.itemCounter(parameter);
106+
},
107+
clearCompletedButton: function () {
108+
that._clearCompletedButton(parameter.completed, parameter.visible);
109+
},
110+
contentBlockVisibility: function () {
111+
that.$main.style.display = that.$footer.style.display = parameter.visible ? 'block' : 'none';
112+
},
113+
toggleAll: function () {
114+
that.$toggleAll.checked = parameter.checked;
115+
},
116+
setFilter: function () {
117+
that._setFilter(parameter);
118+
},
119+
clearNewTodo: function () {
120+
that.$newTodo.value = '';
121+
},
122+
elementComplete: function () {
123+
that._elementComplete(parameter.id, parameter.completed);
124+
},
125+
editItem: function () {
126+
that._editItem(parameter.id, parameter.title);
127+
},
128+
editItemDone: function () {
129+
that._editItemDone(parameter.id, parameter.title);
130+
}
131+
};
139132

140133
viewCommands[viewCmd]();
141134
};
142135

143-
View.prototype._itemIdForEvent = function (e) {
144-
var element = e.target;
136+
View.prototype._itemId = function (element) {
145137
var li = $parent(element, 'li');
146-
var id = li.dataset.id;
147-
148-
return id;
138+
return li.dataset.id;
149139
};
150140

151141
View.prototype._bindItemEditDone = function (handler) {
152-
$live('#todo-list li .edit', 'blur', function (e) {
153-
var input = e.target;
154-
var id = this._itemIdForEvent(e);
155-
156-
if (!input.dataset.iscanceled) {
142+
var that = this;
143+
$live('#todo-list li .edit', 'blur', function () {
144+
if (!this.dataset.iscanceled) {
157145
handler({
158-
id: id,
159-
title: input.value
146+
id: that._itemId(this),
147+
title: this.value
160148
});
161149
}
162-
}.bind(this));
150+
});
163151

164-
$live('#todo-list li .edit', 'keypress', function (e) {
165-
var input = e.target;
166-
if (e.keyCode === this.ENTER_KEY) {
152+
$live('#todo-list li .edit', 'keypress', function (event) {
153+
if (event.keyCode === that.ENTER_KEY) {
167154
// Remove the cursor from the input when you hit enter just like if it
168155
// were a real form
169-
input.blur();
156+
this.blur();
170157
}
171-
}.bind(this));
158+
});
172159
};
173160

174161
View.prototype._bindItemEditCancel = function (handler) {
175-
$live('#todo-list li .edit', 'keyup', function (e) {
176-
var input = e.target;
177-
var id = this._itemIdForEvent(e);
178-
179-
if (e.keyCode === this.ESCAPE_KEY) {
180-
181-
input.dataset.iscanceled = true;
182-
input.blur();
162+
var that = this;
163+
$live('#todo-list li .edit', 'keyup', function (event) {
164+
if (event.keyCode === that.ESCAPE_KEY) {
165+
this.dataset.iscanceled = true;
166+
this.blur();
183167

184-
handler({id: id});
168+
handler({id: that._itemId(this)});
185169
}
186-
}.bind(this));
170+
});
187171
};
188172

189173
View.prototype.bind = function (event, handler) {
174+
var that = this;
190175
if (event === 'newTodo') {
191-
this.$newTodo.addEventListener('change', function () {
192-
handler(this.$newTodo.value);
193-
}.bind(this));
176+
that.$newTodo.addEventListener('change', function () {
177+
handler(that.$newTodo.value);
178+
});
194179

195180
} else if (event === 'removeCompleted') {
196-
this.$clearCompleted.addEventListener('click', function () {
181+
that.$clearCompleted.addEventListener('click', function () {
197182
handler();
198-
}.bind(this));
183+
});
199184

200185
} else if (event === 'toggleAll') {
201-
this.$toggleAll.addEventListener('click', function (e) {
202-
var input = e.target;
203-
204-
handler({completed: input.checked});
205-
}.bind(this));
186+
that.$toggleAll.addEventListener('click', function () {
187+
handler({completed: this.checked});
188+
});
206189

207190
} else if (event === 'itemEdit') {
208-
$live('#todo-list li label', 'dblclick', function (e) {
209-
var id = this._itemIdForEvent(e);
210-
211-
handler({id: id});
212-
}.bind(this));
191+
$live('#todo-list li label', 'dblclick', function () {
192+
handler({id: that._itemId(this)});
193+
});
213194

214195
} else if (event === 'itemRemove') {
215-
$live('#todo-list .destroy', 'click', function (e) {
216-
var id = this._itemIdForEvent(e);
217-
218-
handler({id: id});
219-
}.bind(this));
196+
$live('#todo-list .destroy', 'click', function () {
197+
handler({id: that._itemId(this)});
198+
});
220199

221200
} else if (event === 'itemToggle') {
222-
$live('#todo-list .toggle', 'click', function (e) {
223-
var input = e.target;
224-
var id = this._itemIdForEvent(e);
225-
226-
handler({id: id, completed: input.checked});
227-
}.bind(this));
201+
$live('#todo-list .toggle', 'click', function () {
202+
handler({
203+
id: that._itemId(this),
204+
completed: this.checked
205+
});
206+
});
228207

229208
} else if (event === 'itemEditDone') {
230-
this._bindItemEditDone(handler);
209+
that._bindItemEditDone(handler);
231210

232211
} else if (event === 'itemEditCancel') {
233-
this._bindItemEditCancel(handler);
212+
that._bindItemEditCancel(handler);
234213
}
235214
};
236215

0 commit comments

Comments
 (0)