Angular-UI UI-Select Stop default behaviour of applying active class to first item - angular-ui

When options are initially displayed the first item has the active class applied.
To me this makes good sense if search is not toggled, although if the intention is for users to primarily use the search functionality, applying the active class seems clunky – particularly if you are using grouped items and applying custom styles to the drop down content.
The ability to navigate through the items with arrow keys is still desirable, but should only appear when the user initiates.
It does not seem any means to stop this default behaviour exists, I'm simply looking for a way to have an initial state of no active item.

I had a similar need and I simply set $select.activeIndex = -1 on focus of the primary element. This stopped the default behavior of the active class being set when the dropdown is loaded

I was able to remove the active class from the first item in the dropdown using the uis-open-close attribute on the parent element.
define the attribute in the template:
<ui-select theme="selectize" uis-open-close="$ctrl.setActiveIndex($select)">
Then in the controller set the activeIndex to -1:
setActiveIndex($select) {
$timeout(() => {
if($select.selected === undefined) {
$select.activeIndex = -1;
}
}, 25);
}

Related

I'm wondering about custom attributes, CSS attribute selector & repaint

So a little disclaimer: I am completely and utterly self taught. Bear over with me if I'm being a clown.
Anyways, I am currently working on a some platform and in need for a dropdown functionality. That's simple right? Just use HTML5 select tag. However option tags can't be styled :>
So onwards to build my own. The HTML5 select tag uses keyboard input (up/down/enter) for those with disabilities, and I thought I would implement that too. That did present a problem though: The :hover selector collided with my custom attribute, which I use to style keyboard selected items (&[data-selected=true] to be precise).
So onwards to implement my own :hover. And this is where my bewilderment starts.
const handleChildMouseOver = () => {
const items = Array.from(listItem.current?.children!); // The wonders of typescript XD
for (const item of items) {
if (item === event.target) {
item.setAttribute("data-selected", "true");
} else {
item.removeAttribute("data-selected"); // I'm removing the attribute, rather than toggling it, because I got components with 3 states: On, off, and default.
}
}
}
(...)
<ul css={css.list} /*emotion prop*/ data-toggled={toggled} /*parent state*/ onMouseOver={handleChildMouseOver}>
{children} // parent prop
</ul>
So it works as intended, which is fine. But I recall from my pre-react days that you should never manipulate the DOM in loops, as it causes repaints on every iteration. However when I look at the Dev Tools performance profiler, I barely see any "Paints", 8 or so, even when I'm switching hover targets like a madman. What I do see is one million "Composite layer". Oh, and as a bonus React doesn't re-render. Which is fine right? 'Cause I'm not really changing the state of anything, just adding some CSS.
So my question boils down to: Am I being bonkers or smart?
N.B.: I would love to share the actual component, but seeing as this is my first post on stackoverflow, I've got no clue how you do those fancy script tag. Well github is involved somehow, I know that much 🤔

CSS Change Each Cursor

I have a website I'm building and I want to have a custom cursors specified for each property like hand, wait, pointer, default, move and so on...
I'm build an operating system website so I want to have custom cursors.
Here is the CSS code.
* {
cursor:url("../.drive/system/visual/cursors/pointer.png"),pointer;
cursor:url("../.drive/system/visual/cursors/hand.cur"),hand;
cursor:url("../.drive/system/visual/cursors/pointer.cur"),default;
cursor:url("../.drive/system/visual/cursors/move.cur"),move;
cursor:url("../.drive/system/visual/cursors/move.cur"),all-scroll;
cursor:url("../.drive/system/visual/cursors/horizontal-resize.cur"),col-resize;
cursor:url("../.drive/system/visual/cursors/horizontal-resize.cur"),e-resize;
cursor:url("../.drive/system/visual/cursors/horizontal-resize.cur"),w-resize;
cursor:url("../.drive/system/visual/cursors/vertical-resize.cur"),row-resize;
cursor:url("../.drive/system/visual/cursors/vertical-resize.cur"),n-resize;
cursor:url("../.drive/system/visual/cursors/vertical-resize.cur"),s-resize;
cursor:url("../.drive/system/visual/cursors/diagonal-resize-1.cur"),se-resize;
cursor:url("../.drive/system/visual/cursors/diagonal-resize-1.cur"),nw-resize;
cursor:url("../.drive/system/visual/cursors/diagonal-resize-2.cur"),sw-resize;
cursor:url("../.drive/system/visual/cursors/diagonal-resize-2.cur"),ne-resize;
cursor:url("../.drive/system/visual/cursors/move.cur"),grab;
cursor:url("../.drive/system/visual/cursors/move.cur"),grabbing;
cursor:url("../.drive/system/visual/cursors/unavailable.cur"),no-drop;
cursor:url("../.drive/system/visual/cursors/unavailable.cur"),not-allowed;
cursor:url("../.drive/system/visual/cursors/text.cur"),vertical-text;
cursor:url("../.drive/system/visual/cursors/text.png"),text;
cursor:url("../.drive/system/visual/cursors/wait.cur"),wait;
cursor:url("../.drive/system/visual/cursors/help.cur"),help;
cursor:url("../.drive/system/visual/cursors/precision-select.cur"),crosshair;
}
The only cursor that happens to load is the one at the bottom (crosshair)
I've also specified some PNG cursors aswell and they did not change the outcome.
I tried putting this into html,body{} and div{} but again nothing worked.
I want something like on Windows93 but without JavaScript
If there is no CSS-only method then I can accept JavaScript ones. But please only vanilla-js.Thanks!
The cursor values are overwriting each other. This means that the last value is the only one that works, as it is the last one to overwrite the cursor value.
The word that follows the URL is a fallback keyword. This means that if the image cannot be found or rendered, the cursor specified by the keyword will be drawn.
For example, with the property cursor: url("../.drive/system/visual/cursors/precision-select.cur"), crosshair;, the browser will attempt to draw the cursor specified in the URL, but if it cannot it will use the default crosshair cursor.
To get the browser to display different cursors you will need to specify the cursor for each element. For your default cursor you would have:
* {
cursor:url("../.drive/system/visual/cursors/pointer.cur"),default;
}
To get a pointer over links you might then do:
a {
cursor:url("../.drive/system/visual/cursors/pointer.png"),pointer;
}
For crosshairs on a particular element you might try:
.target-element {
cursor:url("../.drive/system/visual/cursors/precision-select.cur"),crosshair;
}
You need to specify the cursor property for each element that you wish to have a changed/custom cursor. Using a universal selector for the default cursor ensures that you only specify the property for elements that require it.

what is the proper way to interact with inner components within the shadowDom using lit-element?

I am trying to use paper-dialog within my custom component.
I want to be able to open the dialog from outside the component. What is the best way to do this? (all the examples work directly on the component)
Also the dialog requires me to call "open()" on it to open it.
In the examples I found I found:
this.$.dialog.open();
But this doesn't seem to work with lit-element
I got it to work using shadowRoot, not sure this is the best option:
render() {
return html`
<style>
</style>
<paper-dialog id="dialog">
<h2>Content</h2>
</paper-dialog>
`;
}
firstUpdated(changedProperties) {
console.log("firstUpdated called")
if (this.shown == "true")
{
// this.$.dialog.open();
this.shadowRoot.getElementById("dialog").open()
}
}
I added a property to my element called "shown"
static get properties() {
return {
shown: Boolean,
Thinking I could pass this from the outside into my component, but it doesnt seem to do the trick either (I can set it once with the custom element propery, but changes to it from the out side dont seem to work.
Generally, if you are aggregating a dialog within an element that has other UI elements then you shouldn't be showing/hiding the dialog from outside the element - the event that triggers the dialog should be raised and handled with the containing element.
That said, if it's absolutely necessary, then I prefer a "showDialog" method (not a property). Closing the dialog should be triggered by a dialog button or loss of focus, so you don't need to expose a close method.

Disabling tabbing for dom elements not within a modal and overlay

I have a modal that pops up with tab-able elements. Is there something like jQuery's :focusable or pointer-events: none that would allow me use CSS to disallow focusing on items underneath the overlay?
edit: The problem with a JS based approach (and selectors), is that each rerender with React, the query selector would have to be run through again. I don't have control over the component rendering this modal.
You want to do something along the lines of:
const inputs = [...document.getElementsByTagName('input')];
inputs.forEach((input) => input.setAttribute('tabindex', '-1'));
const modalInputs = [...document.querySelectorAll('.my-modal input')];
modalInputs.forEach((input, index) => input.setAttribute('tabindex', index));
Full Example https://codepen.io/bradevans/pen/GGYxrg
Edit: I hadn't seen the reactjs tag until OP commented... I'd utilize the Modals componentDidMount lifecycle method to change the underlying DOM inputs tab indexes and change the modals at the same time or using internal state....
You may also want to store the old tab indexes and reapply them on componentWillUnmount();

knockout.js - IE -7 css class Issue

Here is a funny little issue i've come across with
dynamically setting the class for a array of divs.
Using Knockout.js i'm assigning the classes used via the 'attr' binding.
This works well in all browsers i've tested except IE-7 (Not worried about IE-6 etc)
I have an jsfiddle example highlighting the issue here
In the example the static (top row) should match the bottom one (ko generated)
In IE-7 i'm just seeing the broadest css selector color (Silver)
IE7 requires that you set className instead of class.
For instance, this works in IE7 and other browsers: http://jsfiddle.net/thirtydot/VVuGh/14/
<div data-bind='attr: { "class": classes, "className": classes }'></div>
However, support for this IE7 quirk should ideally not be in your HTML. Inside knockout.js would be a better place, though I know nothing about the library to be able to make such a recommendation.
If your class name can't be determined when you generate the template (i.e. it is part of your model), you could create a custom binding.
The content of your init / update methods would just set the class name for element based on what is returned by the valueAccessor. For a simple example, you could do (using jQuery):
ko.bindingHandlers.yourBindingName = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
// This will be called when the binding is first applied to an element
// Set up any initial state, event handlers, etc. here
$(element).addClass(valueAccessor());
},
update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
// This will be called once when the binding is first applied to an element,
// and again whenever the associated observable changes value.
// Update the DOM element based on the supplied values here.
}
};
You might build a more complex binding based on the knockout css binding.

Resources