10x speedup in tag selector refresh

Using createDocumentFragment() and event delegation

Filtering for a tag could still be sped up quite a lot. Resizing the tag
selector is also very laggy, but that might require switching to clusterize.js
or similar.
This commit is contained in:
Dan Stillman 2016-09-27 23:44:22 -04:00
parent ed46414502
commit 6e74110078

View File

@ -165,6 +165,41 @@
this.id('show-automatic').setAttribute('checked', this.showAutomatic); this.id('show-automatic').setAttribute('checked', this.showAutomatic);
this.id('display-all-tags').setAttribute('checked', !this.filterToScope); this.id('display-all-tags').setAttribute('checked', !this.filterToScope);
this.dragObserver = new this._dragObserverConstructor; this.dragObserver = new this._dragObserverConstructor;
//
// Event listeners
//
var tagsBox = this.id('tags-box');
tagsBox.addEventListener('click', function (event) {
this.handleTagClick(event);
}.bind(this));
tagsBox.addEventListener('mousedown', function (event) {
if (!this.editable) return;
if (event.button == 2) {
// Without the setTimeout, the popup gets immediately hidden
// for some reason
setTimeout(function () {
_popupNode = event.target;
self.id('tag-menu').openPopup(
null,
'after_pointer',
event.clientX + 2,
event.clientY + 2,
true,
event
);
event.stopPropagation();
event.preventDefault();
});
}
}.bind(this));
tagsBox.addEventListener('dragover', this.dragObserver.onDragOver);
tagsBox.addEventListener('dragexit', this.dragObserver.onDragExit);
tagsBox.addEventListener('drop', this.dragObserver.onDrop, true);
]]> ]]>
</constructor> </constructor>
@ -257,6 +292,7 @@
return collation.compareString(1, a.tag, b.tag); return collation.compareString(1, a.tag, b.tag);
}); });
var fragment = document.createDocumentFragment();
let lastTag; let lastTag;
for (let i = 0; i < this._tags.length; i++) { for (let i = 0; i < this._tags.length; i++) {
let tagData = this._tags[i]; let tagData = this._tags[i];
@ -267,7 +303,7 @@
} }
lastTag = tagData.tag; lastTag = tagData.tag;
let elem = this._insertClickableTag(tagsBox, tagData); let elem = this._insertClickableTag(fragment, tagData);
let visible = this._updateClickableTag( let visible = this._updateClickableTag(
elem, tagData.tag, tagColors elem, tagData.tag, tagColors
); );
@ -275,6 +311,7 @@
emptyRegular = false; emptyRegular = false;
} }
} }
tagsBox.appendChild(fragment);
this._dirty = false; this._dirty = false;
} }
// Otherwise just update based on visibility // Otherwise just update based on visibility
@ -614,13 +651,14 @@
<method name="handleTagClick"> <method name="handleTagClick">
<parameter name="event"/> <parameter name="event"/>
<parameter name="elem"/>
<body> <body>
<![CDATA[ <![CDATA[
if (event.button != 0) { if (event.button != 0) {
return; return;
} }
var elem = event.target;
// Ignore clicks on tags not in scope // Ignore clicks on tags not in scope
if (elem.getAttribute('inScope') == 'false') { if (elem.getAttribute('inScope') == 'false') {
return; return;
@ -642,6 +680,8 @@
if (this.onchange) { if (this.onchange) {
this.onchange(); this.onchange();
} }
event.stopPropagation();
]]> ]]>
</body> </body>
</method> </method>
@ -746,34 +786,6 @@
if (tagObj.type) { if (tagObj.type) {
elem.setAttribute('tagType', tagObj.type); elem.setAttribute('tagType', tagObj.type);
} }
var self = this;
elem.addEventListener('click', function(event) {
self.handleTagClick(event, this);
});
if (this.editable) {
elem.addEventListener('mousedown', function (event) {
if (event.button == 2) {
// Without the setTimeout, the popup gets immediately hidden
// for some reason
setTimeout(function () {
_popupNode = elem;
self.id('tag-menu').openPopup(
null,
'after_pointer',
event.clientX + 2,
event.clientY + 2,
true,
event
);
event.stopPropagation();
event.preventDefault();
});
}
}, true);
elem.addEventListener('dragover', this.dragObserver.onDragOver);
elem.addEventListener('dragexit', this.dragObserver.onDragExit);
elem.addEventListener('drop', this.dragObserver.onDrop, true);
}
return elem; return elem;
]]></body> ]]></body>
</method> </method>