Yes that should work, and that is my recommended solution if there are parts of the page you still want to check -- e.g., ignoring .page-civicrm .toolbar *, .page-civicrm header *, but still checking the rest of main.
But if you want to hide the checker altogether in that section, I recommend scrolling down to the "Displaying Results" section and putting .page-civicrm in the field labeled "Disable the scanner if these elements are detected." The checker does not even initiate if it detects a match for that one.
So far that has worked for everyone with this issue in Drupal, which is why I haven't implemented a more formal path-based check on the PHP side...waiting for someone to come back and tell me it didn't work!
Batching moved into new sub-module with separate dependencies, so that users can define their own export fields.
I like this idea. Centralizing it would be especially useful for users who need to disable hotkeys due to conflicts with assistive tech -- one easy toggle on their user page to enable/disable shortcuts. I imagine you could even provide a global modifier key (shift, control, etc) that could be added as an override.
If there was a "read-only" type attribute, I imagine this could also provide a way for modules to document hard-coded keyboard shortcuts provided by libraries that cannot be overridden.
I'm still not sure what is meant by the View itself not being in the schema, but there were schema errors for some of the fields I found when working on the 3.x branch. I think they are fixed now.
I'm guessing I need to change something in the pipeline config to enable it?
Adding functionality to identify and remove stale records requires rewriting the database tables, adding maintenance functions and a manual refresh crawler. That is all being worked on in the 3.x branch. I will be tagging an alpha this week and hope to have a stable release by the end of the year.
In the meantime, if you click through to a page record in the dashboard via the issue count, there is a button to delete the records for that page. But that's a bit too much work if you have more than a few stale records.
itmaybejj → made their first commit to this issue’s fork.
Oh cool. I never know which lines in there are mandatory.
FYI on:
  return window.parent.drupalSettings.canvas && !window.parent.document.body.querySelector('[class^=_PagePreviewIframe]');
...I got a bug report 🐛 Check for parent.drupalSettings.canvas causes errors in environments where parent is not set Needs review soon after launch that automated testing running headlessly doesn't create a parent context. So you might want something like:
  return window?.parent?.drupalSettings?.canvas && !window.parent.document.body.querySelector('[class^=_PagePreviewIframe]');
Two bugs located!
Summary of Slack conversation:
- The Editoria11y library version number was not incremented in the last release. I'm adding a script to automate this for the next release. In the interim, browsers many need to hard refresh to get the new file version.
- The alt mark tags themselves are duplicating on incremental checks, and can flicker in and out of existence. I'm fixing that for the next release too.
Thank you for your help debugging this
Two questions:
- Cache cleared?
- Are you viewing a published or preview page, or viewing the checker while editing? I haven't implemented this while editing yet. I should change the release notes to make that clear. But if you are not in edit mode, this might be a bug.
In the interim, I found a rathery-hacky way I can tell whether my component JS is running in a Canvas frame, and whether Canvas is in edit or preview mode:
  if (parent.drupalSettings.canvas) {
    // I'm in <em>some</em> sort of preview iframe, because the window has loaded Canvas' drupalSettings.
    if (!parent.document.body.querySelector('[class^=_PagePreviewIframe]') {
      // Canvas has not rendered the page preview pane, so it must be editing. Don't run.
    } else {
      // Canvas is previewing. Run.
    }
  }
I'm doing the !not for now, because I would rather fail to not running at all than running while editing. So long as classes never change, this is good enough for my purposes.
Hmm. I need this to let Editoria11y run in preview mode 📌 Disable functionality in the Canvas editor Active .
Passing on some methods I have used to do this in the past for detecting whether WordPress editors are running in frames. Apologies if you already know all this, but it's niche enough that I know a lot of people that don't, so...
1.
As long as the iframe is served from the same domain, the outer document can write to the iframe DOM directly.
The key is accessing starting selectors against DOMREFERENCETOFRAME.contentWindow.document.* rather than document.*.
You can then write JS as normal using that DOM reference: frame.contentWindow.document.body.classList.add('hi')
For example, I insert a script tag into the frame header. This inner script only has a few lines of code -- sets some classes, things like that. But it is injected from the outer into the inner:
      const iframes = document.querySelectorAll('.whatever')
      iframes.forEach(iframe => {
        const head = iframe.contentWindow.document.getElementsByTagName('head')[0];
        const script = iframe.contentWindow.document.createElement('script');
        script.src = URL-FROM-DRUPALSETTINGS;
        script.type = 'text/javascript';
        head.appendChild(script);
      });
That's going to be the easiest thing to do in my opinion -- have the outer Canvas editor JS set a body class in the preview inner frames that tells them when they are in an edit or preview state. I would also dispatch a JS event inside the frame, in case that change came after the load event fired.
Note that you may need to wait for the inner to load. I think it is possible to try to access them before the contentWindow is ready. I have not had problems in practice.
2.
The other thing frames in the same domain can do is access variables elevated to the window scope using the parent prefix -- e.g., if your Canvas outer application sets "window.MyGlobalVar = myLocalVar," that lets all iframes from the same domain access it as parent.MyGlobalVar. So inner JS could just check on run if, say, "parent.canvasMode" exists ("Oh it's there...I'm definitely in a frame...), and whether it was set to "editing" or "previewing."
3.
The most complicated but powerful way I have communicated with iframes is using Web workers. Setting up a simple pass-through worker lets the outer JS and inner JS dispatch variables and events to each other. That would have the advantage of being able to nest more than one layer down, too -- e.g., if the inner iframe had its own iframe, in theory they could all be listening on the same port, and the outermost could just shout "hey folks you're all in iframes!" to the worker, and all the inners would receive it.
Oh bother. They changed the name and CSS classes, which of course broke my code that detected and reacted to the editor.
I'll get a fix out soon.
Can I suggest an approach that addresses both the concerns about required and the help text, and avoids fighting with CKEditor over the aria-label?
Rather than adding an aria-label to the CKEditor frame, add it to the field wrapper, with another attribute of role="group":
<div class="form-item" role="group" aria-label="[original field label] [, required (if applicable)]"...
eg
<div class="form-item" role="group" aria-label="Body, Required"...
Then the screen reader will speak the various inner elements (there may be several), but you would hear the outermost label and whether the fieldset is required when the cursor enters the region.
That sounds good and I can do that.
I think what I really need to do is provide a better method -- e.g., have the module JS create an options file, and then dispatch a JS event that would let people modify the object without having to copy and hack the module JS. It would not work any differently now, but it would make their life easier down the road if the module JS changed. Basically create a hook in JS.
There -- tagged a release → for the module with that new library code. That should fix the PopeTech validation errors.
For the moment I am leaving the icon deduplication. This deduplication only happens when there is a combination of a specific action warning ("this link opens an app or a file download") and a general warning ("this link is external or opens in a new window.") The more specific icon "wins" visually on the logic that it is enough of a warning of a differing link purpose for users who can see that the new action popped a new window. The library allows adjusting priority to control which icon wins.
If someone wanted to add an option to not deduplicate icons, they would need to go to the location in the JS where the text merges for multiple hits, have it check a config option and then generate and insert the relevant icon, and add that new config option to both the library and the module.
I don't plan to take that on because I think the current solution is a good balance of informative and annoying, but I would be happy to offer tips and testing if someone wanted to try.
It won't address the single icon -- that is by design -- but I'll be tagging a release shortly that fixes the invalid aria description.
Just an FYI from when I was getting reports like this -- if you start converting between absolute and relative you may then run into "excitement" on sites that are served from a subfolder.
Yeah seems like cache clear is the thing to do. I added version numbers to the library definition just for kicks, but I am pretty sure cache will need to clear for those as well.
Thank you @leoenriquezp and testers. This was a regression from hard-coding check prevention when Experience Builder is active.
Closing for now; please re-open if something is not working as expected.
I will leave the issue open until August 2025 and then close it with a won't fix - maybe someone will come up with an amazing idea of how to make this work reliably.
Why not something much simpler, using a Dirty Forms approach?
Rather than an automatic unlock via beacons when closing the form, just throw an alert dialog that the page is still locked for other editors, and ask if the user wants to keep the page checked out for 30 minutes or discard their editing lock now?
Yes there has. Targeting fall/winter now, as this will be a breaking change so I've wrapped a bunch of other issues into the branch.
Thank you; I'll try to get a release out next week.
It updates as soon as you visit the fixed page. No need for a cache clear.
It is using the URL as the unique key though, so you can sometimes end up with a record that needs to be manually dropped if you change an alias. Usually clicking through from the dashboard takes care of that (the "ed1ref" query variable is to check for that). I'm working on switching to using NID/TID as a key when available.
If this is happening every time you may have found a bug.
swirt → credited itmaybejj → .
Just tagged Editoria11y 2.2.14 → , which removes conflicts and enables checking in XB page previews. I updated the issue description.
I would love to add live-checking, but I think that might require a lot of React work and configuration, since the in-editor containers do not even have the same tags (div instead of p or h2), and I don't plan to explore that until XB is stable and has documented APIs for modifying the UI. This release at least achieves parity with my Layout Builder support.
That was indeed the issue.
This whole page should be rewritten; the code is far too fragile as it is. I may revisit in the 3.x branch. But in the interim -- I tagged a release with a quick fix.
I see you closed this -- is this because you no longer need it, or because you figured it out?
Both can be adjusted via CSS and/or injected configuration.
I've had...less embarrassing moments. 2.2.13 tagged → .
Thanks for posting the workaround; I'll take a look at this in the next release cycle.
Possible hints if anybody wants to take this on:
- Views itself has a wildcard schema for views? and data types
- some documentation → that of course does not mention Views, but presumably it's a config type
I'm working on this in a 3.x issue fork.
OK I'm convinced. 1.0.19 removes the parentheses. →
If it works on your project I'm satisfied. This basically removes all the new code in the PR and replaces it with a simple "If the bundle is missing a label just use this hard-coded string instead." I don't expect that to introduce regressions
Updated MR !32. See if this works.
$entity_type = $entity && method_exists($entity, 'bundle') ? "Taxonomy: " . $entity->bundle() : 'Taxonomy term';
I'd vote to keep the H2. Sub-themes might place this block in other regions.
Thank you. The smaller viewport attribute is probably going to solve a longstanding bug where the icons sometimes paint oversize for a single frame while the CSS is loading.
That looks good to me. Let me do some testing against some past edge cases before tagging a release.
Thanks. This will be an easy change but it's nice to able to test.
Finding out "what is this thing and what is its name" is startlingly complicated in Drupal, and edge cases in custom entities are common.
Reading up on this; it sounds like JAWS pronounces them at certain verbosity settings? Is it in JAWS where you are hearing it?
I have been testing in NVDA and VoiceOver, and in both of those it sounds more natural to drop the injected text into a parenthetical clause. I could probably achieve a similar audible affect using commas, but I'm trying not to mess with the actual grammar of the surrounding sentence...
It would certainly be easy from a technical perspective to expose these settings in config -- these strings are all passed to the library as options. But I'd rather have the base library have defaults that satisfy the majority of the people who are going to benefit from it.
I might have to reach out to some JAWS users for feedback; the more the merrier for this sort of thing...
Yeah I'll work on this in the 3.x branch. That will have a beta period that will be good for feedback.
itmaybejj → created an issue.