This was failing with a 'Object doesn't have
method' error on IE11. Assume Babel wasn't
polyfilling Array.includes so reverting to jQuery
version for now.
The work done to stack sticky elements closer
together only effected the stack when stuck to the
top/bottom edge:
707c426b9a
It should have included the same for when a stack
of sticky elements is stopped at the end of it's
scroll area. This adds code to deal with that.
The templateFolderForm JS was setting the mode to
'dialog' but not back when the state was changed
back to a normal sticky element. This caused
adjustments and scrolling when no adjustment
needed to be accommodated.
There were also problems with adjustForResize. It
was manipulating the same flag that resizing the
window did and returned a value never used.
The `recalculate` method currently does three
things:
1. sync's the internal store with the DOM
2. updates the saved positional and dimensional
data from the new DOM
3. allows the mode to be set
The problem with using it as the way to set the
mode is that, every call to it is effectively
setting the mode but this isn't always the
intention.
This splits off setting the mode so other modules
have to explicity set it and those that don't
intend to can just call `recalculate` to notify of
DOM changes.
If a sticky element was already in the store, the
code for adding it would return early. This meant
dimensions and positions for it were not being
recalculated.
make sure the class is applied to a child element, so that `$el.find`
will always find something for `js-will-stick-at-bottom-when-scrolling`.
Also, clean up code by treating all stickies on the template folder
form as dialogs - they all are after all all dialogs - modals that
expect your attention on top of the main page content.
When the screen resizes, the dimensions of our
elements may change so we run
`setElementDimensions` again to update our store
of those values.
This caused a bug with the stored position of
stuck elements. When stuck, elements are
'fixed' so their position is relative to the
window position. We need the value stored to be
from the position in the document flow, not the
'fixed' value.
This change means, when an element is stuck, we
check its shim for the position instead. The shim
occupies the space the element would do in the
page so it makes sense to use it for this.
The controls for the template folders are all
present in the page when it loads. The
templateFolderForm JS filters them so you only see
the one you need to for the thing you're trying to
do.
This changes when the controls are made sticky so
it happens after the templateFolderForm JS has
performed its filtering.
This ensures sticky elements don't fade in if
in a sticky position when the page loads.
The fade is there to show when an element is
becoming sticky. This has no use if it was already
sticky the first time you see it.
Because the same situation applies when
recalculate is called, we also want the flag to be
reset before this happens.
When mode === 'dialog', sticky elements are
stacked so we need to apply the box shadow to the
top (when sticking to the bottom edge) and bottom
(when sticking to the top edge) elements in the
stack.
From what I can see, we need the version of
`nth-child` that supports targeting by selector.
As of this date, support for this is only in
Safari:
https://caniuse.com/#feat=css-nth-child-of
Until we can use this version of `nth-child`, we
need to use JS to apply the styles.
Instead of keeping references to nodes detached
from the DOM, remove them from the store.
Likewise, add node appended to the DOM.
This includes code to 'clean' DOM nodes when
removed. This is important because nodes can
retain classes and styles. If they are re-attached
in future this can cause problems with how the
state of the element is determined.
We want a mode for when a single task is shared
between all sticky elements on the page and that
task has the highest priority on the page. In that
case:
- they should stack together into a single block,
attached to the top/bottom of the viewport
- that block should adjust to the vertical space
available
This should also adjust to the height of the
viewport, dropping whatever elements that don't
fit back into the page flow. When this happens, we
scroll the page so all the parts of the dialog are
seen together at the start of the task.
If the screen resizes, sticky elements can end up
moving from one part of the screen to another,
sometimes without passing through their different
states (in-page, stuck, stopped) in the normal
order.
This makes the methods that change their states
better at dealing with those state changes.
If you have a long template it’s annoying to have to scroll all the
way to the bottom to click save, when you’ve only changed a small thing
near the staert of the content.
Includes:
- change .stopped method to .isStopped() for
consistency
- replace code in checkResize that adjusts
dimensions for setElementDimensions
- add code that deals with the window size being
too small to run whenever positions are calculated
- add reset method for when screen is too small
for sticking behaviour
- move guard out of methods for stopping and
sticking (it hid info that was useful at the
point they were called)
Allows other JS to tell sticky elements to
recalculate their dimensions and then position
(and then check to see if their state needs
changing).
We need this because we change the content of our
element so its dimensions change.
The recalculation code also updates the shim for
elements that are 'stuck' so the horizontal space
the element would occupy in the flow of the page
is correct.
Includes other code that splits the height
StickyElement stores into two properties:
1. `verticalSpace`
2. `height`
`verticalSpace` is the vertical space the element
occupies in the document flow when not stuck.
`height` is the visual space of the element,
including padding and border.
This is better because it saves vertical space for the contents of the
pop-up menu.
This commit also adds some padding to the cancel and clear buttons, to
make them easier targets to hit.
Being able to see how many things you have selected gives you positive
feedback that reinforces that what you’ve done has been recognised. It
helps you understand the implications of your actions (ie you see ‘3
selected’ before you press the ‘Move’ button). And it gives you an
escape hatch the get out of the state you’re in by providing the ‘Clear’
button.
We also found in prototyping that having a ‘Nothing selected’ message
helps draws people’s attention to the checkboxes when they first
encounter the folders feature.
This commit implements the counter and the cancel button. It tries to
follow the existing patterns for this module.
We ‘shim’ the sticky element so that its space in the page is reserved
while it is sticky.
This means the shim have have the same height as the sticky element.
It’s height was not getting set because of a missing semicolon in the
shim element’s `style` attribute.
When you hit enter while an input in a form is in focus, your browser
finds the first button in the form, and carries out that action. So,
for non-js users, we added a hidden submit button with a value of
"unknown" to reflect that we don't know the intention of the user.
However, with JS enabled, this ambiguity doesn't exist - there's only
submit button and forms to fill in at a time, and non-visible fields
aren't even submitted at all. We can remove the unknown button,
supporting enter as submit properly. If the user is on one of the grey
button states, with no submit, it'll press the first button, and go to
the new template / move to existing folder dialog. That's fine enough.
previously, it'd always show nothing-selected-buttons - however, if
some items were checked (due to being selected previously, and loading
with a form error message), it would be showing the wrong buttons.
Now, if the state is unknown, work out which state to show by counting
checkboxes, the same as when someone presses the cancel button.
If you’ve searched to select an item and then you want to perform an
action on it it’s confusing when it goes away if you change your search.
It should always be clear which items you’re performing an action on.
This means that checked items should always be visible, no matter what
your search term is.
the html now contains a `data-prev-state` attribute which contains the
previous state, taken from the `operation` value in the form data (from
the submit button). This is used to seed the `currentState` of the
templateFolderForm. If not specified (or 'unknown', because the user
hit enter last time round), then set it to nothingSelectedButtons.
so that they better align with the front-end, where they'll be used in
data attributes. Also, making the kebab case is nice because it doesn't
give favouritism to either JS or python naming conventions
only remove the add template button if they have the folder service
permission (thus can see the add button at the bottom).
Also make some unnecessary functions into strings in the js, and
remove some commented out code
when cancelled, clears any data inputted into the sub-form action, and
then uses an icky hack to go back to the buttons, by changing the
state to "nothingSelectedButtons", and then pretending a checkbox was
clicked so it works out which actions to show and re-renders.
the action buttons have a value that matches up with the key for the
target form in the `this.states` object - we can just set the
currentState to that and call re-render and it all Just Works™.
detatch and reattach feel better than hide/unhide, mainly because it
means when the form is posted, any data that might linger in them
definitely won't be sent in the POST.
if action buttons are shown (either the nothing selected actions or the
stuff selected actions), when a checkbox is selected or deselected,
count how many checkboxes are selected. If it's zero, then show the
new template/folder buttons, if it's non-zero, then show the move
options.
Under the hood, we set the `currentState` variable, then the render fn
shows that element and hides all others.