Rails file_field input as a button - css

I have a button that I want to perform the action generated by a file_field in Rails. Here is the erb code I have right now:
<label for='file-input'>
<span class='btn btn-success' style='max-width: 300px;'>
<img src=<%= image_path('button-upload-white.svg')%>></img> Upload from computer
</span>
</label>
<%= f.file_field :files, multiple: true, name: 'attachment[file]', id: 'file-input'%>
I was following the pattern in this question with the associated CSS:
.file-input > input
{
display: none;
}
.file-input > label{
cursor: pointer;
}
but it does not seem to work and generates the following:
Desired output would be the same with the choose files input hidden or somehow connected to the button itself. Thanks, please let me know if I should post more code or I'm thinking about this in the wrong way.

Try this to 'hide' the input element
Width and height are set to 0.1px instead of just 0px. Setting the property values to zero ends up throwing the element out of tab party in some browsers. And position: absolute guarantees the element does not interfere with the sibling elements.
.file-input > input {
width: 0.1px;
height: 0.1px;
opacity: 0;
overflow: hidden;
position: absolute;
z-index: -1;
}
Credit

Related

Angular parent form-control Bootstrap / CSS is not applied to child component

I created a autocomplete child component that I am using in parent. In parent when try to apply the validation using Bootstrap form-control it's not getting applied to this child component - which is an input box with a list, although it's getting applied to other controls which are not child.
Child component HTML:
<div class="searching">
<input type="text" class="form-control" (input)="getFilteredData(inputBox.value);" class="form-control" [formControl]="inputBox">
<div id="search" tabindex="0" >
<ul class="suggestionList">
<li *ngFor="let result of filteredResults | async" (click)="onUserSelected(result)" >{{result[displayField1]}} | {{result[displayField2]}} {{result[displayField3]}}</li>
</ul>
</div>
</div>
Parent component:
<app-auto-complete formControlName="requestorId"
[ngClass]="{ 'is-invalid': submitted &&
requestorId.errors }"></app-auto-complete>
<div *ngIf="submitted && f.requestorId.errors" class="invalid-feedback">
<div *ngIf="f.requestorId.errors.required">Requestor ID is required</div>
</div>
Child CSS:
.searching {
width: inherit;
position: relative;
}
.searching input {
margin: 0;
padding: 0;
width: 100%;
height: 30px;
}
.suggestionList {
background-color: #fff;
width: 100%;
position: absolute;
padding: 0;
left: 0;
z-index: 1000;
}
.suggestionList li {
list-style-type: none;
border: 1px solid #c5c5c5;
cursor: pointer;
left: 0;
font-family: Arial,Helvetica,sans-serif;
font-size: 1em;
text-align: left;
}
I have several workaraounds in mind, so I hope any helps.
As mentioned in the comments, add in your parent component decorator the property 'encapsulation' (same level as 'selector' and such) with ViewEncapsulation.None.
Be aware that this approach makes styles of the parent component penetrate the whole app, so be wary with doing this unless you have the parent selector be really specific such as .my-specific-parent-selector-which-isnt-gonna-be-repeated
use #Input property on child component to pass the validation boolean, and apply the class directly according to the Input passed.
add a .parent-selector .is-invalid selector to parent, and then add behind it a ::ng-deep .parent-selector .is-invalid making that specific styling penetrate child classes. Be wary that this approach is deprecated though, so it might stop working in the future (although unlikely)
Note:
also note that you are applying the is-invalid class to a selector.. if you inspect with chrome web browser you will see that this selector usually is a different element that where you try to add your class... so maybe your best approach is using inputs

Show tooltip on DIV FOCUS and HOVER on it

I am displaying a tooltip on an input field using css and surrounding the inPut within DIV. Basically the style is applying on DIV. The style gets applied on hover of the input field now.I want to display the tooltip as soon as the user tabs into that field. I see that DIV doesn't work on :focus. Any thoughts on how to show as soon as user focus on the field. I am using angular, can we apply some the class of the parentNode or any other way of doing it.
test(e: Event) {
if (this.inputfield.nativeElement.parentNode.tagName.toString().toLowerCase() === 'div') {
// apply the class to the parentNode
}
}
.tooltipmain {
position: relative;
display: inline-block;
}
.tooltipmain .tooltiptext {
visibility: hidden;
width: 185px;
background-color: #fff;
color: #000;
text-align: center;
}
.tooltipmain .tooltiptext::after {
content: "";
position: absolute;
bottom: 100%;
left: 50%;
}
.tooltipmain:hover .tooltiptext {
visibility: visible;
}
<div class="tooltipmain">
<input #inputfield onFocus="test($event)"> </input>
<div class="tooltiptext">
<table>
<tr>
<td></td>
</tr>
</table>
</div>
</div>
You can make use of focus, blur, mouseenter and mouseleave to track events triggered by the input field. Each of these events will be calling a function which will update the isFocussed variable.
<input
(blur)="focusChanged(false)"
(focus)="focusChanged(true)"
(mouseenter)="focusChanged(true)"
(mouseleave)="focusChanged(false)"
type="text">
On the element you want to toggle visibility you can make use of [class.<className>="<expression>"]. This will add/remove a class on the element based on the expressions.
<div [class.isActive]="focussed" class="tooltiptext">
Stackblitz example here

Prevent css transition when angular 4 component load

I have a big problem with css transitions and angular 4.
Actually, I use an external library which provides an input counter (that's my library, so I know no more style is applied to the wrapped input), but on the application I have the following style for the inputs:
input {
&[type="text"],
&[type="password"],
&[type="email"] {
border-radius: 4px;
border: 1px solid $grey-color;
padding: 0.5rem 1rem;
outline: none;
width: 100%;
transition-property: all;
transition-duration: 300ms;
font-size: inherit;
}
}
And in the html template:
<input-counter
type="text"
placeholder="Name"
[maxlength]="nameMaxLength"
[(ngModel)]="name">
</input-counter>
<input-counter> component template:
<style>
.input-counter-group {
display: block;
position: relative;
}
.input-counter-group span {
color: #b0b0b0;
font-size: 10px;
}
.input-counter-group .text-input-counter {
position: absolute;
line-height: 10px;
right: 0;
bottom: -13px;
}
</style>
<div class="input-counter-group">
<input
[id]="id"
[type]="type"
[ngClass]="className"
[name]="name"
[placeholder]="placeholder"
[maxlength]="maxlength"
[disabled]="disabled"
[pattern]="pattern"
[required]="required"
[readonly]="readonly"
[(ngModel)]="value"
(focus)="onFocus()"
(blur)="onBlur()">
<span *ngIf="enabled" class="text-input-counter">
<span *ngIf="displayMinLength()">{{ minlength }} characters at least required: </span>{{ counter }}<span *ngIf="displayMaxLength()">/{{ maxlength }}</span>
</span>
</div>
The problem is when component is loaded, a css transition is applied to the input, like if the input was "initialized" to the css properties I defined for inputs:
This animation appears when the component <input-counter> is displayed, whereas the only animation which should happens is the border color changes when the input is hovered.
Thanks!
EDIT: the origin of the problem was the plugin codemirror which was loaded with ngIf, and applied under the hood a style to my input (itself loaded from another component!), but with css transitions it did the rendering above, so I display it with [hidden] and all is ok.
You can use angular's animation system to get what you are looking for.
Create an animation trigger for your input-counter component, attach it to whichever tag you need to animate in your template and change the trigger's state when you need the transition to happen.

Overlapping a font awesome icon inside a text field

In an overlapping like the one below, how to prevent the large space between the title and text field?
.icon-link-mail {
position: relative;
left: 485px;
top: 29px;
padding: 8px 8px 7px 8px;
z-index: 2
}
<h3>Title</h3>
<form name="mail_form" id="mail_form" method="POST" action="">
<label for="sendto">
<i class="icon-envelope icon-2x icon-link-mail" style="color:#E4E4E4; text-decoration:none"></i>
<input name="sendto" class="sendto" type="text" style="width: 98%; margin-bottom:10px" placeholder="Send to.." />
</label>
</form>
Result can be seen in this fiddle
Personally I'd just use a pseudo-element, but if you wish to use the <i> icon, then we can do that a lot better by using position:absolute instead of position:relative. Adding position:relative just moves the icon, but leaves the space that it would have taken. position:absolute won't leave that space.
We need to make sure to set the parent contain (label) to position:relative though, so that the icon will be absolutely positioned in relation to the parent instead of the entire page.
#mail_form label {
position: relative;
}
.icon-link-mail {
position: absolute;
z-index: 2;
right: 0;
}
<h3>Title</h3>
<form name="mail_form" id="mail_form" method="POST" action="">
<label for="sendto">
<i class="icon-envelope icon-2x icon-link-mail" style="color:#E4E4E4; text-decoration:none"></i>
<input name="sendto" class="sendto" type="text" style="width: 98%; margin-bottom:10px" placeholder="Send to.." />
</label>
</form>
Result
Fiddle
http://jsfiddle.net/Ay6Hw/4/
I find the best way to do this is to just use an image. Here would be the code:
.search input {
padding-left: 17px;
background: #FFF url("../images/icon_search.png") left no-repeat;
}
.search input:focus {
background:#fff;
}
This will also remove the background image on focus giving the user a better experience overall.
Here is a solution that works with simple CSS and standard font awesome syntax, no need for unicode values, etc.
Create an <input> tag followed by a standard <i> tag with the icon you need.
Use relative positioning together with a higher layer order (z-index) and move the icon over and on top of the input field.
(Optional) You can make the icon active, to perhaps submit the data, via standard JS.
See the three code snippets below for the HTML / CSS / JS.
Or the same in JSFiddle here:
Example: http://jsfiddle.net/ethanpil/ws1g27y3/
$('#filtersubmit').click(function() {
alert('Searching for ' + $('#filter').val());
});
#filtersubmit {
position: relative;
z-index: 1;
left: -25px;
top: 1px;
color: #7B7B7B;
cursor: pointer;
width: 0;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="filter" type="text" placeholder="Search" />
<i id="filtersubmit" class="fa fa-search"></i>

Browse button with input group is cropping on IE9

Using bootstrap, I created input-group with a button and input type='file'.
It is working fine everywhere except IE9. On IE9 the browse button is being cropped from right side.
Demo: http://jsbin.com/alESiBo/6/edit
Code:
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button">
<i class="icon-upload-alt"></i> Upload
</button>
</span>
<input id="fileField" class="form-control" name="fileField" type="file" />
</div>
Output:
IE 9.0.8112.16421
Chrome 31.0.1650.63 m
IE Version with snapshot:
What you are seeing ( the grey part ) is the 'browse..' part of the file upload in IE9. This is 'just the way it is' for the bootstrap css. As other answers have shown, if you do not like this, yeah, just need to have a look into making your own.
Add this in your head tag to prevent further mismatches though...
<meta http-equiv='X-UA-Compatible' content='IE=edge'/>
Most common is to set this control hidden ( I agree it always looks awful and inconsistent ) and 'trigger' it from your own fake button.
Lots of great links from other answers.
Like Rob Sedgwick said in his answer this is just the way the control looks in IE, and styling it is not really allowed.
But… you can cheat: make the file input disappear, and create your own fake input. Then redirect the relevant events using JS.
HTML
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button">
<i class="icon-upload-alt"></i> Upload
</button>
</span>
<input id="fileField" class="form-control" name="fileField" type="file" />
<span class="form-control form-control-overlay" id="fileFieldOverlay">Choose file</span>
</div>
CSS
.form-control[type="file"] {
margin-bottom: -100%;
opacity: 0;
}
.form-control-overlay {
/* style, if you want */
cursor: pointer;
}
Javascript
var fileFieldEl = document.getElementById("fileField");
var fileFieldOverlayEl = document.getElementById("fileFieldOverlay");
// On change of file selection, update display
fileFieldEl.onchange = function(ev) {
// remove file path; it's a fake string for security
fileFieldOverlayEl.innerText = ev.target.value.replace(/^.*(\\|\/)/, '');
};
// Redirect clicks to real file input
fileFieldOverlayEl.onclick = function() {
fileFieldEl.click();
};
Run the code: http://jsbin.com/alESiBo/16/edit
add one more class :
bootstrap.css:3296
.input-group {position: relative; display: table; border-collapse: separate; width: 100%;}
try this may be it will be help you out.
Your code seems to work fine in IE9.
http://fiddle.jshell.net/XCN83/1/show/
So, make sure your compatibility mode is not on. (see red circle in the attached image)
If not, some other css you have is affecting it, use the dev tools inspector to find styles applied to the file input box and it's parents working your way up.
I will suggest to use your own custom CSS to give same look and feel across the browser and same behavior across the browser. I have used similar approach to take care of this issue in my project. Following are same details also link of JSBIN for live demo.
HTML Code:
<!--Import button-->
<div class="fileinput-button import-modal-select-file-btn" title="Import file">
<!--Name of button -->
<span>Upload</span>
<!-- Upload file control-->
<input id="importFileUploadFileId" type="file" name="file" onchange="uploadFile(this);" />
<!-- Any hidden field; Generally needed when upload button is part of form-->
<input type="hidden" name="request" value="value"/>
</div>
CSS Code (Please customize as per your need):
.fileinput-button {
border-radius: 5px;
padding-left: 10px;
padding-right: 10px;
background-color: #e7e9eb;
border: 1px solid #454b59;
font-family: "Gill Sans","Gill Sans MT","Helvetica Neue",Helvetica,Arial,sans-serif;
color: #454b59;
font-weight: lighter;
font-size: 16px;
cursor: pointer;
overflow: hidden;
position: relative !important;
background-image: none;
height: 30px;
outline: none;
height: 28.5px;
line-height: 28.5px;
}
.fileinput-button input {
position: absolute;
top: 0;
right: 0;
margin: 0;
opacity: 0;
filter: alpha(opacity=0);
transform: translate(-300px, 0) scale(4);
font-size: 16px;
direction: ltr;
cursor: pointer;
}
.import-modal-select-file-btn {
width: 50px;
}
Following is live JSBIN link for your reference.
http://jsbin.com/EWIGUrEL/1/edit
Hope it may help.

Resources