When using React Quill I am trying to keep the elements in a specific order so that we can can handle clicks on the annoations accordingly (along with things like hover effects etc)
Currently, we highlight text in strings. This is currently how Quill will format the HTML.
[abc]this could [def][abc]be one[/abc][/def] of the strings[/abc]
The problem with this format is that hover/click's on [def] cause issues because it's a child of [abc], the [abc] will trigger the click/hover listeners.
I would like quill to instead format as HTML like this:
[abc]this could [/abc][def][abc]be one[/abc][/def][abc] of the strings[/abc]
As you can see, [def] is now an equal level whilst still possessing [abc] as a child.
I've tried using quill to register extensions of block and inline components as shown here: But unfortunately, neither have provided the solution that I would like. Maybe i'm trying to achieve this the wrong way. I also have a different SuggestionBlock for each type of highlight (Same content inside) so the content removed.
class SuggestionBlock extends Block {
static create(suggestion) {
let node = super.create()
// Add the suggestion attributes.
node.setAttribute("data-id", suggestion.id)
node.classList.add("highlight")
node.classList.add(suggestion.name)
return node
}
static formats(domNode) {
const id = domNode.getAttribute("data-id")
return id
}
}
Any ideas on how I could implement this would be incredible! Thank you.
Related
The puzzle
I'm working on a custom WordPress theme. I've created custom post types and custom taxonomies, some of which are tag style (rather than category style). All is working as it should, and the appropriate taxonomies show up where they should in their matching content types ('show_in_rest' => true).
BUT I would like to add a list of the currently existing tags to the description in the tags block.
Right now, the instructions for tags say: "Separate with commas or the Enter key." I'd like to append something along the lines of "Existing Tags: " and then the list of tags. Ideally, this would be dynamically generated, so that as clients add new tags it would update the list. For the specific site I'm working on though, even static text would be better than nothing.
What I've got so far
I found someone asking a somewhat similar question and tried using the code from one of the responses. I'm taking a modular approach, so I've put the enqueue_script in a separate php file which I'm require_once-ing...
In functions.php, I've got:
...
require_once("lib/gutenberg/tag_options.php");
...
In tag_options.php I've got:
<?php
/**
* Add a list of available tags to tag panels in the gutenberg editor.
*/
function radicati_tag_options() {
wp_enqueue_script(
'gutenberg-tag-options',
get_stylesheet_directory_uri() . '/lib/gutenberg/tag_options.js',
['wp-blocks', 'jquery'],
1.0,
false
);
}
add_action('enqueue_block_editor_assets', 'radicati_tag_options');
And in tag_options.js I've got:
window.onload = function() {
// This is code I found on the internet,
// aimed at creating a custom panel...
var el = wp.element.createElement;
function customizeProductTypeSelector(OriginalComponent) {
console.log(OriginalComponent);
return function(props) {
console.log(props.slug);
// The slug of one of my custom tag-style taxonomies is "topic"
// That's what I'm seeing in console.log, so I feel like I might
// be on the right track!
// Once I get this figured out, if need be I can write custom code
// for each of my custom tag-style taxonomies :)
if (props.slug === "topic") {
return el("div", {}, "Product Type Selector");
HELP! THIS IS WHERE IT ALL FALLS APART!
I CAN *REPLACE* THE CONTENTS OF THE TAG BLOCK
(AND THUS RENDER IT NOT A TAGS BLOCK ANYMORE)
BUT I JUST WANT TO ADD A PARAGRAPH CONTAINING
SOME TEXT, INCLUDING A LIST OF EXISTING TAGS
TO THE OTHERWISE PERFECTLY FUNCTIONAL BLOCK!
} else {
return el(OriginalComponent, props);
}
};
}
wp.hooks.addFilter(
"editor.PostTaxonomyType",
"my-custom-plugin",
customizeProductTypeSelector
);
};
TIA
Unfortunately, the documentation for messing with Gutenberg stuff is still pretty patchy, so this is as far as I've been able to get. I'll admit that my React is equally sketchy, so it's a pitiful combination :laughing: If any of you have any clues to throw my way, I would really appreciate your help!
I want to insert my block of HTML into a Shopify shop after a certain section but the problem is that each shop can use one of thousands of different themes, each one having a different DOM structure.
I can create the Script Tag and I can try to insert my HTML like this:
(function() {
var child = document.createElement("div");
var text = document.createTextNode("This is a test message");
child.appendChild(text);
var parent = document.getElementByClassName("ProductSection");
parent.appendChild(child);
})();
And this will work if the theme has a section with a class name of ProductSection but it won't for the majority of them that don't. Let's say I have an image gallery I'd like to show but only on Product pages and after the product description, what's the best way to select the product description DOM node so that I can insert my image gallery after it?
I found a couple threads with similar problems:
https://community.shopify.com/c/Shopify-APIs-SDKs/Using-Script-tag-to-add-dynamic-content-to-product-template/m-p/457855
https://community.shopify.com/c/Shopify-APIs-SDKs/Need-to-add-a-button-to-the-Product-page-via-a-Script-Tag/m-p/413919
and they seem to come to a similar conclusion, yet there are apps on the Shopify app market that do exactly this, and I wonder how do they do it?
As suggested in the links shared by you, it is not possible to correctly identify the DOM element in all the cases. However, there are couple of different approaches that can be used.
1) One is to ask merchant to add some specific element to markup that you can later use for rendering your content via JavaScript.
2) Try to guess the DOM element via some specific tag or href value, but allow merchants to override the DOM element selector via some JavaScript variable.
3) Use approach 2 with a combination of pre-determined info. Saw this approach used by AfterPay. They have a pre-defined array of popular themes along with their selectors. Then they use the theme name property from Shopify.theme.name
and get the relevant selectors. This solution may not work in all cases, so do allow the merchant to override DOM selector via some JavaScript variable.
Afterpay.supportedThemes = {
alchemy: {
product: {
"2017-12-14": {
selector: ".quadd-wrapper"
}
}
}
}
AfterPay JS Source Code
If you know of any other plugins, you can inspect the JavaScript and have a look how they identify the selectors.
I am having difficulty modifying or adding additional classes to individual components of wordpress blocks. I essentially just want to add a class or classes to some of the pieces that make up some of the core wordpress blocks to do things like add bootstrap styling.
An example of this would be the image gallery block. It works well enough for my purposes, but I may want to do something like add an "img-fluid" or "img-thumbnail" class to the images that are within that gallery.
I have looked through the documentation for block filters and I feel as though my answer is going to lie somewhere in there, I'm just not sure where yet.
I have tried using the blocks.getBlockDefaultClassName filter, but this adds a classname to the entire block as opposed to individual pieces that make up that block (such as the images in my gallery example).
This is the example they give for it in the documentation:
// Our filter function
function setBlockCustomClassName( className, blockName ) {
return blockName === 'core/code' ?
'my-plugin-code' :
className;
}
// Adding the filter
wp.hooks.addFilter(
'blocks.getBlockDefaultClassName',
'my-plugin/set-block-custom-class-name',
setBlockCustomClassName
);
I feel as though blocks.getSaveContent.extraProps might do what I need it to, but I am not sure how to use it in this way. The example they use looks like this:
function addBackgroundColorStyle( props ) {
return lodash.assign( props, { style: { backgroundColor: 'red' } } );
}
wp.hooks.addFilter(
'blocks.getSaveContent.extraProps',
'my-plugin/add-background-color-style',
addBackgroundColorStyle
);
But even if I were to add an extra property like a class name, I would think I would then need to modify the actual save and edit functions (I guess using more block filters) to then use that class name when it displays those pieces (in this case - the images), and I'm also not sure how to do that.
Any thoughts or suggestions about this would be appreciated.
There are two kind of changes one is structural change and the other one is styling change. In your scenario you need styling change but you are actually looking for structural change. You can write your own CSS that can handles your block styling on editor view and on front end.
These are the hooks that you need to enqueue your styles enqueue_block_editor_assets (enqueue your styles only on backend editor) and enqueue_block_assets (enqueue your styles on both backend and frontend).
I'm testing out CKEditor
I'm trying to get the display in the editor, to match my sites css style for displaying the end result.
What I'm trying to do is style the "wrap code" button to match the css of my site, by adding in a class.
I've seen on this page of the manual, that you can do stuff like this:
config.format_pre = { element: 'pre', attributes: { 'class': 'editorCode' } };
However, doing the same for a code block like so:
config.format_code = { element: 'code', attributes: { 'class': 'someclass' } };
Doesn't actually do anything. Anyone got a pointer on what I might be missing?
I've tested it working on other elements, so I know the config file changes are being picked up.
The one important thing is that every tag which is formatted via config.format_tagname should be also included in config.format_tags. However, this two settings (config.format_tagname and config.format_tags) works only form Block-Level elements (as stated in the manual page you referenced ).
As code element is considered as an inline one by CKEditor (see DTD), it is not possible to use this config here.
However, the easiest way to modify the elements added via Style dropdown is to edit styles.js file which is present in CKEditor directory. The dropdown styles are based on this file, so you can easily modify code element there. You can also define your custom stylesSet.
As part of automation testing, we want to inspect the element in a website which is made of using the Zebkit UI framework.
We are unable to find the element using zebra.ui
examples can be found here
Can someone help us on inspecting the element
Zebkit UI components are rendered on HTML5 Canvas. So they are not part of browser DOM tree what can be a problem for a test tool that expects DOM as an input. But it doesn't mean you cannot go over zebkit UI stuff to perform test cases.
First of all keep in mind zebkit components are a hierarchy/tree like DOM is. Every rendered on a canvas zebkit UI component has a related JS instance of appropriate class. There are number of API methods you can use to travel over UI components tree. These methods expect path (XPath-like) since path (from my point of view) is less "encrypted" way than CSS selector.
The API methods you probably need:
byPath(path [,callback]) - traversing UI components tree by the given path
var zcanvas = new zebkit.ui.zCanvas();
...
// travel over all UI components in tree
zcanvas.byPath("//*", function(comp) {
// perform test cases here
...
});
properties([path,] properties) applies the specified properties set to component or number of components requested by the given path
var zcanvas = new zebkit.ui.zCanvas();
...
// set color property to black value for all labels
zcanvas.properties("//zebkit.ui.Label", { color: "black" });
on([eventName], [path], handler) add listener method(s) for the given event (or all events) of the given component or components identified with the path:
var zcanvas = new zebkit.ui.zCanvas();
...
// register event listener for all found buttons
zcanvas.on("//zebkit.ui.Button", function (src) {
// handle button press event here
...
});
fire([eventName,] [path,] [argument]) fire the given event to the given component or to components identified with the path:
var zcanvas = new zebkit.ui.zCanvas();
...
// fire button pressed event to button with id equals "testButton"
zcanvas.fire("//[#id='testButton']");
...
// or the same with a shortcut
zcanvas.fire("#testButton");
I'm not sure I understand correctly your issue, but assume you cannot click right button on canvas to open context menu and select "Inspect element" option.
You can
press F12 in browser
switch to "Elements"/"HTML" tab
in search field (CTRL + F) print "canvas"/"<canvas" and press Enter
Continue pressing Enter until required canvas found (current element should be highlighted)
These controls are implemented using an HTML5 CANVAS tag. Selenium cannot see "inside" this tag because it doesn't contain HTML. It's like an app inside the page. From the page you linked, it looks like you should be able to use JS to access elements inside the control. When I've done things with CANVAS tags in the past, I generally find JS that does or returns what I want and then wrap that code in a function that I can call. It will work but you will likely have to do some research on Zebkit to find out what JS you will need to validate, etc. all the different things you will want to validate... and it may end up that you won't be able to validate some things.