From 06168268412e909e83ed5bbc1f12c0bfe1487c8d Mon Sep 17 00:00:00 2001 From: David Taylor Date: Fri, 24 Apr 2020 09:47:33 +0100 Subject: [PATCH] DEV: Add jquery-free `decorateCookedElement` function to plugin api (#9534) This is a replacement for `decorateCooked` which will work without jquery. A backwards compatibility layer is provided for existing plugins/themes which are currently using `decorateCooked` --- .../app/components/composer-editor.js | 2 +- .../discourse/app/lib/lazy-load-images.js | 10 +++--- .../discourse/app/lib/plugin-api.js | 35 +++++++++++++------ .../discourse/app/widgets/post-cooked.js | 8 ++--- 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/app/assets/javascripts/discourse/app/components/composer-editor.js b/app/assets/javascripts/discourse/app/components/composer-editor.js index ad34e961849..a71902ed524 100644 --- a/app/assets/javascripts/discourse/app/components/composer-editor.js +++ b/app/assets/javascripts/discourse/app/components/composer-editor.js @@ -1019,7 +1019,7 @@ export default Component.extend({ this._registerImageScaleButtonClick($preview); - this.trigger("previewRefreshed", $preview); + this.trigger("previewRefreshed", $preview[0]); this.afterRefresh($preview); } } diff --git a/app/assets/javascripts/discourse/app/lib/lazy-load-images.js b/app/assets/javascripts/discourse/app/lib/lazy-load-images.js index 56ab825e0b8..c3f63d2891e 100644 --- a/app/assets/javascripts/discourse/app/lib/lazy-load-images.js +++ b/app/assets/javascripts/discourse/app/lib/lazy-load-images.js @@ -84,8 +84,8 @@ function show(image) { } } -function forEachImage($post, callback) { - $post[0].querySelectorAll("img").forEach(img => { +function forEachImage(post, callback) { + post.querySelectorAll("img").forEach(img => { if (img.width >= MINIMUM_SIZE && img.height >= MINIMUM_SIZE) { callback(img); } @@ -104,7 +104,7 @@ export function setupLazyLoading(api) { }); }, OBSERVER_OPTIONS); - api.decorateCooked($post => forEachImage($post, img => hide(img)), { + api.decorateCookedElement(post => forEachImage(post, img => hide(img)), { onlyStream: true, id: "discourse-lazy-load" }); @@ -112,8 +112,8 @@ export function setupLazyLoading(api) { // IntersectionObserver.observe must be called after the cooked // content is adopted by the document element in chrome // https://bugs.chromium.org/p/chromium/issues/detail?id=1073469 - api.decorateCooked( - $post => forEachImage($post, img => observer.observe(img)), + api.decorateCookedElement( + post => forEachImage(post, img => observer.observe(img)), { onlyStream: true, id: "discourse-lazy-load-after-adopt", diff --git a/app/assets/javascripts/discourse/app/lib/plugin-api.js b/app/assets/javascripts/discourse/app/lib/plugin-api.js index 8f0e14253fa..71880003272 100644 --- a/app/assets/javascripts/discourse/app/lib/plugin-api.js +++ b/app/assets/javascripts/discourse/app/lib/plugin-api.js @@ -54,7 +54,7 @@ import { on } from "@ember/object/evented"; import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts"; // If you add any methods to the API ensure you bump up this number -const PLUGIN_API_VERSION = "0.8.41"; +const PLUGIN_API_VERSION = "0.8.42"; class PluginApi { constructor(version, container) { @@ -192,10 +192,23 @@ class PluginApi { } /** - * Used for decorating the `cooked` content of a post after it is rendered using - * jQuery. + * Method for decorating the `cooked` content of a post using JQuery * - * `callback` will be called when it is time to decorate with a jQuery selector. + * You should use decorateCookedElement instead, which works without JQuery + * + * This method will be deprecated in future + **/ + decorateCooked(callback, opts) { + this.decorateCookedElement( + (element, decoratorHelper) => callback($(element), decoratorHelper), + opts + ); + } + + /** + * Used for decorating the `cooked` content of a post after it is rendered + * + * `callback` will be called when it is time to decorate with an DOM node. * * Use `options.onlyStream` if you only want to decorate posts within a topic, * and not in other places like the user stream. @@ -206,8 +219,8 @@ class PluginApi { * For example, to add a yellow background to all posts you could do this: * * ``` - * api.decorateCooked( - * $elem => $elem.css({ backgroundColor: 'yellow' }), + * api.decorateCookedElement( + * elem => { elem.style.backgroundColor = 'yellow' }, * { id: 'yellow-decorator' } * ); * ``` @@ -215,7 +228,7 @@ class PluginApi { * NOTE: To avoid memory leaks, it is highly recommended to pass a unique `id` parameter. * You will receive a warning if you do not. **/ - decorateCooked(callback, opts) { + decorateCookedElement(callback, opts) { opts = opts || {}; addDecorator(callback, { afterAdopt: !!opts.afterAdopt }); @@ -1114,10 +1127,10 @@ function decorate(klass, evt, cb, id) { } const mixin = {}; - mixin["_decorate_" + _decorateId++] = on(evt, function($elem) { - $elem = $elem || $(this.element); - if ($elem) { - cb($elem); + mixin["_decorate_" + _decorateId++] = on(evt, function(elem) { + elem = elem || this.element; + if (elem) { + cb(elem); } }); klass.reopen(mixin); diff --git a/app/assets/javascripts/discourse/app/widgets/post-cooked.js b/app/assets/javascripts/discourse/app/widgets/post-cooked.js index 71fc9f43ef0..6cd3a6f66a2 100644 --- a/app/assets/javascripts/discourse/app/widgets/post-cooked.js +++ b/app/assets/javascripts/discourse/app/widgets/post-cooked.js @@ -11,7 +11,7 @@ import { let _beforeAdoptDecorators = []; let _afterAdoptDecorators = []; -// Don't call this directly: use `plugin-api/decorateCooked` +// Don't call this directly: use `plugin-api/decorateCookedElement` export function addDecorator(callback, { afterAdopt = false } = {}) { if (afterAdopt) { _afterAdoptDecorators.push(callback); @@ -67,13 +67,11 @@ export default class PostCooked { } _decorateAndAdopt(cooked) { - const $cooked = $(cooked); - - _beforeAdoptDecorators.forEach(d => d($cooked, this.decoratorHelper)); + _beforeAdoptDecorators.forEach(d => d(cooked, this.decoratorHelper)); document.adoptNode(cooked); - _afterAdoptDecorators.forEach(d => d($cooked, this.decoratorHelper)); + _afterAdoptDecorators.forEach(d => d(cooked, this.decoratorHelper)); } _applySearchHighlight($html) {