WhatSock / apex

Apex 4X: The Comprehensive ARIA Development Suite
MIT License
29 stars 9 forks source link

Still struggling with .render() #38

Closed mfs-bldmghty closed 1 year ago

mfs-bldmghty commented 1 year ago

I'm using the afterRemove setting. That passes the value of dc and I then do a dc.render() to immediately render the calendar. To the user it looks like it stays open. I don't think it matters, but I do some other things at the same time. For example, I get the date value from the input, turn it into something like "You've selected Tuesday Jan 10,2023" in the header above the dp / cal.

The issue is, (I think) the render() shifts the focus back to the calendar / datepicker. But I don't want that.

More specifically, once the user picks a date, I expose a form. When they submit that form, 4X / dc detects the click outside of the datepicker, closes the DP, but once removed, I - as mentioned above - "reopen" it. And cause focus to jump to the cal. Along the same lines, even just clicking into the form is a problem, as that first click in an input looks like an "outside" click to 4X / dc and focus immediately jumps out of the input.

I'm looking for a way to keep the calendar open at all times, without getting anything janky from using afterRemove or render().

Thoughts? Suggestions??

p.s. i think you can close the issue about UTC. I believe I've resolved that. Mostly, i think, it was a defective in the mental model in my head. Sorry.

accdc commented 1 year ago

Hi, This is actually easy to do, though it requires you manually run the methods that you want when you need them.

After you instantiate the calendarDC object, just lock it open like so.

calendarDC.lock = true;

This will lock the DC object in its current state, whether this is currently open or closed, so you want to set this only after the calendar is rendered.

By doing this though, it won't run any of the lifecycle events like afterRender() or afterRemove(), so you will need to manually run the methods you want to run when you need them instead like so.

calendarDC.afterRender(); calendarDC.afterRemove();

Since you are halting the internal lifecycle methods as well, you will need to make sure things are working correctly by doing this through comprehensive testing.

This should prevent the auto-focus issue from occurring, or at least make it possible to override it by setting focus to a different location when you need to.

There are a lot of events tied to proper focus movement that relate to accessibility, so please be careful not to impair this for assistive technology users.

mfs-bldmghty commented 1 year ago

@accdc - Thanks again for your help.

I slapped .lock = true and yeah, it locks it up :) While I'm going to say it's possible to manually manage the lifecycle, that's not something I have the bandwidth for at the moment :(

I'm going to - at least for now - abandon the "keep it open always." I've actually done that already and it does get rid of the jankies. So overall it's working. The client's previous calendar (jQuery UI) was always open so I'm guessing they'll want that. I'll just have to say "not now". And either I'll look at the lifecycle stuff you've mentioned, or it'll be a feature in a future release.

btw, I've been using this:

https://whatsock.com/Templates/Datepickers/index.htm

Looks like that was a mistake, as lock isn't there :(

p.s. Might you have an example of using animation? Maybe instead of closing immediately, I can slow that down and the transition will feel less whiplash-y?

accdc commented 1 year ago

Hi, yes of course, animation is built in.

Are you using the $A.import() method for loading the datepicker module, or are you using the traditional script statement?

If using the $A.import() method, you can see that all the examples within the repo Templates/Datepickers folder include an "animate" module import and code block for configuring this.

If using the traditional script statement instead, you simply need to load the animation module imports before loading the datepicker module and setup script, like so.

    <script  src="4X/4X.js"></script>
    <script  src="4X/Standard/Modules/Velocity.js"></script>
    <script  src="4X/Standard/Modules/VelocityUI.js"></script>
    <script  src="4X/Standard/Modules/Animate.js"></script>
    <script  src="4X/Standard/Modules/Datepicker.js"></script>

Afterwards, you can include a code block like the following to set whatever animation effects you wish.


    style: { position: "absolute", zIndex: 1, display: "none" },
    animate: {
      onRender: function (dc, wrapper, next) {
        Velocity(wrapper, "transition.fadeIn", {
          complete: function () {
            // Running next() is required to continue executing built-in lifecycle methods such as afterRender() when the animation completes.
            next();
          },
        });
      },
      onRemove: function (dc, wrapper, next) {
        Velocity(wrapper, "transition.fadeOut", {
          complete: function () {
            // Running next() is required to continue executing built-in lifecycle methods such as afterRender() when the animation completes.
            next();
          },
        });
      },
    },

To see which animation effects you can use, simply check out the help file within the repo at: Help/VelocityUI-Effects-Index.txt

About the lock property, this is actually not a feature specific to the datepicker, but is rather a DC API feature. All of these are documented within the help folder at: Help/DC API/