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`
This commit is contained in:
David Taylor 2020-04-24 09:47:33 +01:00 committed by GitHub
parent 8a112b7464
commit 0616826841
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 22 deletions

View File

@ -1019,7 +1019,7 @@ export default Component.extend({
this._registerImageScaleButtonClick($preview); this._registerImageScaleButtonClick($preview);
this.trigger("previewRefreshed", $preview); this.trigger("previewRefreshed", $preview[0]);
this.afterRefresh($preview); this.afterRefresh($preview);
} }
} }

View File

@ -84,8 +84,8 @@ function show(image) {
} }
} }
function forEachImage($post, callback) { function forEachImage(post, callback) {
$post[0].querySelectorAll("img").forEach(img => { post.querySelectorAll("img").forEach(img => {
if (img.width >= MINIMUM_SIZE && img.height >= MINIMUM_SIZE) { if (img.width >= MINIMUM_SIZE && img.height >= MINIMUM_SIZE) {
callback(img); callback(img);
} }
@ -104,7 +104,7 @@ export function setupLazyLoading(api) {
}); });
}, OBSERVER_OPTIONS); }, OBSERVER_OPTIONS);
api.decorateCooked($post => forEachImage($post, img => hide(img)), { api.decorateCookedElement(post => forEachImage(post, img => hide(img)), {
onlyStream: true, onlyStream: true,
id: "discourse-lazy-load" id: "discourse-lazy-load"
}); });
@ -112,8 +112,8 @@ export function setupLazyLoading(api) {
// IntersectionObserver.observe must be called after the cooked // IntersectionObserver.observe must be called after the cooked
// content is adopted by the document element in chrome // content is adopted by the document element in chrome
// https://bugs.chromium.org/p/chromium/issues/detail?id=1073469 // https://bugs.chromium.org/p/chromium/issues/detail?id=1073469
api.decorateCooked( api.decorateCookedElement(
$post => forEachImage($post, img => observer.observe(img)), post => forEachImage(post, img => observer.observe(img)),
{ {
onlyStream: true, onlyStream: true,
id: "discourse-lazy-load-after-adopt", id: "discourse-lazy-load-after-adopt",

View File

@ -54,7 +54,7 @@ import { on } from "@ember/object/evented";
import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts"; import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts";
// If you add any methods to the API ensure you bump up this number // 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 { class PluginApi {
constructor(version, container) { constructor(version, container) {
@ -192,10 +192,23 @@ class PluginApi {
} }
/** /**
* Used for decorating the `cooked` content of a post after it is rendered using * Method for decorating the `cooked` content of a post using JQuery
* 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, * Use `options.onlyStream` if you only want to decorate posts within a topic,
* and not in other places like the user stream. * 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: * For example, to add a yellow background to all posts you could do this:
* *
* ``` * ```
* api.decorateCooked( * api.decorateCookedElement(
* $elem => $elem.css({ backgroundColor: 'yellow' }), * elem => { elem.style.backgroundColor = 'yellow' },
* { id: 'yellow-decorator' } * { id: 'yellow-decorator' }
* ); * );
* ``` * ```
@ -215,7 +228,7 @@ class PluginApi {
* NOTE: To avoid memory leaks, it is highly recommended to pass a unique `id` parameter. * NOTE: To avoid memory leaks, it is highly recommended to pass a unique `id` parameter.
* You will receive a warning if you do not. * You will receive a warning if you do not.
**/ **/
decorateCooked(callback, opts) { decorateCookedElement(callback, opts) {
opts = opts || {}; opts = opts || {};
addDecorator(callback, { afterAdopt: !!opts.afterAdopt }); addDecorator(callback, { afterAdopt: !!opts.afterAdopt });
@ -1114,10 +1127,10 @@ function decorate(klass, evt, cb, id) {
} }
const mixin = {}; const mixin = {};
mixin["_decorate_" + _decorateId++] = on(evt, function($elem) { mixin["_decorate_" + _decorateId++] = on(evt, function(elem) {
$elem = $elem || $(this.element); elem = elem || this.element;
if ($elem) { if (elem) {
cb($elem); cb(elem);
} }
}); });
klass.reopen(mixin); klass.reopen(mixin);

View File

@ -11,7 +11,7 @@ import {
let _beforeAdoptDecorators = []; let _beforeAdoptDecorators = [];
let _afterAdoptDecorators = []; 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 } = {}) { export function addDecorator(callback, { afterAdopt = false } = {}) {
if (afterAdopt) { if (afterAdopt) {
_afterAdoptDecorators.push(callback); _afterAdoptDecorators.push(callback);
@ -67,13 +67,11 @@ export default class PostCooked {
} }
_decorateAndAdopt(cooked) { _decorateAndAdopt(cooked) {
const $cooked = $(cooked); _beforeAdoptDecorators.forEach(d => d(cooked, this.decoratorHelper));
_beforeAdoptDecorators.forEach(d => d($cooked, this.decoratorHelper));
document.adoptNode(cooked); document.adoptNode(cooked);
_afterAdoptDecorators.forEach(d => d($cooked, this.decoratorHelper)); _afterAdoptDecorators.forEach(d => d(cooked, this.decoratorHelper));
} }
_applySearchHighlight($html) { _applySearchHighlight($html) {