This repository has been archived on 2023-03-18. You can view files and clone it, but cannot push or open issues or pull requests.
osr-discourse-src/app/assets/javascripts/discourse/components/mount-widget.js.es6
2016-03-21 15:14:31 -04:00

99 lines
2.5 KiB
JavaScript

import { diff, patch } from 'virtual-dom';
import { WidgetClickHook } from 'discourse/widgets/click-hook';
import { renderedKey, queryRegistry } from 'discourse/widgets/widget';
const _cleanCallbacks = {};
export function addWidgetCleanCallback(widgetName, fn) {
_cleanCallbacks[widgetName] = _cleanCallbacks[widgetName] || [];
_cleanCallbacks[widgetName].push(fn);
}
export default Ember.Component.extend({
_tree: null,
_rootNode: null,
_timeout: null,
_widgetClass: null,
_afterRender: null,
init() {
this._super();
const name = this.get('widget');
this._widgetClass = queryRegistry(name) || this.container.lookupFactory(`widget:${name}`);
this._connected = [];
},
didInsertElement() {
WidgetClickHook.setupDocumentCallback();
this._rootNode = document.createElement('div');
this.element.appendChild(this._rootNode);
this._timeout = Ember.run.scheduleOnce('render', this, this.rerenderWidget);
},
willClearRender() {
const callbacks = _cleanCallbacks[this.get('widget')];
if (callbacks) {
callbacks.forEach(cb => cb());
}
this._connected.forEach(v => v.destroy());
this._connected.length = 0;
},
willDestroyElement() {
Ember.run.cancel(this._timeout);
},
queueRerender(callback) {
if (callback && !this._afterRender) {
this._afterRender = callback;
}
Ember.run.scheduleOnce('render', this, this.rerenderWidget);
},
rerenderWidget() {
Ember.run.cancel(this._timeout);
if (this._rootNode) {
const t0 = new Date().getTime();
const opts = { model: this.get('model') };
const newTree = new this._widgetClass(this.get('args'), this.container, opts);
newTree._emberView = this;
const patches = diff(this._tree || this._rootNode, newTree);
const $body = $(document);
const prevHeight = $body.height();
const prevScrollTop = $body.scrollTop();
this._rootNode = patch(this._rootNode, patches);
const height = $body.height();
const scrollTop = $body.scrollTop();
// This hack is for when swapping out many cloaked views at once
// when using keyboard navigation. It could suddenly move the
// scroll
if (prevHeight === height && scrollTop !== prevScrollTop) {
$body.scrollTop(prevScrollTop);
}
this._tree = newTree;
if (this._afterRender) {
this._afterRender();
this._afterRender = null;
}
renderedKey('*');
if (this.profileWidget) {
console.log(new Date().getTime() - t0);
}
}
}
});