Styling The File Upload 'Browse' Button - html

I have an asp.net website which is using Bootstrap and on one page I have a file upload field. Now I know this has been asked may times before but I cant seem to find a solution for asp.net.
Ideally what i'm after is to style the file upload 'Browse' button so it's just a file glyphicon so looking at the Bootstrap site I would like to use something like
What I'm after it looking like (take from Bootstrap website)
<div class="input-group">
<input type="text" class="form-control" placeholder="Username" aria-describedby="basic-addon1">
<span class="input-group-addon" id="basic-addon1">
<i class="glyphicon glyphicon-folder-open"></i>
</span>
</div>
So I would have the input field with the folder icon at the end of it but I can't seem to find a way to do this and was wondering if anyone else could help.
My current code is:
<div class="form-group">
<asp:Label ID="Label3" class="col-md-3 control-label" runat="server" Text="Upload"></asp:Label>
<div class="col-md-3">
<asp:FileUpload ID="fuAttachment" runat="server" class="fileupload"></asp:FileUpload>
</div>
</div>
And my custom CSS is
.fileupload
{
font-family: inherit;
font-size: inherit;
line-height: inherit;
width: 100%;
height: 32px;
pointer-events: none;
}

Jasny Plugin This plugin may help.
/* ===========================================================
* Bootstrap: fileinput.js v3.1.3
* http://jasny.github.com/bootstrap/javascript/#fileinput
* ===========================================================
* Copyright 2012-2014 Arnold Daniels
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ========================================================== */
+ function($) {
"use strict";
var isIE = window.navigator.appName == 'Microsoft Internet Explorer'
// FILEUPLOAD PUBLIC CLASS DEFINITION
// =================================
var Fileinput = function(element, options) {
this.$element = $(element)
this.$input = this.$element.find(':file')
if (this.$input.length === 0) return
this.name = this.$input.attr('name') || options.name
this.$hidden = this.$element.find('input[type=hidden][name="' + this.name + '"]')
if (this.$hidden.length === 0) {
this.$hidden = $('<input type="hidden">').insertBefore(this.$input)
}
this.$preview = this.$element.find('.fileinput-preview')
var height = this.$preview.css('height')
if (this.$preview.css('display') !== 'inline' && height !== '0px' && height !== 'none') {
this.$preview.css('line-height', height)
}
this.original = {
exists: this.$element.hasClass('fileinput-exists'),
preview: this.$preview.html(),
hiddenVal: this.$hidden.val()
}
this.listen()
}
Fileinput.prototype.listen = function() {
this.$input.on('change.bs.fileinput', $.proxy(this.change, this))
$(this.$input[0].form).on('reset.bs.fileinput', $.proxy(this.reset, this))
this.$element.find('[data-trigger="fileinput"]').on('click.bs.fileinput', $.proxy(this.trigger, this))
this.$element.find('[data-dismiss="fileinput"]').on('click.bs.fileinput', $.proxy(this.clear, this))
},
Fileinput.prototype.change = function(e) {
var files = e.target.files === undefined ? (e.target && e.target.value ? [{
name: e.target.value.replace(/^.+\\/, '')
}] : []) : e.target.files
e.stopPropagation()
if (files.length === 0) {
this.clear()
return
}
this.$hidden.val('')
this.$hidden.attr('name', '')
this.$input.attr('name', this.name)
var file = files[0]
if (this.$preview.length > 0 && (typeof file.type !== "undefined" ? file.type.match(/^image\/(gif|png|jpeg)$/) : file.name.match(/\.(gif|png|jpe?g)$/i)) && typeof FileReader !== "undefined") {
var reader = new FileReader()
var preview = this.$preview
var element = this.$element
reader.onload = function(re) {
var $img = $('<img>')
$img[0].src = re.target.result
files[0].result = re.target.result
element.find('.fileinput-filename').text(file.name)
// if parent has max-height, using `(max-)height: 100%` on child doesn't take padding and border into account
if (preview.css('max-height') != 'none') $img.css('max-height', parseInt(preview.css('max-height'), 10) - parseInt(preview.css('padding-top'), 10) - parseInt(preview.css('padding-bottom'), 10) - parseInt(preview.css('border-top'), 10) - parseInt(preview.css('border-bottom'), 10))
preview.html($img)
element.addClass('fileinput-exists').removeClass('fileinput-new')
element.trigger('change.bs.fileinput', files)
}
reader.readAsDataURL(file)
} else {
this.$element.find('.fileinput-filename').text(file.name)
this.$preview.text(file.name)
this.$element.addClass('fileinput-exists').removeClass('fileinput-new')
this.$element.trigger('change.bs.fileinput')
}
},
Fileinput.prototype.clear = function(e) {
if (e) e.preventDefault()
this.$hidden.val('')
this.$hidden.attr('name', this.name)
this.$input.attr('name', '')
//ie8+ doesn't support changing the value of input with type=file so clone instead
if (isIE) {
var inputClone = this.$input.clone(true);
this.$input.after(inputClone);
this.$input.remove();
this.$input = inputClone;
} else {
this.$input.val('')
}
this.$preview.html('')
this.$element.find('.fileinput-filename').text('')
this.$element.addClass('fileinput-new').removeClass('fileinput-exists')
if (e !== undefined) {
this.$input.trigger('change')
this.$element.trigger('clear.bs.fileinput')
}
},
Fileinput.prototype.reset = function() {
this.clear()
this.$hidden.val(this.original.hiddenVal)
this.$preview.html(this.original.preview)
this.$element.find('.fileinput-filename').text('')
if (this.original.exists) this.$element.addClass('fileinput-exists').removeClass('fileinput-new')
else this.$element.addClass('fileinput-new').removeClass('fileinput-exists')
this.$element.trigger('reset.bs.fileinput')
},
Fileinput.prototype.trigger = function(e) {
this.$input.trigger('click')
e.preventDefault()
}
// FILEUPLOAD PLUGIN DEFINITION
// ===========================
var old = $.fn.fileinput
$.fn.fileinput = function(options) {
return this.each(function() {
var $this = $(this),
data = $this.data('bs.fileinput')
if (!data) $this.data('bs.fileinput', (data = new Fileinput(this, options)))
if (typeof options == 'string') data[options]()
})
}
$.fn.fileinput.Constructor = Fileinput
// FILEINPUT NO CONFLICT
// ====================
$.fn.fileinput.noConflict = function() {
$.fn.fileinput = old
return this
}
// FILEUPLOAD DATA-API
// ==================
$(document).on('click.fileinput.data-api', '[data-provides="fileinput"]', function(e) {
var $this = $(this)
if ($this.data('bs.fileinput')) return
$this.fileinput($this.data())
var $target = $(e.target).closest('[data-dismiss="fileinput"],[data-trigger="fileinput"]');
if ($target.length > 0) {
e.preventDefault()
$target.trigger('click.bs.fileinput')
}
})
}(window.jQuery);
.form-group .boot-input {
color: transparent;
}
.form-group .boot-input::-webkit-file-upload-button {
visibility: hidden;
}
.form-group .boot-input::before {
content: "\e204";
font-family: 'Glyphicons Halflings';
color: #444;
display: inline-block;
border: none;
border-radius: 2px;
margin: 0;
padding: 0;
outline: transparent;
white-space: nowrap;
-webkit-user-select: none;
cursor: pointer;
font-weight: 700;
font-size: 10pt;
float: right;
}
/*!
* Jasny Bootstrap v3.1.3 (http://jasny.github.io/bootstrap)
* Copyright 2012-2014 Arnold Daniels
* Licensed under Apache-2.0 (https://github.com/jasny/bootstrap/blob/master/LICENSE)
*/
.container-smooth {
max-width: 1170px;
}
#media (min-width: 1px) {
.container-smooth {
width: auto;
}
}
.btn-labeled {
padding-top: 0;
padding-bottom: 0;
}
.btn-label {
position: relative;
left: -12px;
display: inline-block;
padding: 6px 12px;
background: transparent;
background: rgba(0, 0, 0, .15);
border-radius: 3px 0 0 3px;
}
.btn-label.btn-label-right {
right: -12px;
left: auto;
border-radius: 0 3px 3px 0;
}
.btn-lg .btn-label {
left: -16px;
padding: 10px 16px;
border-radius: 5px 0 0 5px;
}
.btn-lg .btn-label.btn-label-right {
right: -16px;
left: auto;
border-radius: 0 5px 5px 0;
}
.btn-sm .btn-label {
left: -10px;
padding: 5px 10px;
border-radius: 2px 0 0 2px;
}
.btn-sm .btn-label.btn-label-right {
right: -10px;
left: auto;
border-radius: 0 2px 2px 0;
}
.btn-xs .btn-label {
left: -5px;
padding: 1px 5px;
border-radius: 2px 0 0 2px;
}
.btn-xs .btn-label.btn-label-right {
right: -5px;
left: auto;
border-radius: 0 2px 2px 0;
}
.btn-file {
position: relative;
overflow: hidden;
vertical-align: middle;
}
.btn-file > input {
position: absolute;
top: 0;
right: 0;
width: 100%;
height: 100%;
margin: 0;
font-size: 23px;
cursor: pointer;
filter: alpha(opacity=0);
opacity: 0;
direction: ltr;
}
.fileinput {
display: inline-block;
margin-bottom: 9px;
}
.fileinput .form-control {
display: inline-block;
padding-top: 7px;
padding-bottom: 5px;
margin-bottom: 0;
vertical-align: middle;
cursor: text;
}
.fileinput .thumbnail {
display: inline-block;
margin-bottom: 5px;
overflow: hidden;
text-align: center;
vertical-align: middle;
}
.fileinput .thumbnail > img {
max-height: 100%;
}
.fileinput .btn {
vertical-align: middle;
}
.fileinput-exists .fileinput-new,
.fileinput-new .fileinput-exists {
display: none;
}
.fileinput-inline .fileinput-controls {
display: inline;
}
.fileinput-filename {
display: inline-block;
overflow: hidden;
vertical-align: middle;
}
.form-control .fileinput-filename {
vertical-align: bottom;
}
.fileinput.input-group {
display: table;
}
.fileinput.input-group > * {
position: relative;
z-index: 2;
}
.fileinput.input-group > .btn-file {
z-index: 1;
}
.fileinput-new.input-group .btn-file,
.fileinput-new .input-group .btn-file {
border-radius: 0 4px 4px 0;
}
.fileinput-new.input-group .btn-file.btn-xs,
.fileinput-new .input-group .btn-file.btn-xs,
.fileinput-new.input-group .btn-file.btn-sm,
.fileinput-new .input-group .btn-file.btn-sm {
border-radius: 0 3px 3px 0;
}
.fileinput-new.input-group .btn-file.btn-lg,
.fileinput-new .input-group .btn-file.btn-lg {
border-radius: 0 6px 6px 0;
}
.form-group.has-warning .fileinput .fileinput-preview {
color: #8a6d3b;
}
.form-group.has-warning .fileinput .thumbnail {
border-color: #faebcc;
}
.form-group.has-error .fileinput .fileinput-preview {
color: #a94442;
}
.form-group.has-error .fileinput .thumbnail {
border-color: #ebccd1;
}
.form-group.has-success .fileinput .fileinput-preview {
color: #3c763d;
}
.form-group.has-success .fileinput .thumbnail {
border-color: #d6e9c6;
}
.input-group-addon:not(:first-child) {
border-left: 0;
}
/*# sourceMappingURL=jasny-bootstrap.css.map */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<div class="container">
<h3>Jasny Plugin (Extracted)</h3>
<div class="fileinput fileinput-new input-group" data-provides="fileinput">
<div class="form-control" data-trigger="fileinput"><i class="glyphicon glyphicon-file fileinput-exists"></i> <span class="fileinput-filename"></span>
</div> <span class="input-group-addon btn btn-default btn-file"><span class="fileinput-new"><span class="glyphicon glyphicon-level-up"></span></span><span class="fileinput-exists">Change</span>
<input type="file" name="...">
</span> Remove
</div>
<hr>
<h3>Standalone CSS</h3>
<div class="form-group">
<input type="file" class="boot-input form-control" />
</div>
</div>

html
<div class="upload">
<input type="file" name="upload"/>
</div>
css
div.upload {
width: 157px;
height: 57px;
background: #ccc;
overflow: hidden;
}
div.upload input {
display: block;
width: 157px;
height: 57px;
opacity: 0;
overflow: hidden;
}

You can try like this: Demo
Used Bootstrap buttons for styling upload button.
.fileUpload {
position: relative;
overflow: hidden;
margin: 10px;
}
.fileUpload input.upload {
position: absolute;
top: 0;
right: 0;
margin: 0;
padding: 0;
font-size: 20px;
cursor: pointer;
opacity: 0;
filter: alpha(opacity=0);
}

Related

How to push DIVs down when they run out of screen space

When I new books to the library, it generates a new div with the book information, however, when you spam the books, they will run out of screen space but they wont drop down. Just keep spamming the add book, notice how they got shrunk. It can be related to CSS settings. My book DIVs were not lining up horizontally, so I added
#book-list { display: flex; flex-direction:row }
How can I push the DIVs generated when they have no screen space left?
// ############ Selectors ############
const newBtn = document.querySelector('#newBtn');
const addBtn = document.querySelector('#addBtn');
const closeSpan = document.querySelector('.delete');
const display = document.querySelector('.display-lib');
//############ Listeners ############
// pop up the modal
newBtn.addEventListener('click', function () {
popUp.style.display = "block";
})
// closes the form
closeSpan.addEventListener('click', function () {
popUp.style.display = "none";
})
// closes the form when you click anywhere on the window
window.addEventListener('click', function (e) {
if (e.target == popUp) {
popUp.style.display = "none";
}
})
addBtn.addEventListener('click', function(){
const titleBook = document.querySelector('#title').value;
const authorBook = document.querySelector('#author').value;
const pagesBook = document.querySelector('#pages').value;
const notesBook = document.querySelector('#notes').value;
const readBook = document.querySelector('#read').checked;
if (titleBook === "" || authorBook === "" || pagesBook === "" || notesBook === "") {
showAlert("Please fill in all the blanks", 'error');
} else {
book = new Book(titleBook, authorBook, pagesBook, notesBook, readBook);
myLibrary.push(book);
displayBook(book);
showAlert("book is added", 'success');
}
event.preventDefault();
});
let myLibrary = [];
function Book(title, author, pages, notes, read) {
this.title = title;
this.author = author;
this.pages = pages;
this.notes = notes;
this.read = read;
}
function addBookToLibrary() {
const titleBook = document.querySelector('#title').value;
const authorBook = document.querySelector('#author').value;
const pagesBook = document.querySelector('#pages').value;
const notesBook = document.querySelector('#notes').value;
const readBook = document.querySelector('#read').checked;
if(titleBook === "" && authorBook === "" && pagesBook === "" && notesBook === ""){
showAlert("Please fill in all the blanks", 'success');
} else {
book = new Book(titleBook, authorBook, pagesBook, notesBook, readBook);
myLibrary.push(book);
displayBook(book);
showAlert("book is added", 'success');
}
event.preventDefault();
}
function displayBook(book) {
const shelf = document.querySelector('#book-list');
const books = document.createElement('div');
const row = document.createElement('tr');
const makeTitle = document.createElement('p');
const makeAuthor = document.createElement('p');
const makePages = document.createElement('p');
const makeNotes = document.createElement('p');
const deleteBtn = document.createElement('button');
const readBox = document.createElement('checkbox');
books.classList.add('book');
makeTitle.classList.add("title");
makeAuthor.classList.add("author");
makePages.classList.add("pages");
makeNotes.classList.add("notes");
deleteBtn.classList.add("delete");
readBox.classList.add("switch");
makeTitle.innerHTML = `Title: ${book.title}`;
makeAuthor.innerHTML = `Author: ${book.author}`;
makePages.innerHTML = `Pages: ${book.pages}`;
makeNotes.innerHTML = `Notes: ${book.notes}`;
readBox.innerHTML = `Read: ${book.read}`;
row.appendChild(makeTitle);
row.appendChild(makeAuthor);
row.appendChild(makePages);
row.appendChild(makeNotes);
row.appendChild(deleteBtn);
row.appendChild(readBox);
shelf.appendChild(books);
books.appendChild(row);
const dltBtn = books.querySelector('.delete');
dltBtn.addEventListener('click', function (e) {
deleteBook(e.target);
showAlertDelete('book removed', 'success');
})
}
// ######### ALERTS FOR THE UI ###########
function showAlert(message, className) {
const div = document.createElement('div');
div.className = `alert ${className}`;
div.appendChild(document.createTextNode(message));
const form = document.querySelector('#form');
form.appendChild(div);
setTimeout(function () {
document.querySelector('.alert').remove();
}, 3000);
}
function showAlertDelete(message, className) {
const div = document.createElement('div');
div.className = `alert ${className}`;
div.appendChild(document.createTextNode(message));
const form = document.querySelector('.content');
form.appendChild(div);
setTimeout(function () {
document.querySelector('.alert').remove();
}, 3000);
}
// function that deletes the book. aims at parentElements
function deleteBook(target) {
if (target.className === 'delete') {
target.parentElement.parentElement.remove();
}
}
h1 {
display: flex;
justify-content: center;
}
.title {
display: flex;
justify-content: center;
padding-top: 4rem;
}
p {
display: flex;
justify-content: center;
padding-top: 1rem;
}
body {
background-color: #41b3a3;
}
.success,
.error {
color: white;
padding: 5px;
border-radius: 3px;
}
.error {
background: rgb(190, 0, 0);
}
.success {
background: green;
margin: auto;
}
/* Modal popup box https://www.w3schools.com/howto/howto_css_modals.asp */
/* The Modal (background) */
input#title {
height: 30px;
width: 200px;
font-size: 20px;
}
input#author {
height: 30px;
width: 200px;
font-size: 20px;
}
input#pages {
height: 30px;
width: 200px;
font-size: 20px;
margin-bottom: 20px;
}
input[type=checkbox] {
transform: scale(2);
}
#popUp {
display: none;
/* Hidden by default */
position: fixed;
/* Stay in place */
z-index: 1;
/* Sit on top */
left: 0;
top: 0;
width: 100%;
/* Full width */
height: 100%;
/* Full height */
overflow: auto;
/* Enable scroll if needed */
background-color: rgb(0, 0, 0);
/* Fallback color */
background-color: rgba(0, 0, 0, 0.4);
/* Black w/ opacity */
font-size: 30px;
}
/* Modal Content/Box */
#form {
margin: 15% auto;
/* 15% from the top and centered */
padding: 20px;
width: 20%;
/* Could be more or less, depending on screen size */
}
/* The Close Button */
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
.mark_as_read {
display: inline-block;
vertical-align: middle;
justify-content: center;
}
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
vertical-align: middle;
justify-content: center;
margin: auto;
width: 60px;
height: 34px;
}
/* Hide default HTML checkbox */
.switch input {
opacity: 0;
width: 0;
height: 0;
}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked+.slider {
background-color: #41b3a3;
}
input:focus+.slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked+.slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
#switch_container {
display: flex;
justify-content: center;
}
/* Styles for the added book */
.book{
display:flex;
align-items: center;
padding: 15px;
margin: 20px;
background-color: #83d898;
border-radius: 20px;
}
.title {
font-size: 30px;
font-weight: bold;
margin-bottom: 20px;
}
.author {
font-size: 30px;
margin-bottom: 20px;
}
.pages {
font-size: 25px;
margin-bottom: 20px;
}
.notes {
font-size: 25px;
margin-bottom: 20px;
}
#book-list {
display: flex;
flex-direction: row;
}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma#0.9.2/css/bulma.min.css">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
<title>Library</title>
</head>
<body>
<div class="content">
<h1 class="title">A Book Library</h1>
<p>A library project where you can store your books, coded for the Odin Project</p>
<div id="addBtn_container" class="has-text-centered">
<a id="newBtn" class="button is-primary is-inverted">Add a New Book</a>
</div>
<div id="popUp" >
<form id='form'>
<header class="modal-card-head">
<p class="modal-card-title">New Book</p>
<span class="delete" id="close" aria-label="close"></span>
</header>
<section class="modal-card-body">
<div id='textInput'>
<p><input type='text' id='title' name='title' placeholder='Title'></p>
<p><input type='text' id='author' name='author' placeholder='Author'></p>
<p><input type='text' id='pages' name='pages' placeholder='Pages'></p>
</div>
<p class="modal-card-title">Notes</p>
<textarea id='notes' class="textarea" placeholder="Notes"></textarea>
</section>
<footer class="modal-card-foot">
<span class="mark_as_read">Mark as read: </span>
<label class="switch">
<input type="checkbox" value="yes" id='read' name='read'>
<span class="slider round"></span>
</label>
<button class="button is-success is-rounded is-pulled-right" type='submit' form='form'
id='addBtn'>Add</button></div>
</footer>
</form>
</div>
</div>
<h1>MY BOOKS</h1>
<div class="display-lib">
<table>
<tbody id="book-list">
</tbody>
</table>
</div>
</tbody>
<script src="app.js"></script>
</body>
</html>
It is happening because you put the div into a table and it is not well formed. A table has to have <tr> and <td> to make the row and the cell, but the thing I recommend you is to get rid of <table> and <tbody>. Flex should be enough. Or if you need a two directions layout you could try grid instead. It is the new way to display things in a 'table way'.
You can make different things. Two of them are: removing <table> and <tbody> tags and changing them to just one <div> (with 100% width) or to make a well formed table with <tr>and <td> and checking the whole table width is your desired (100%).

Carrying specific body class onto every page | Wordpress

I have the following code, when the user presses the 'x' I want to make sure it doesnt pop up again, how would I copy the body class 'demoBookedHidden' to any future page the user goes to?
Currently the code works for the one page the user visits but the body class doesn't carry across to another page.
$(".demoBookedContentClose").click(function(){
$("body").addClass("demoBookedHidden");
});
function shuffle(array) {
var currentIndex = array.length,
temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
var queue = [];
function setUp() {
var elems = $(".demoBooked").get();
queue = shuffle(elems);
showNext();
}
function showNext() {
var elem = queue.pop();
if (elem) {
$(elem)
.fadeIn(2000)
.delay(5000)
.fadeOut(1000, function(){ setTimeout(showNext,25000); });
} else {
setUp();
}
}
setUp();
.demoBooked {
background: #fff;
box-shadow: 0 1px 2px rgba(0,0,0,0.05), 0 2px 4px rgba(0,0,0,0.08);
border: 1px solid #dddddd;
padding: 20px;
border-radius: 8px;
display: none;
}
.demo-booked-section {
position: fixed;
bottom: 10px;
left: 10px;
z-index: 2;
}
.demoBooked h3 {
font-size: 22px;
font-weight: 900;
margin-bottom: 4px;
}
.demoBooked img {
max-width: 50px;
margin-top: -55px;
border-radius: 100%;
display: inline-block;
}
.demoBookedContent {
display: inline-block;
padding-left: 20px;
}
.demoBooked p {
font-size: 18px;
line-height: 20px;
}
.demoBookedTime {
color: #e12826;
}
.demoBookedContentClose {
position: absolute;
right: 15px;
top: 10px;
font-size: 10px;
cursor: pointer;
}
.demoBookedHidden .demo-booked-section {
display: none!important;
}
#media only screen and (max-width: 768px) {
.demo-booked-section {
display: none!important;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="demo-booked-section">
<div class="demoBooked">
<img src="/wp-content/uploads/2021/01/william-diaz.jpg">
<div class="demoBookedContent">
<span class="demoBookedContentClose">X</span>
<h3>William Diaz</h3>
<p class="demoBookedText">Booked in his free trial</p>
<p class="demoBookedTime">1hrs ago</p>
</div>
</div>
<div class="demoBooked">
<img src="/wp-content/uploads/2021/01/freya-smith.jpg">
<div class="demoBookedContent">
<span class="demoBookedContentClose">X</span>
<h3>Freya Smith</h3>
<p class="demoBookedText">Booked in her free trial</p>
<p class="demoBookedTime">3hrs ago</p>
</div>
</div>
<div class="demoBooked">
<img src="/wp-content/uploads/2021/01/mia-fleming.jpg">
<div class="demoBookedContent">
<span class="demoBookedContentClose">X</span>
<h3>Mia Fleming</h3>
<p class="demoBookedText">Booked in her free trial</p>
<p class="demoBookedTime">2hrs ago</p>
</div>
</div>
</div>
You can use sessionStorage to let the browser know if it has already shown the popup.
For more info check out this answer

Why can't I type or click into textarea?

I'm new to HTML and CSS, and I have some problems that I can't fix by myself.
My problem is that I can't type into my textarea, when I click on it nothing happens, also, I tried to put text ( "New Paste" ) above that, and I cant see it.
There is already questions on Stackoverflow about the textarea problem, but it didnt match to my problem.
How can I change my textarea position to be under the "New Paste" text ?
How can I fix my problem with textarea and write to it ?
function saveTextAsFile() {
var textToWrite = document.getElementById('textArea1').innerHTML;
var textFileAsBlob = new Blob([textToWrite], {
type: 'text/plain'
});
var fileNameToSaveAs = "MakePython.py";
var downloadLink = document.createElement("a");
downloadLink.download = fileNameToSaveAs;
downloadLink.innerHTML = "Download File";
if (window.webkitURL != null) {
// Chrome allows the link to be clicked without actually adding it to the DOM.
downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
} else {
// Firefox requires the link to be added to the DOM before it can be clicked.
downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
downloadLink.onclick = destroyClickedElement;
downloadLink.style.display = "none";
document.body.appendChild(downloadLink);
}
downloadLink.click();
}
var button = document.getElementById('SaveFile');
button.addEventListener('click', saveTextAsFile);
function destroyClickedElement(event) {
// remove the link from the DOM
document.body.removeChild(event.target);
}
body {
background-color: lightslategray
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
position: fixed;
top: 0px;
width: 100%;
}
li {
float: left;
}
.text {
display: block;
color: white;
text-align: center;
padding: 16px 18px;
background-color: teal;
text-decoration: none;
}
li a:hover {
background-color: black;
}
#textAreaOne {
display: block;
margin-left: auto;
margin-right: auto;
resize: none;
width: 950px;
height: 750px;
}
#SaveFile {
background-color: #4CAF50;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin-left: auto;
margin-right: auto;
display: block;
}
#SaveFile:hover {
box-shadow: 0 12px 16px 0 rgba(0, 0, 0, 0.24), 0 17px 50px 0 rgba(0, 0, 0, 0.19);
}
<ul>
<li><a class="text" href="">Home</a></li>
<li><a class="text" href="">About</a></li>
<li><a class="text" href="">Contact</a></li>
</ul>
<p style="color: black;"><b>New Paste</b></p>
<textarea id="textAreaOne"></textarea>
<button id="SaveFile" type="button" value="Save File">Save</button>
Changing the position: fixed to sticky fixes your 'New Paste' problem.
function saveTextAsFile() {
var textToWrite = document.getElementById('textArea1').innerHTML;
var textFileAsBlob = new Blob([textToWrite], {
type: 'text/plain'
});
var fileNameToSaveAs = "MakePython.py";
var downloadLink = document.createElement("a");
downloadLink.download = fileNameToSaveAs;
downloadLink.innerHTML = "Download File";
if (window.webkitURL != null) {
// Chrome allows the link to be clicked without actually adding it to the DOM.
downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
} else {
// Firefox requires the link to be added to the DOM before it can be clicked.
downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
downloadLink.onclick = destroyClickedElement;
downloadLink.style.display = "none";
document.body.appendChild(downloadLink);
}
downloadLink.click();
}
var button = document.getElementById('SaveFile');
button.addEventListener('click', saveTextAsFile);
function destroyClickedElement(event) {
// remove the link from the DOM
document.body.removeChild(event.target);
}
body {
background-color: lightslategray;
margin: 0;
padding: 0;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
position: sticky;
top: 0px;
width: 100%;
}
li {
float: left;
}
.text {
display: block;
color: white;
text-align: center;
padding: 16px 18px;
background-color: teal;
text-decoration: none;
}
li a:hover {
background-color: black;
}
#textAreaOne {
display: block;
margin-left: auto;
margin-right: auto;
resize: none;
width: 950px;
height: 750px;
}
#SaveFile {
background-color: #4CAF50;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin-left: auto;
margin-right: auto;
display: block;
}
#SaveFile:hover {
box-shadow: 0 12px 16px 0 rgba(0, 0, 0, 0.24), 0 17px 50px 0 rgba(0, 0, 0, 0.19);
}
<ul>
<li><a class="text" href="">Home</a></li>
<li><a class="text" href="">About</a></li>
<li><a class="text" href="">Contact</a></li>
</ul>
<p style="color: black;"><b>New Paste</b></p>
<textarea id="textAreaOne"></textarea>
<button id="SaveFile" type="button" value="Save File">Save</button>
Like I said, your textarea just works fine.
Your textArea id textAreaOne but you select the textArea1
var textToWrite = document.getElementById('textArea1').innerHTML;
<textarea id="textAreaOne"></textarea>
That's why when you click button nothing happens. To fix this handle true id
Also i would like say something about your HTML
Give an static height your header which is ul in this example
Use HTML5 tags like <header>, <section>
Then let margin on top the section because your header is position absolute or fixed, so this is not effect to relative height.
For example:
<head>
<style type="text/css">
header {
position: absolute;
height: 50px;
width: 100%;
top: 0;
}
section {
position: relative;
margin-top: 100px;
}
</style>
</head>
<body>
<header>
...blabla
</header>
<section>
...blabla
</section>
</body>```

Checkbox need two clicks to uncheck?

My checkboxes need 2 clicks to be unchecked.
I have the issue in all 7 checkboxes.
To check the boxes, one click is enough.
I have no onchange() function or something in TS.
.............................................................................................................................................................
import { Component, OnInit, Inject } from '#angular/core';
import { PHPAPIService } from '../../php-api.service';
import * as socketIO from 'socket.io-client';
import {MatTableModule} from '#angular/material/table';
import * as $ from 'jquery';
import { ToastrService } from 'ngx-toastr';
import {MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '#angular/material';
export interface DialogData {
name: string;
}
#Component({
selector: 'app-module',
templateUrl: './module.component.html',
styleUrls: ['./module.component.css'],
providers: [PHPAPIService]
})
export class ModuleComponent implements OnInit {
toastChanges = 0;
xForToastMSG = 1;
moduleTimer = [];
fileToUpload: File = null;
moduleExpandState = [];
constructor(public PHPAPIService:PHPAPIService, private toastrService: ToastrService, public dialog: MatDialog) {
}
ngOnInit() {
for(var i=0;i<1000;i++)
this.moduleExpandState[i] = false;
this.PHPAPIService.get("tprofile").subscribe(
(data) => this.PHPAPIService.profiles = data
);
this.PHPAPIService.get("ttimer").subscribe(
(data) => this.PHPAPIService.timers = data
);
this.PHPAPIService.get("tmodule").subscribe(
(data) => this.PHPAPIService.modules = data
);
const socket = socketIO(this.PHPAPIService.apiUrl);
socket.on('tmodule', (snapshot) => this.PHPAPIService.modules = snapshot);
socket.on('timeUpdate', (snapshot) => this.PHPAPIService.date = snapshot);
setTimeout(()=>{
for(var i=0; i< this.PHPAPIService.modules.length ;i++){
/*Konvertiert die einelenen Daten HH und MM in ein String HH:MM*/
this.moduleTimer[i] = this.PHPAPIService.modules[i].time_h + ":" + this.PHPAPIService.modules[i].time_m;
//console.log(this.localTimerVar[i].on);
}
},1200);
//socket.on('tmodule', () => this.showSuccess());
}
/* showSuccess(text) {
/* if(this.xForToastMSG == 1){
this.xForToastMSG = 0;*/
// this.toastrService.success(text,'',{
// positionClass: 'toast-bottom-right'
// });
/* this.toastChanges = 1;*/
// }
/* setTimeout(()=>{
this.toastChanges = 0;
this.xForToastMSG = 1;
},500);*/
//}*/
showWarning(text) {
this.toastrService.warning(text,'',{
positionClass: 'toast-bottom-right'
});
}
/* showDownload() {
this.toastrService.success('Datensicherung wird erstellt','',{
positionClass: 'toast-bottom-right'
});
}*/
/*NUR FÜR MEHERERE FILES*/
/*handleFileInput(files: FileList) {
// console.log("TEST");
this.fileToUpload = files.item(0);
this.uploadFileToActivity();
}
*/
uploadFileToActivity(files: FileList) {
this.fileToUpload = files.item(0);
console.log(files.item(0));
if(files.item(0).name.substring(0,6) === 'module'){
this.PHPAPIService.uploadBackupModule(files.item(0)).subscribe(data => {
// do something, if upload success
this.showSuccess('Import erfolgreich!');
console.log(data);
}, error => {
console.log(error);
});
}else{
this.showWarning('fehlerhafte Datei');
}
}
backupModule(m_id, m_name){
this.showSuccess('Datensicherung wird erstellt');
this.PHPAPIService.backupModule(m_id, m_name).subscribe(response => this.downLoadFile(response.text(), "application/plain", m_name));
}
downLoadFile(data: any, type: string, name) {
var blob = new Blob([data], { type: type});
var url = window.URL.createObjectURL(blob);
// var pwa = window.open(url);
var anchor = document.createElement("a");
anchor.setAttribute("type", "hidden"); // make it hidden if needed
anchor.download = "module_"+name+".sql";
anchor.href = url;
document.body.appendChild(anchor);
anchor.click();
anchor.remove();
/*if (!pwa || pwa.closed || typeof pwa.closed == 'undefined') {
alert( 'Please disable your Pop-up blocker and try again.');
}*/
}
showSuccessNoChanges() {
this.toastrService.warning('keine Änderungen','',{
positionClass: 'toast-bottom-right'
});
}
showSuccess(x){
console.log(this.PHPAPIService.modules[x].time_h);
if(this.PHPAPIService.modules[x].time_h != '' && this.PHPAPIService.modules[x].time_m != ''){
this.toastrService.success('Änderung gespeichert','',{
positionClass: 'toast-bottom-right'
});
}else{
this.toastrService.error('Bitte Zeit eintragen','',{
positionClass: 'toast-bottom-right'
});
}
if(x == "zeit verfügbar"){
this.toastrService.error('Zeit bereits verfügbar','Die eingetragene Zeit ist bereits in einem andern Modul verfügbar, bitte eine andere Uhrzeit eintragen.',{
positionClass: 'toast-bottom-right'
});
}
}
togglePanel(x){
this.moduleExpandState[x] = !this.moduleExpandState[x];
$('#nameInput-'+x+' ').toggleClass('inputEdit');
}
saveModule(mID, x){
if(this.PHPAPIService.modules[x]['0'] == false) this.PHPAPIService.modules[x]['0'] = "";
if(this.PHPAPIService.modules[x]['1'] == false) this.PHPAPIService.modules[x]['1'] = "";
if(this.PHPAPIService.modules[x]['2'] == false) this.PHPAPIService.modules[x]['2'] = "";
if(this.PHPAPIService.modules[x]['3'] == false) this.PHPAPIService.modules[x]['3'] = "";
if(this.PHPAPIService.modules[x]['4'] == false) this.PHPAPIService.modules[x]['4'] = "";
if(this.PHPAPIService.modules[x]['5'] == false) this.PHPAPIService.modules[x]['5'] = "";
if(this.PHPAPIService.modules[x]['6'] == false) this.PHPAPIService.modules[x]['6'] = "";
if(this.PHPAPIService.modules[x]['0'] == true) this.PHPAPIService.modules[x]['0'] = "checked";
if(this.PHPAPIService.modules[x]['1'] == true) this.PHPAPIService.modules[x]['1'] = "checked";
if(this.PHPAPIService.modules[x]['2'] == true) this.PHPAPIService.modules[x]['2'] = "checked";
if(this.PHPAPIService.modules[x]['3'] == true) this.PHPAPIService.modules[x]['3'] = "checked";
if(this.PHPAPIService.modules[x]['4'] == true) this.PHPAPIService.modules[x]['4'] = "checked";
if(this.PHPAPIService.modules[x]['5'] == true) this.PHPAPIService.modules[x]['5'] = "checked";
if(this.PHPAPIService.modules[x]['6'] == true) this.PHPAPIService.modules[x]['6'] = "checked";
/*checke ob gleiche Uhrzeiten verfügbar sind*/
/*for(var i = 0; i < this.PHPAPIService.modules.length+1; i++){
console.log(this.moduleTimer[x]);
console.log(this.PHPAPIService.modules[x].time_h+":"+this.PHPAPIService.modules[x].time_m);
if(this.PHPAPIService.modules[i].time_h+":"+this.PHPAPIService.modules[i].time_m == this.moduleTimer[x]){
this.showSuccess("zeit verfügbar");
return null;
}
}*/
/*Konvertiert den 19:45 String in 19 und 45*/
//console.log(this.PHPAPIService.modules[x]);
if(this.PHPAPIService.modules[x].m_active == false){
this.PHPAPIService.modules[x].m_active = "";
}
if(this.PHPAPIService.modules[x].m_active == true){
this.PHPAPIService.modules[x].m_active = "checked";
// this.PHPAPIService.saveModule(mID, this.PHPAPIService.modules[x]).subscribe();
}
if(this.moduleTimer[x] != ''){
this.PHPAPIService.modules[x].time_h = this.moduleTimer[x].split(":")[0];
this.PHPAPIService.modules[x].time_m = this.moduleTimer[x].split(":")[1];
}
if(this.PHPAPIService.modules[x].time_h != '' && this.PHPAPIService.modules[x].time_m != ''){
this.PHPAPIService.saveModule(mID, this.PHPAPIService.modules[x]).subscribe();
}
setTimeout(()=>{
// if(this.toastChanges != 1){
this.showSuccess(x);
// };
},200);
}
deleteModule(mID, x){
const dialogRef = this.dialog.open(DialogOverviewModule, {
width: '250px',
data: {name: this.PHPAPIService.modules[x].m_name}
});
dialogRef.afterClosed().subscribe(result => {
console.log(result);
if(result == true){
this.PHPAPIService.deleteModule(mID).subscribe();
}
});
//this.PHPAPIService.deleteModule(mID).subscribe();
// this.PHPAPIService.profiles[x] = null;
}
addModule(){
this.PHPAPIService.addModule().subscribe();
for(var i=0;i<1000;i++)
this.moduleExpandState[i] = false;
// this.PHPAPIService.profiles[x] = null;
}
}
#Component({
selector: 'dialog-overview-example-dialog',
templateUrl: 'dialog-overview-example-dialog.html',
})
export class DialogOverviewModule {
constructor(
public dialogRef: MatDialogRef<DialogOverviewModule>,
#Inject(MAT_DIALOG_DATA) public data: DialogData) {}
save = true;
onNoClick(): void {
this.dialogRef.close();
}
}
h1{
display: block;
margin: 0;
padding: 20px;
padding-left: 220px;
}
h4{
margin: auto 0px;
padding: 0;
font-weight: 200;
padding-right: 50px;
}
h2{
margin: 10px;
font-weight: 100;
}
header{
display: flex;
flex-direction: row;
justify-content: space-between;
margin: 0;
margin-left:200px;
padding-left: 20px;
padding-right: 20px;
background-color: #323741;
color: #D7E2F7;
}
input[type="file"] + label {
margin: 0;
padding: 0;
}
/*input[type="file"]:focus + label,
input[type="file"] + label:hover {
background-color: red;
}*/
input[type="file"]{
float: right;
margin: 20px;
width: 0.1px;
height: 0.1px;
opacity: 0;
overflow: hidden;
position: absolute;
z-index: -1;
}
.modSelect, .modSelect option{
font-size: 1.2em;
width: 250px !important;
}
input{
height: 30px;
outline: none;
border: none;
background: transparent;
font-size: 1.2em;
}
input:focus{
background: white;
outline: none;
border: solid 1px black;
}
input[type="checkbox"]{
margin: auto 0px;
margin-left: 10px;
width: 18px;
}
/deep/ .mat-expansion-panel-header{
padding-top: 10px !important;
padding-bottom: 10px !important;
margin-left:200px;
}
.row_expansion_column{
display: flex;
flex-wrap: nowrap;
flex-direction: row;
justify-content: center;
align-items: center;
flex-grow: 0;
text-align: center;
margin-left:200px;
}
.row_expansion_column select{
margin: 10px;
width: 100px;
}
.delBtn{
background-color: #ed1212;
border: 1px solid #ed1212;
font-size: 1.2em;
color: white;
}
.saveBtn{
background-color: green;
border: 1px solid green;
font-size: 1.2em;
color: white;
}
.exportBtn{
background-color: #707070FF;
border: 1px solid #707070FF;
font-size: 1.2em;
color: white;
}
.addBtn{
background-color: #707070FF;
border: 1px solid #707070FF;
float: right;
margin: 20px;
padding: 0 10px;
font-size: 1.2em;
color : white;
}
.importBtn{
background-color: #707070FF;
border: 1px solid #707070FF;
float: right;
margin: 20px;
padding: 0;
font-size: 1.2em;
color : white;
}
.fileBtn{
background-color: #707070FF;
border: 1px solid #707070FF;
float: right;
padding: 0px 20px;
font-size: 1em;
color : white;
line-height: 34px;
cursor: pointer;
}
.editBtn{
margin: 0 0 0 auto;
//background-color: #DADADAFF;
border: 1px solid #707070FF;
color : #707070FF;
padding: 2px 10px 2px 10px;
font-size: 1.2em;
}
input[type="text"]{
outline: none;
border: none;
background: transparent;
height: 30px;
font-size: 1.2em;
pointer-events: none;
}
input[type="text"]:hover{
cursor: default;
pointer-events: none;
}
input[type="text"].inputEdit:hover{
pointer-events: auto;
outline: none;
cursor: text;
border: 1px solid #707070FF;
}
input[type="text"].inputEdit{
background: white;
pointer-events: auto;
outline: none;
cursor: text;
border: 1px solid #707070FF;
}
img{
width: 120px;
position: absolute;
right: 20px;
bottom: 20px;
}
/deep/ .mat-slide-toggle.mat-warn.mat-checked:not(.mat-disabled) .mat-slide-toggle-thumb {
background-color: blue;
float: right;
}
/deep/ .mat-slide-toggle.mat-warn.mat-checked:not(.mat-disabled) .mat-slide-toggle-bar {
background-color: rgba(124, 172, 249,.5);
float: right;
}
/deep/ .mat-slide-toggle{
position: relative;
top: 15px;
padding-right: 10px;
margin-left: 20px;
}
/deep/ .mat-slide-toggle-bar {
height: 15px !important;
width: 40px !important;
}
/deep/ .mat-slide-toggle-thumb {
height: 25px !important;
width: 25px !important;
background-color: #ececec;
margin-left: -2px;
margin-top: -2px;
}
/deep/ .mat-slide-toggle.mat-checked .mat-slide-toggle-thumb-container {
transform: translate3d(23px,0,0) !important;
}
.seperateContainer{
padding-left: 20px;
display: inherit;
background-color: #f5f5f5;
}
#modAct{
margin-left: 20px;
}
#media only screen and (max-width: 600px) {
header h2{
padding-left: 20px;
}
.row_expansion_column{
margin-left:0px;
}
/deep/ .mat-expansion-panel-header{
margin-left:0px;
}
header{
margin-left:0px;
}
}
<header>
<h2>Module</h2>
<h4 [(ngModel)]="PHPAPIService.date" ngDefaultControl>
{{PHPAPIService.date | date:'HH:mm:ss dd.MM.yyyy'}}
</h4>
</header>
<mat-expansion-panel *ngFor="let module of PHPAPIService.modules; let x = index" [expanded]="moduleExpandState[module.m_id]"
[disabled]="true">
<mat-expansion-panel-header>
<input type="text" name="" id="{{ 'nameInput-' + module.m_id }}" placeholder="Bezeichnung"
required [(ngModel)]="module.m_name" [value]="module.m_name"/>
<button mat-button class="editBtn" (click)="togglePanel(module.m_id)">Bearbeiten</button>
</mat-expansion-panel-header>
<div class="row_expansion">
<div class=row_expansion_column>
<h3>Profil</h3>
<select class="modSelect" required [(ngModel)]="module.m_profile">
<option [value]="profile.profileID" *ngFor="let profile of PHPAPIService.profiles">{{profile.Name}}</option>
</select>
<h3>schaltetzeit</h3>
<input type="time" name="" required [(ngModel)]="moduleTimer[x]" value="{{module.time_h}}:{{module.time_m}}"/>
<div class="seperateContainer">
<div class="dayCheckBox"><h3>MO</h3>
<input type="checkbox" required [(ngModel)]="module['1']" checked="{{module['1']}}"/> <!-- timer.1 funktiniert nicht, DB hat leider 0 - 7 als spalten -->
</div>
<div class="dayCheckBox"><h3>DI</h3>
<input type="checkbox" required [(ngModel)]="module['2']" checked="{{module['2']}}"/></div>
<div class="dayCheckBox"><h3>MI</h3>
<input type="checkbox" required [(ngModel)]="module['3']" checked="{{module['3']}}"/></div>
<div class="dayCheckBox"><h3>DO</h3>
<input type="checkbox" required [(ngModel)]="module['4']" checked="{{module['4']}}"/></div>
<div class="dayCheckBox"><h3>FR</h3>
<input type="checkbox" required [(ngModel)]="module['5']" checked="{{module['5']}}"/></div>
<div class="dayCheckBox"><h3>SA</h3>
<input type="checkbox" required [(ngModel)]="module['6']" checked="{{module['6']}}"/></div>
<div class="dayCheckBox"><h3>SO</h3>
<input type="checkbox" required [(ngModel)]="module['0']" checked="{{module['0']}}"/></div>
</div>
<h3 id="modAct">Active</h3>
<mat-slide-toggle [(ngModel)]="module.m_active" color="warn"
[checked]="module.m_active"></mat-slide-toggle>
</div>
</div>
<mat-action-row>
<button mat-button class="exportBtn" (click)="backupModule(module.m_id, module.m_name)">Export</button>
<button mat-button class="delBtn" (click)="deleteModule(module.m_id, x)">Löschen</button>
<button mat-button class="saveBtn" (click)="saveModule(module.m_id, x)">Speichern</button>
</mat-action-row>
</mat-expansion-panel>
<button mat-button class="addBtn" (click)="addModule()">neues Modul erstellen</button>
<!-- <div class="form-group"> -->
<!-- <button mat-button class="fileBtn"> <label for="file">Datei auswählen</label></button> -->
<input type="file"
class="inputfile"
enctype="multipart/form-data"
id="file"
name="filetoupload"
(change)="uploadFileToActivity($event.target.files)" >
<button mat-button class="importBtn" ><label for="file"class="fileBtn">Import</label></button>
<!-- <label for="file"class="fileBtn">Import</label> -->
<!-- </div> -->
You don't need checked="{{module['1']}}", data binding is handling that. So please remove below code from your check boxes and it would work.
checked="{{module['1']}}" //Remove this
Let me know if you need full code, I can share.
Check running code at below repository.
https://stackblitz.com/github/nitin1982/StackOverFlowProblems/tree/master/CheckBoxIssue?file=src%2Fapp%2Fapp.component.html

Customizing Increment Arrows on Input of Type Number Using CSS

I have an input of type number that is rendered using the following code:
<input class="quantity" id="id_form-0-quantity" min="0" name="form-0-quantity" value="1" type="number">
It looks like this:
I would like to turn it into something like this:
The second view is emulated using two separate buttons.
How could I style the arrows as described?
tl;dr:
Having been asked in private about the following setup quite a few times, I decided to add a demo for it (Bootstrap 4 + jQuery + Font Awesome input-group setup):
$('.btn-plus, .btn-minus').on('click', function(e) {
const isNegative = $(e.target).closest('.btn-minus').is('.btn-minus');
const input = $(e.target).closest('.input-group').find('input');
if (input.is('input')) {
input[0][isNegative ? 'stepDown' : 'stepUp']()
}
})
.inline-group {
max-width: 9rem;
padding: .5rem;
}
.inline-group .form-control {
text-align: right;
}
.form-control[type="number"]::-webkit-inner-spin-button,
.form-control[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.0/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
<div class="input-group inline-group">
<div class="input-group-prepend">
<button class="btn btn-outline-secondary btn-minus">
<i class="fa fa-minus"></i>
</button>
</div>
<input class="form-control quantity" min="0" name="quantity" value="1" type="number">
<div class="input-group-append">
<button class="btn btn-outline-secondary btn-plus">
<i class="fa fa-plus"></i>
</button>
</div>
</div>
long (initial) answer:
The native input[type=number] controls are not style-able cross-browser. The easiest and safest way to achieve what you want cross-browser/cross-device is to hide them using:
input[type="number"] {
-webkit-appearance: textfield;
-moz-appearance: textfield;
appearance: textfield;
}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
}
...which allows you to use your custom buttons, which could be linked to execute the functions the spinners (arrows) would (.stepUp() and .stepDown()), provided you keep the input's type="number".
For example:
input[type="number"] {
-webkit-appearance: textfield;
-moz-appearance: textfield;
appearance: textfield;
}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
}
.number-input {
border: 2px solid #ddd;
display: inline-flex;
}
.number-input,
.number-input * {
box-sizing: border-box;
}
.number-input button {
outline:none;
-webkit-appearance: none;
background-color: transparent;
border: none;
align-items: center;
justify-content: center;
width: 3rem;
height: 3rem;
cursor: pointer;
margin: 0;
position: relative;
}
.number-input button:before,
.number-input button:after {
display: inline-block;
position: absolute;
content: '';
width: 1rem;
height: 2px;
background-color: #212121;
transform: translate(-50%, -50%);
}
.number-input button.plus:after {
transform: translate(-50%, -50%) rotate(90deg);
}
.number-input input[type=number] {
font-family: sans-serif;
max-width: 5rem;
padding: .5rem;
border: solid #ddd;
border-width: 0 2px;
font-size: 2rem;
height: 3rem;
font-weight: bold;
text-align: center;
}
<div class="number-input">
<button onclick="this.parentNode.querySelector('input[type=number]').stepDown()" ></button>
<input class="quantity" min="0" name="quantity" value="1" type="number">
<button onclick="this.parentNode.querySelector('input[type=number]').stepUp()" class="plus"></button>
</div>
Note: In order to change the input's value, one needs to find it. To provide flexibility, in the example above I grouped buttons and the <input> under a common parent and used that parent to find the <input> (choosing not to rely on their proximity or particular order in DOM). The above method will change any input[type=number] sibling to the buttons. If that's not convenient, one could use any other methods to find the input from the buttons:
by id: .querySelector('#some-id'):
<button onclick="this.parentNode.querySelector('#some-id').stepUp()"></button>
by className: .querySelector('.some-class'):
<button onclick="this.parentNode.querySelector('.some-class').stepUp()"></button>
Also note the above examples only search inside the .parentNode, not in the entire document, which is also possible:
i.e: onclick="document.getElementById('#some-id').stepUp()"
by proximity (previousElementSibling | nextElementSibling)
<button onclick="this.previousElementSibling.stepUp()"></button>
any other way to determine and find a particular input element in a DOM structure. For example, one could use third party libraries, such as jQuery:
<button onclick="$(this).prev()[0].stepUp()"></button>
An important note when using jQuery is that the stepUp() and stepDown() methods are placed on the DOM element, not on the jQuery wrapper. The DOM element is found inside the 0 property of the jQuery wrapper.
Note on preventDefault(). Clicking a <button> inside a <form> will trigger the form submission. Therefore, if used as above, inside forms, the onclick should also contain preventDefault();. Example:
<button onclick="$(this).prev()[0].stepUp();preventDefault()"></button>
However, if one would use <a> tags instead of <button>s, this is not necessary. Also, the prevention can be set globally for all form buttons with a small JavaScript snippet:
var buttons = document.querySelectorAll('form button:not([type="submit"])');
for (i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function(e) {
e.preventDefault();
});
}
... or, using jQuery:
$('form').on('click', 'button:not([type="submit"])', function(e){
e.preventDefault();
})
Number inputs can be stylized this way with the following script I recently found:
Demo.
This script is a super-light-weight (1.49kb uncompressed, 0.71kb compressed, 0.35kb gzipped), usable and reliable quantity input that replaces the horrible, fiddly little input buttons built in to the number input in the browser. It is written using ES6 modules, so will need to be transpiled for older browsers.
The author's repository is here.
Hope this helps ;)
Edit:
Alternatively, if you'd like to have up/down arrow buttons instead of plus/minus ones, there is another jQuery-based solution.
$(document).ready(function () {
jQuery('<div class="quantity-nav"><button class="quantity-button quantity-up"></button><button class="quantity-button quantity-down">&#xf107</button></div>').insertAfter('.quantity input');
jQuery('.quantity').each(function () {
var spinner = jQuery(this),
input = spinner.find('input[type="number"]'),
btnUp = spinner.find('.quantity-up'),
btnDown = spinner.find('.quantity-down'),
min = input.attr('min'),
max = input.attr('max');
btnUp.click(function () {
var oldValue = parseFloat(input.val());
if (oldValue >= max) {
var newVal = oldValue;
} else {
var newVal = oldValue + 1;
}
spinner.find("input").val(newVal);
spinner.find("input").trigger("change");
});
btnDown.click(function () {
var oldValue = parseFloat(input.val());
if (oldValue <= min) {
var newVal = oldValue;
} else {
var newVal = oldValue - 1;
}
spinner.find("input").val(newVal);
spinner.find("input").trigger("change");
});
});
});
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
min-width: 100vw;
background: #34495E;
font-size: 1rem;
}
.quantity {
position: relative;
}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type=number] {
-moz-appearance: textfield;
}
.quantity input {
width: 45px;
height: 42px;
line-height: 1.65;
float: left;
display: block;
padding: 0;
margin: 0;
padding-left: 20px;
border: none;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08);
font-size: 1rem;
border-radius: 4px;
}
.quantity input:focus {
outline: 0;
}
.quantity-nav {
float: left;
position: relative;
height: 42px;
}
.quantity-button {
position: relative;
cursor: pointer;
border: none;
border-left: 1px solid rgba(0, 0, 0, 0.08);
width: 21px;
text-align: center;
color: #333;
font-size: 13px;
font-family: "FontAwesome" !important;
line-height: 1.5;
padding: 0;
background: #FAFAFA;
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
}
.quantity-button:active {
background: #EAEAEA;
}
.quantity-button.quantity-up {
position: absolute;
height: 50%;
top: 0;
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
font-family: "FontAwesome";
border-radius: 0 4px 0 0;
line-height: 1.6
}
.quantity-button.quantity-down {
position: absolute;
bottom: 0;
height: 50%;
font-family: "FontAwesome";
border-radius: 0 0 4px 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="quantity">
<input type="number" min="1" max="9" step="1" value="1">
</div>
Here is another version, based on the answer of #tao, using font-awesome:
input[type="number"] {
-webkit-appearance: textfield;
-moz-appearance: textfield;
appearance: textfield;
}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
}
.number-input {
border: 2px solid #ddd;
display: inline-flex;
}
.number-input,
.number-input * {
box-sizing: border-box;
}
.number-input button {
outline:none;
-webkit-appearance: none;
background-color: transparent;
border: none;
align-items: center;
justify-content: center;
width: 3rem;
height: 3rem;
cursor: pointer;
margin: 0;
position: relative;
}
.number-input button:after {
display: inline-block;
position: absolute;
font-family: "Font Awesome 5 Free";
font-weight: 900;
content: '\f077';
transform: translate(-50%, -50%) rotate(180deg);
}
.number-input button.plus:after {
transform: translate(-50%, -50%) rotate(0deg);
}
.number-input input[type=number] {
font-family: sans-serif;
max-width: 5rem;
padding: .5rem;
border: solid #ddd;
border-width: 0 2px;
font-size: 2rem;
height: 3rem;
font-weight: bold;
text-align: center;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css" integrity="sha512-HK5fgLBL+xu6dm/Ii3z4xhlSUyZgTT9tuc/hSrtw6uzJOvgRr2a9jyxxT1ely+B+xFAmJKVSTbpM/CuL7qxO8w==" crossorigin="anonymous" />
<div class="number-input">
<button onclick="this.parentNode.querySelector('input[type=number]').stepDown()" class="minus"></button>
<input class="quantity" min="0" name="quantity" value="1" type="number">
<button onclick="this.parentNode.querySelector('input[type=number]').stepUp()" class="plus"></button>
</div>
You can easily convert first design with second one like this:
HTML
<div class="quantity">
<button class="btn minus1">-</button>
<input class="quantity" id="id_form-0-quantity" min="0" name="form-0-quantity" value="1" type="number">
<button class="btn add1">+</button>
CSS
.quantity{
display:flex;
width:160px;
}
/* it will support chrome and firefox */
.quantity input[type=number]::-webkit-inner-spin-button,
.quantity input[type=number]::-webkit-outer-spin-button{
-webkit-appearance:none;
}
.quantity input,.quantity button{
width:50px;
padding:.5em;
font-size:1.2rem;
text-align:center;
font-weight:900;
background:white;
border:1px solid #aaa;
}
.quantity input{
border-left:none;
border-right:none;
}
I found a nice solution. Just rotate the arrow keys and set the opacity to 0. (they are now in the right place, invisible but clickable) Then set an :after and :before element over these invisible buttons. These elements can then be styled as desired.
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
transform: rotate(90deg);
height: 80px;
opacity: 0;
}
.quantity-wrapper {
position: relative;
}
.quantity-wrapper:after {
content: "+";
position: absolute;
right: 5px;
height: 100%;
top: 8px;
pointer-events: none;
}
.quantity-wrapper:before {
content: "-";
position: absolute;
left: 5px;
height: 100%;
top: 8px;
}
<div class="quantity-wrapper">
<input class="quantity" id="id_form-0-quantity" min="0" name="form-0-quantity" value="1" type="number">
</div>
This code can help you .may be found [here also](Detecting number input spinner click
$.fn.spinInput = function (options) {
var settings = $.extend({
maximum: 1000,
minimum: 0,
value: 1,
onChange: null
}, options);
return this.each(function (index, item) {
var min = $(item).find('>*:first-child').first();
var max = $(item).find('>*:last-child').first();
var v_span = $(item).find('>*:nth-child(2)').find('span');
var v_input = $(item).find('>*:nth-child(2)').find('input');
var value = settings.value;
$(v_input).val(value);
$(v_span).text(value);
async function increment() {
value = Number.parseInt($(v_input).val());
if ((value - 1) > settings.maximum) return;
value++;
$(v_input).val(value);
$(v_span).text(value);
if (settings.onChange) settings.onChange(value);
}
async function desincrement() {
value = Number.parseInt($(v_input).val());
if ((value - 1) < settings.minimum) return;
value--
$(v_input).val(value);
$(v_span).text(value);
if (settings.onChange) settings.onChange(value);
}
var pressTimer;
function actionHandler(btn, fct, time = 100, ...args) {
function longHandler() {
pressTimer = window.setTimeout(function () {
fct(...args);
clearTimeout(pressTimer);
longHandler()
}, time);
}
$(btn).mouseup(function () {
clearTimeout(pressTimer);
}).mousedown(function () {
longHandler();
});
$(btn).click(function () {
fct(...args);
});
}
actionHandler(min, desincrement, 100);
actionHandler(max, increment, 100)
})
}
$('body').ready(function () {
$('.spin-input').spinInput({ value: 1, minimum: 1 });
});
:root {
--primary-dark-color: #F3283C;
--primary-light-color: #FF6978;
--success-dark-color: #32A071;
--sucess-light-color: #06E775;
--alert-light-color: #a42a23;
--alert-dark-color: #7a1f1a;
--secondary-dark-color: #666666;
--secondary-light-color: #A6A6A6;
--gold-dark-color: #FFA500;
--gold-light-color: #FFBD00;
--default-dark-color: #1E2C31;
--default-light-color: #E5E5E5;
}
.fx-row {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.fx-colum {
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.fx-colum.nowrap,
.fx-row.nowrap {
flex-wrap: nowrap;
}
.fx-row.fx-fill>*,
.fx-colum.fx-fill>* {
flex-grow: 1;
}
.spin-input {
border: 1px solid var(--secondary-light-color);
}
.spin-input>div:first-child {
cursor: pointer;
border-right: 1px solid var(--secondary-light-color);
}
.spin-input>div:first-child:active {
transform: translate3d(1px, 0px, 1px)
}
.spin-input>div:last-child {
flex: none;
border-left: 1px solid var(--secondary-light-color);
cursor: pointer;
}
.spin-input>div:last-child:active {
transform: translate3d(1px, 0px, 1px)
}
.icon {
font-weight: bold;
text-align: center;
vertical-align: middle;
padding: 12px;
font-size: 28px;
}
.icon.primary,
.icon.primary .ci {
color: var(--primary-dark-color);
}
.icon.reactive:hover .ci {
color: var(--primary-light-color);
}
.hidden {
display: none;
}
<script src="https://releases.jquery.com/git/jquery-3.x-git.min.js"></script>
<div class="spin-input nowrap fx-row fx-fill" >
<div class="icon reactive">
<span class="ci ci-minus">-</span>
</div>
<div class="icon">
<span>0</span>
<input type="text" class="hidden" value="0">
</div>
<div class="icon reactive">
<span class="ci ci-plus">+</span>
</div>
</div>
259)