Possible to use CSS transitions with textarea rows value? - javascript

In all the years I've been developing websites this situation has never cropped up before and I'm not sure that what I'm attempting to do is even possible.
I have a React component with a textarea. It's initial state is rendered with a height of 1 row like this :
state = {
rows: 1
}
...
<textarea
...
rows={this.state.rows ? this.state.rows : 1}
onFocus={this.onFocus}
...
/>
The onFocus function changes the rows state to 5, thereby expanding the textarea.
This works perfectly, but I'm now trying to add CSS transitions to the textarea so it expands nicely instead of just instantly expanding.
Everything I've tried doesn't work, for example :
textarea#content {
transition: all 2s ease-in-out;
}
...so my question is - is it not possible to use CSS transitions in this way? I did some googling and couldn't find any answers which leads me to believe that it isn't, but I just want to make sure before I set about achieving this another way.

Can't say how React might be involved here, but for a transition to work, the CSS property being transitioned must have a default value set for it. You are indirectly affecting the height property by changing the rows, but you are not actually specifying that you want the height to change, so you can't transition the height if you are only indirectly changing it. Also, there is no CSS rows property, so no luck on transitioning that either.
The solution is to not set the height indirectly with rows in the first place. Set the height directly and set a default value for height in the CSS.
And, you really don't even need JavaScript to do this:
textarea {
height:1em; /* Initial value required for transitions to work */
transition:height 1s ease-in-out; /* configure the transition*/
}
/* Style to be applied automatically when the textarea recievs the focus */
textarea:focus {
height:5em; /* A change in this property will trigger the transition */
}
<textarea></textarea>

Related

How to prevent JavaScript from filling in unspecified parts of style

If I set the style of an element with JS it seems to fill out the parts of the style which I intentionally left unspecified.
For example, if I set the transition style
el.style.transition = 'width .2s'
The html changes to
<div style="width: 50px; transition: width 0.2s ease 0s;"></div>
Which is inconvenient, because I want to be able to set the timing function in css without using !important
Does anyone know any simple ways to get around this, ideally without manipulating el.attributes.style?
That has nothing to do with JavaScript. That's the default behaviour of transition.
You could, for instance, try and make it the way you want by either specifying the duration yourself or by using el.style.transitionDuration
el.style.transitionDuration = "1s";

Tapping into fade events for Bootstrap 4

Many transitions in Bootstrap 4 provide a set of events to listen for. For example, you could do something like:
$('.certainDropdowns').on('hidden.bs.dropdown', function() {
// do the things
});
A light inspection of some of the components shows that somehow they are able to respond to fading. For example, the Bootstrap modal fires a "hidden" event once it has faded out. But this is at the modal level, not the transition level (hidden.bs.modal)
Unlike dropdowns and modals, there is not a "fade" JavaScript component. But the light scan of the source code seems to be indicating that Bootstrap provides emulation for CSS transitionEvent, and I'm trying to figure out how I can tap into it.
In brief:
Is there a Bootstrap 4-provided method for tapping into the fade transition's events, or am I limited to native transitionend (possibly with help from a 3rd-party polyfill)?
[edit to add content below]
I possibly should have tried transitionend before posting the question, but I just gave it a try and it seems to be no go like this:
<div id="something" class="fade show">Fadeable</div>
Then JS:
$('#something').on('transitionend', function() {
console.log('transition ended!');
});
//later
$('#something').removeClass('show');
This was tested only with the latest Firefox, which is one of my target browsers.
I couldn't find a way to do it in my intended way with the provided components. Instead, I ended up writing it as a single new class, "collapseFade" which could still use the Bootstrap pattern of adding/removing the class "show".
The tricky thing was that transitions would trample over each other if I just tried to add or remove the "show" class, so I had to add a second helper class, "out". This requires intimate understanding of the new classes, which was potentially hazardous to maintenance developers. Consequently, I wrote a jQuery plugin to go with it. Without using this answer as code repository, here's the lightweight breakdown:
SASS:
.collapseFade {
max-height: 400px;
transition:
max-height 0.5s,
opacity 0.5s 0.5s;
&:not(.show) {
opacity: 0;
max-height: 0;
}
}
.collapseFade.out {
transition:
max-height 0.5s 0.5s,
opacity 0.5s;
&:not(.show) {
opacity: 0;
max-height: 0;
}
}
(You could theoretically use Bootstrap's SASS fade variables instead of hard-coding time intervals).
Then the plug-in (code not included, for brevity) simply allows you to call collapseFade on an element. Eg. $('.something').collapseFade(). It optionally accepts "show" or "hide" as string parameters, but will just toggle by default. For whatever reason, transitionend is working here, so I also listen and fire an appropriate custom event for future maintenance or feature devs who might find it useful.
It functions thus: when showing, it removes the out class and adds the show class. When hiding, it adds the out class and then removes the show class.
The so-called "magic" is just in the timing. The second transition start is delayed by a value equal to the first transition time, which visually chains them together even though technically they are fired at the same time.
The other tricky bit is that the collapse animates max-height rather than height. This is the way Bootstrap themselves do it, and it makes sense... you can't animate "auto" height; it needs an actual target number. But straight-up "height" (no "max") means you're committed to occupying a certain amount of space. Max-height will allow height to be dynamic, but the trade-off is that it will operate smoothly only by restricting it as closely as possible. If I had put max-height of ten-thousand, for example, the collapsing animation wouldn't be smooth. You might notice that in Bootstrap's own collapse functionality, which is less than smooth for elements that are not tall. I don't anticipate my targets to be any taller than 400px so that's what I've provided.

Dynamic value for a transitioned property in CSS

I searched for a way to manage the transition CSS programmatically at runtime. Therefore I need to change the top value in the transition relatively at to the behavior of others components.
Is it possible or I am dreaming?
Yes, the transition setup (that is specification of the properties whose change of value should be transitioned) can be done in CSS and we can still dynamically modify the value for those properties.
All that is needed is a bit of JavaScript to assign the modified value to the element through inline style attributes. The transition which is set on the element will apply irrespective of whether the value is changed through a CSS selector or through inline styles.
/* transition after some time so that the effect is visible */
window.setTimeout(function() {
document.getElementsByTagName('div')[0].style.top = '100px'; /* set the top value dynamically */
}, 500);
div {
position: absolute;
top: 50px;
transition: all 1s;
}
<div>Something</div>

How to get a dynamic height when clicking again on a toggled div

I have this code:
$(document).ready(function(){
/* SET VAR FOR IS OPEN */
var isopen = 0;
/* SHOW FIRST NEWS ON STARTUP EXTENDED */
/* SET ALL .TRIGGER PARENT .CONTAINER TO FIXED HEIGHT WITH CUTTED CONTENT (OVERFLOW) */
$('.trigger:not(:first)').css({
height: "70",
overflow: "hidden"
}, 200 );
/* CLOSE THE CLICKED ELEMENT */
$('.trigger').click(function() {
if (isopen == 0) {
// SET ALL TRIGGER TO 70PX HEIGHT
$('.trigger').css({overflow: "hidden"}).animate({
height: "70",
}, 200 );
$(this).animate({
height: "350",
}, 200 );
} else {
alert('this Alert shuld show up if isopen=1');
}
});
})
Its a news content of a website.
The user see three divs.
2 are cutted to 70px Height
The first news is extended to its original height.
after click the height: auto; does not work. So the height is set to 350px. How to get a dynamic height? Thanks!
Difficult to 100% verify my answer as I would need a fiddle/plunker with your HMTL/CSS/JS to work with, but here is my suggestion that I think will help.
Rather than explicitly setting CSS styles to the elements via JavaScript, via methods like 'css(value, property)', instead add or remove classes to the elements via 'addClass()', 'removeClass()', or 'toggleClass()'.
New look JS:
$('.trigger').click(function() {
$(this).toggleClass('is-closed');
}
New look CSS:
.trigger {
// Your current UI component styling, but no height specified
}
.trigger.is-closed {
height: 70px;
overflow: hidden;
}
The difference here being, is that you're not trying to assert "height: auto" as an overriding style for "height: something else", you are simply adding and withdrawing the fixed height on open/close - which I would suggest is much less error prone much more likely to bring about the behaviour that you want.
Furthermore, this is also a good practice to follow in any event because of the following reasons:
Separation of concerns, your styling belongs in your CSS files rather than JavaScript (i.e. component styles all together)
Reusable code, these styles reflecting the "closed" state could be re-used across all instances of this UI component, as well as others components, rather than re-written every time in JS click handler functions
Modifying CSS via jQuery functions such as 'css(property, value)' is a bad idea, it results in the styles added as inline styles in the DOM (e.g. style="height: 70px;") and this will take priority over other CSS, making managing your CSS harder and debugging presentation errors more difficult
This approach also has the added benefit of reducing the length and clarifying your JavaScript code significantly.
Height Animation
The above code will not provide the height animation that you currently have.
The solution here is to adopt a CSS transition approach rather than animating via JavaScript. Article: http://www.w3schools.com/css/css3_transitions.asp
This will again mean that all of your component related styling will remain together in one place, but CSS animation also performs much better/renders faster than JavaScript animation does.
Hope this helps.
Setting css height in javascript is basically adding an element style tag to it, which will override the css file always due to the rendering rules of css. If you set the value to an explicit height, to get it back to height: auto, you either have to write height: auto to it in the javascript or remove the style element you added completely.

hide element without setting the display to none in jquery

I want to fold a section of the form without setting its display to none. If i set the display to none, the validation is bypassed that is why I don't want to set the display to none. I know I can set the visibility to hidden and visible but this solution is not feasible for rendering the view as the space for the folded section stays there. This results in a very odd look of the view with an empty white space with no content on it.
So my question is to hide a section of the html form (without intacting a placeholder for it) without setting its display to none, so that I could still perform the validation.
Some HTML code:
<td style="margin: 5px; border-bottom: 1px solid; display:none; overflow: hidden;" colspan="3">
<div>...</div>
</td>
The display is initially set to none but once it is unfolded for the first time, I am setting the height to 100% and removing the display style.
You can move it off the screen:
$(elem).css("position", "absolute").css("left", -9999);
Or set it's height to 0:
$(elem).css("height", 0);
The simplest way to fake display:none is by setting the position to absolute (so the element is taken out of flow, no longer influencing the rendering of outside elements) and the visibility to hidden (so it is no longer painted).
$(elem).css('visibility', 'hidden').css('position','absolute');
Set the opacity of the element to 0.
$(elem).css("opacity", 0);
$("#ele").css({"height" : 0, "width" : 0, "opacity" : 0});
Hiding an element with jquery...
$('element').addClass('hidden');
and in your CSS just use what ever you find appropriate to make that element "hidden"
.hidden{
/* whatever you find appropriate */
}

Categories