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
Related
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%).
This question already has answers here:
Image inside div has extra space below the image
(10 answers)
Align inline-block DIVs to top of container element
(5 answers)
Closed 2 years ago.
I just finished the basic react tic tac toe tutorial and I modified the base code so I can dynamically generate n x n tic tac toe grids. Currently I'm using flexbox to format my "grid" of buttons and I'm running into an issue where flexbox column appears to be adding a margin between entities. I'm not sure why this is the case. Additionally, when I click on every element in a row, react rerenders the entire row with the correct margins. Below is my css and javascript.
function Square(props) {
return (
<button className="square" onClick={props.onClick}>
{props.value}
</button>
);
}
class Board extends React.Component {
// essentially these are fields that store the state of the board
constructor(props) {
super(props);
this.state = {
squares: Array(16).fill(null),
xIsNext: true
};
}
// generate row
generateRow(j) {
var i;
var columns = 4;
var row = [];
for (i = 0; i < columns; i++) {
row.push(
<div key={i + columns * j}> {this.renderSquare(i + columns * j)} </div>
);
}
return row;
}
// create board
renderBoard() {
var i;
var rows = 4;
var board = [];
for (i = 0; i < rows; i++) {
board.push(<div className="board-row"> {this.generateRow(i)}</div>);
}
return board;
}
handleClick(i) {
const squares = this.state.squares.slice();
if (squares[i]) {
return;
}
squares[i] = this.state.xIsNext ? "X" : "O";
this.setState({
squares: squares,
xIsNext: !this.state.xIsNext
});
}
renderSquare(i) {
return (
<Square
value={this.state.squares[i]}
onClick={() => this.handleClick(i)}
/>
);
}
render() {
let status;
status = "Next player " + (this.state.xIsNext ? "X" : "O");
return (
<div>
<div className="status">{status}</div>
{this.renderBoard()}
</div>
);
}
}
class Game extends React.Component {
render() {
return (
<div className="game">
<div className="game-board">
<Board />
</div>
</div>
);
}
}
// ========================================
ReactDOM.render(<Game />, document.getElementById("root"));
body {
font: 14px "Century Gothic", Futura, sans-serif;
margin: 20px;
}
ol,
ul {
padding-left: 30px;
}
.status {
margin-bottom: 10px;
}
.square:focus {
outline: none;
}
.kbd-navigation .square:focus {
background: #ddd;
}
.game-info {
margin-left: 20px;
}
.game-board {
display: flex;
flex-direction: column;
}
.board-row {
display: flex;
flex-direction: row;
margin-bottom: -1px;
}
.square {
background: #fff;
border: 1px solid #999;
font-size: 24px;
font-weight: bold;
line-height: 34px;
height: 40px;
padding: 0;
text-align: center;
width: 40px;
margin-right: -1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Image of the issue
One effective way of debugging your layout is examining your elements' dimensions.
As you can see in the images, the button's parent div has a higher height of 2 pixels greater than the button. This is because of the additional size generated by the inline-block (button) element's borders. To address this, I simply assigned button a display: block CSS property.
function Square(props) {
return (
<button className="square" onClick={props.onClick}>
{props.value}
</button>
);
}
class Board extends React.Component {
// essentially these are fields that store the state of the board
constructor(props) {
super(props);
this.state = {
squares: Array(16).fill(null),
xIsNext: true
};
}
// generate row
generateRow(j) {
var i;
var columns = 4;
var row = [];
for (i = 0; i < columns; i++) {
row.push(
<div key={i + columns * j}> { this.renderSquare(i + columns * j) } </div>
);
}
return row;
}
// create board
renderBoard() {
var i;
var rows = 4;
var board = [];
for (i = 0; i < rows; i++) {
board.push(<div className="board-row"> {this.generateRow(i)}</div>);
}
return board;
}
handleClick(i) {
const squares = this.state.squares.slice();
if (squares[i]) {
return;
}
squares[i] = this.state.xIsNext ? "X" : "O";
this.setState({
squares: squares,
xIsNext: !this.state.xIsNext
});
}
renderSquare(i) {
return (
<Square
value={this.state.squares[i]}
onClick={() => this.handleClick(i)}
/>
);
}
render() {
let status;
status = "Next player " + (this.state.xIsNext ? "X" : "O");
return (
<div>
<div className="status">{status}</div>
{this.renderBoard()}
</div>
);
}
}
class Game extends React.Component {
render() {
return (
<div className="game">
<div className="game-board">
<Board />
</div>
</div>
);
}
}
// ========================================
ReactDOM.render(<Game />, document.getElementById("root"));
body {
font: 14px "Century Gothic", Futura, sans-serif;
margin: 20px;
}
ol,
ul {
padding-left: 30px;
}
.status {
margin-bottom: 10px;
}
.square:focus {
outline: none;
}
.kbd-navigation .square:focus {
background: #ddd;
}
.game-info {
margin-left: 20px;
}
.game-board {
display: flex;
flex-direction: column;
}
.board-row {
display: flex;
flex-direction: row;
margin-bottom: -1px;
}
.square {
background: #fff;
border: 1px solid #999;
font-size: 24px;
font-weight: bold;
line-height: 34px;
height: 40px;
padding: 0;
text-align: center;
width: 40px;
margin-right: -1px;
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>
I think I've reproduced your markup output here and I don't see the issue you're having. I suspect there's a CSS rule somewhere that's not represented in your example; something adding a bottom margin to buttons maybe?
Have you inspected it via the browser's dev tools?
body {
font: 14px "Century Gothic", Futura, sans-serif;
margin: 20px;
}
ol,
ul {
padding-left: 30px;
}
.status {
margin-bottom: 10px;
}
.square:focus {
outline: none;
}
.kbd-navigation .square:focus {
background: #ddd;
}
.game-info {
margin-left: 20px;
}
.game-board {
display: flex;
flex-direction: column;
}
.board-row {
display: flex;
flex-direction: row;
margin-bottom: -1px;
}
.square {
background: #fff;
border: 1px solid #999;
font-size: 24px;
font-weight: bold;
line-height: 34px;
height: 40px;
padding: 0;
text-align: center;
width: 40px;
margin-right: -1px;
}
<div class="game">
<div class="game-board">
<div class="board-row">
<button class="square">1</button>
<button class="square">2</button>
<button class="square">3</button>
<button class="square">4</button>
</div>
<div class="board-row">
<button class="square">1</button>
<button class="square">2</button>
<button class="square">3</button>
<button class="square">4</button>
</div>
<div class="board-row">
<button class="square">1</button>
<button class="square">2</button>
<button class="square">3</button>
<button class="square">4</button>
</div>
<div class="board-row">
<button class="square">1</button>
<button class="square">2</button>
<button class="square">3</button>
<button class="square">4</button>
</div>
</div>
</div>
This image slide show is positioned in the middle on my page how do I make it so that it's in the middle but slightly higher? The things I've tried don't currently work which includes my css code. the top: xx%; thing doesn't work either. As you can see the images are actually behind the question container and I want it so that it is above the question container (not in front).
html:
<div class="container2">
<img name="slide">
css
.slide {
width: auto;
max-width: 1%;
height: auto;
max-height: 30%;
position: absolute;
z-index: 1;
top: 50%;
}
const startButton = document.getElementById('start-btn')
const nextButton = document.getElementById('next-btn')
const questionContainerElement = document.getElementById('question-container')
const questionElement = document.getElementById('question')
const image1 = document.getElementById('image1')
const answerButtonsElement = document.getElementById('answer-buttons')
const endbutton = document.getElementById('end-btn')
const trybutton = document.getElementById('try-btn')
const startmsgs = document.getElementById('startmsg')
var i = 0;
var images = [];
images[0] = "http://lorempixel.com/400/200/animals";
images[1] = "http://lorempixel.com/400/200/sports";
images[2] = "http://lorempixel.com/400/200/food";
images[3] = "http://lorempixel.com/400/200/people";
function changeImg(){
document.slide.src = images[i];
// Check If Index Is Under Max
if(i < images.length - 1){
// Add 1 to Index
i++;
} else {
// Reset Back To O
i = 0;
}
window.onload=changeImg;
}
let shuffledQuestions, currentQuestionIndex
startButton.addEventListener('click', startGame)
nextButton.addEventListener('click', () => {
currentQuestionIndex++
setNextQuestion()
changeImg()
})
endbutton.addEventListener('click', () => {
window.top.close()
})
trybutton.addEventListener('click', setNextQuestion)
function startGame() {
startButton.classList.add('hide')
startmsgs.classList.add('hide')
shuffledQuestions = questions.slice()
questionContainerElement.classList.remove('hide')
currentQuestionIndex = 0
setNextQuestion()
}
function setNextQuestion() {
resetState()
showQuestion(shuffledQuestions[currentQuestionIndex])
}
function showQuestion(question) {
questionElement.innerText = question.question
question.answers.forEach(answer => {
const button = document.createElement('button')
button.innerText = answer.text
button.classList.add('btn')
if (answer.correct) {
button.dataset.correct = answer.correct
}
button.addEventListener('click', selectAnswer)
answerButtonsElement.appendChild(button)
})
}
function resetState() {
clearStatusClass(document.body)
nextButton.classList.add('hide')
while (answerButtonsElement.firstChild) {
answerButtonsElement.removeChild(answerButtonsElement.firstChild)
}
trybutton.classList.add('hide')
}
function selectAnswer(e) {
const selectedButton = e.target
const correct = selectedButton.dataset.correct
setStatusClass(document.body, correct)
setStatusClass(selectedButton, correct);
if(correct){
if (shuffledQuestions.length > currentQuestionIndex + 1) {
nextButton.classList.remove('hide')
} else {
endbutton.classList.remove('hide')
}
} else{
trybutton.classList.remove('hide')
}
}
function setStatusClass(element, correct) {
clearStatusClass(element)
if (correct) {
element.classList.add('correct')
}
else {
element.classList.add('wrong')
}
}
function clearStatusClass(element) {
element.classList.remove('correct')
element.classList.remove('wrong')
}
const questions = [
{
question: 'Are you excited to learn about the immune system?',
answers: [
{ text: 'Yes', correct: true },
{ text: 'YES!!!', correct: true },
{ text: 'No', correct: false },
{ text: 'YES!!!!!!!', correct: true }
]
},
{
question: 'Our immune system protects from the thousands of different viruses we encounter daily! Without it, a simple paper cut could mean death. So to demonstrate how the immune system functions to protect us from bacterias, viruses and foreign bodies, we start our journey with a paper cut!',
answers: [
{ text: 'I am exicted!', correct: true },
]
}
]
*, *::before, *::after {
box-sizing: border-box;
font-family: cursive,
'Times New Roman', Times, serif
}
#particles-js {
position: absolute;
width: 100%;
height: 100%;
/* background-color: #b61924; */
background-repeat: no-repeat;
background-size: cover;
background-position: 50% 50%;
z-index: 1;
}
:root {
--hue-neutral: 200;
--hue-wrong: 0;
--hue-correct: 145;
}
body {
--hue: var(--hue-neutral);
padding: 0;
margin: 0;
display: flex;
width: 100vw;
height: 100vh;
justify-content: center;
align-items: center;
background-color: hsl(var(--hue), 100%, 20%);
}
body.correct {
--hue: var(--hue-correct);
}
body.wrong {
--hue: 0;
}
.container {
width: 800px;
max-width: 80%;
background-color: white;
border-radius: 5px;
padding: 10px;
box-shadow: 0 0 10px 2px;
z-index: 2;
position: absolute;
}
.btn-grid {
display: grid;
grid-template-columns: repeat(2, auto);
gap: 10px;
margin: 20px 0;
}
.btn {
--hue: var(--hue-neutral);
border: 1px solid hsl(var(--hue), 100%, 30%);
background-color: hsl(var(--hue), 100%, 50%);
border-radius: 5px;
padding: 5px 10px;
color: white;
outline: none;
}
.btn:hover {
border-color: black;
}
.btn.correct {
--hue: var(--hue-correct);
color: black;
}
.btn.wrong {
--hue: var(--hue-wrong);
}
.next-btn {
font-size: 1.5rem;
font-weight: bold;
padding: 10px 20px;
align-items: flex-end;
--hue: 245;
}
.start-btn {
font-size: 1.5rem;
font-weight: bold;
padding: 10px 20px;
--hue: 245;
}
.end-btn {
font-size: 1.5rem;
font-weight: bold;
padding: 10px 20px;
--hue: 245;
}
.try-btn {
font-size: 1.5rem;
font-weight: bold;
padding: 10px 20px;
--hue: 245;
}
.container1 {
display: flex;
justify-content: center;
align-items: center;
font-family: Arial;
font-size: xx-large;
padding: 10px 10px;
}
.slide {
width: auto;
max-width: 1%;
height: auto;
max-height: 30%;
position: absolute;
z-index: 1;
top: 50%;
}
.controls {
display: flex;
justify-content: center;
align-items: center;
}
.hide {
display: none;
}
.wrapper {
position: absolute;
top: 0px;
right: 0px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="styles.css">
<script defer src="script.js"></script>
<title>Quiz App</title>
</head>
<body>
</div>
<div class="container">
<div id="question-container" class="hide">
<div id="question">Question</div>
<div id="answer-buttons" class="btn-grid">
<button class="btn">Answer 1</button>
<button class="btn">Answer 2</button>
<button class="btn">Answer 3</button>
<button class="btn">Answer 4</button>
</div>
</div>
<div class="container1">
<div id="startmsgcontainer" class="hide"></div>
<div id="startmsg">Adventure Into The Human Immune System</div>
</div>
<div class="controls">
<button id="start-btn" class="start-btn btn">Start!</button>
<button id="next-btn" class="next-btn btn hide">Next</button>
<button id="end-btn" class="end-btn btn hide">End (this will close the current tab)</button>
<button id="try-btn" class="try-btn btn hide">Try again!</button>
</div>
</div>
<div class="container2">
<img name="slide">
</div>
<div class="wrapper">
<img src="img/uni.png" alt="image">
</div>
</div>
<div id="particles-js"></div>
<script src="particles.js"></script>
<script src="app.js"></script>
<script src="slide.js"></script>
</body>
</html>
If I've understood what you want correctly, you'd need to add this to .slide:
transform: translateY(-50%)
top: 50% will put the top of the slider in the middle of the screen so this will push it back up based on the height of the slider.
Edit:
Based on your new code you could do the same thing on .container. Or you could use
margin-top: -100px
or
margin-bottom: 100px
or
position: relative;
top: -100px;
You can try:
Css-
Margin-top: -x;
And add !important
I am stuck on a portion of a project I have been working on today. The task is to sync the timestamp information from the embedded youtube video and display a custom progress bar matching the length of the song at the bottom of the page. Here is the layout so far:
So basically, how do I pull constant timestamps to update the progress and how do I animate the bar to complete 100% matching the end of the video.
I have already disabled the user's ability to scrobble the embedded youtube video. NOTE: the user should not be able to change the time of the youtube video using the custom progress bar either (it is just there for visual queue)!
Please let me know if you need more clarification. HTML and CSS are below. Thank you!! :)
HTML >>>
<!DOCTYPE html>
<html>
<head>
<title>Chat</title>
<link rel="stylesheet" href="main.css">
</head>
<body>
<div class="header-bar">
<div class="bar"></div>
<div class="dropshadow"></div>
</div>
<div class="container-middle-third">
<div class="youtube-video" style="float: left;">
<div class="DJ-text">Affinity FM DJ Room</div>
<div class="DJ-underline"></div>
<div class="transparent-layer"> <iframe width="850px" height="477px" src="https://www.youtube.com/embed/2GvIq2SpVFM?autoplay=0&showinfo=0&controls=0" frameborder="0" allowfullscreen></iframe></div>
</div>
<div class="chat" style="float: left;">
<div class="Chat-text">Chat</div>
<div class="Chat-underline"></div>
<input type="text" class="chat-name" placeholder="Chat">
<div class="info-rect">Info</div>
<div class="chat-messages"></div>
<textarea placeholder="Join the conversation..."></textarea>
<div class="chat-status">Status: <span>Idle</span></div>
</div>
</div>
<div class="bottom-bar">
<div class="thumbnail" style="float: left"></div>
<div class="title-bar" style="float: left;">
<div class="song-name">Finding Hope - Let Go (feat. Deverano)</div>
<div class="dj-playing">Affinity FM is playing</div>
<div class="progress-background"></div>
<div class="progress-bar"></div>
</div>
<div class="subscribe" style="float: left;"></div>
</div>
<script src="http://127.0.0.1:8080/socket.io/socket.io.js"></script>
<script>
(function() {
var getNode = function(s) {
return document.querySelector(s);
},
// Get required nodes
status = getNode('.chat-status span'),
messages = getNode('.chat-messages'),
textarea = getNode('.chat textarea'),
chatName = getNode('.chat-name'),
statusDefault = status.textContent,
setStatus = function(s){
status.textContent = s;
if(s !== statusDefault){
var delay = setTimeout(function(){
setStatus(statusDefault);
clearInterval(delay);
}, 3000);
}
};
//try connection
try{
var socket = io.connect('http://127.0.0.1:8080');
} catch(e){
//Set status to warn user
}
if(socket !== undefined){
//Listen for output
socket.on('output', function(data){
if(data.length){
//Loop through results
for(var x = 0; x < data.length; x = x + 1){
var message = document.createElement('div');
message.setAttribute('class', 'chat-message');
message.textContent = ': ' + data[x].message;
var name=document.createElement('span');
name.setAttribute('class', 'userName');
name.textContent = data[x].name;
message.insertBefore(name, message.firstChild);
//Append
messages.appendChild(message);
messages.insertBefore(message, messages.firstChild);
}
}
});
//Listen for a status
socket.on('status', function(data){
setStatus((typeof data === 'object') ? data.message : data);
if(data.clear === true){
textarea.value = '';
}
});
//Listen for keydown
textarea.addEventListener('keydown', function(event){
var self = this,
name = chatName.value;
if(event.which === 13 && event.shiftKey === false){
socket.emit('input', {
name: name,
message: self.value
});
}
});
}
})();
</script>
</body>
</html>
and CSS >>>
body {
background-color: #0f0f17;
margin: 0px;
width: 100%;
}
.container-middle-third{
margin-top: 20px;
margin-left: 155px;
}
body,
textarea,
input {
font: 13px "Raleway", sans-serif;
color: #ffffff;
}
.bar{
height: 80px;
width: 100%;
background-color: #15151d;
}
.DJ-text{
font-weight: 700;
/*position:relative;*/
text-transform: uppercase;
}
.Chat-text{
font-weight: 700;
text-transform: uppercase;
}
.DJ-underline{
width: 850px;
height: 1px;
position:relative;top:10px;
background-color: #3f3f45;
margin: 0px 0px 40px;
}
.Chat-underline{
width: 100%;
position:relative;
/*left:-140px;*/
float:right;
height: 1px;
position:relative;top:10px;
background-color: #3f3f45;
margin: 0px 0px 40px;
}
.transparent-layer{
width: 850px;
height: 477px;
pointer-events: none;
background-color: #ffffff;
}
.ad{
width: 728px;
height: 90px;
border: 1px solid #000000;
margin-left: 11px;
margin-top: 20px;
}
.chat {
min-width: 400px;
margin: 0px 0px 0px 135px;
}
.chat-messages,
.chat-textarea,
.chat-name {
border: 1px solid #1a1a23;
background-color: #1a1a23;
}
.userName{
font-weight: 700;
color: #079ce0;
}
.chat-messages {
width:380px;
height:400px;
overflow-y:scroll;
padding:10px;
}
.chat-message {
margin-bottom:10px;
}
.info-rect{
height: 40px;
width: 180px;
padding:10px;
max-width: 100%;
margin:0;
border:0;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
text-transform: uppercase;
background-color: #15151d
}
.chat-name{
height: 40px;
max-width: 100%;
width: 180px;
padding:10px;
border:0;
margin:0;
font-weight: 700;
text-transform: uppercase;
float:left;
text-align: center;
}
.chat textarea {
width:380px;
padding:10px;
margin:0;
border-top:0;
max-width:100%;
border-top: 1px solid #0f0f17;
border-bottom: 1px solid #1a1a23;
border-right: 1px solid #1a1a23;
border-left: 1px solid #1a1a23;
background-color: #1a1a23;
}
.chat-status {
color: #bbb;
opacity: 0;
background-color: #0f0f17;
}
.info-rect,
.chat textarea,
.chat-name {
max-width: 100%;
}
.bottom-bar{
position: fixed;
bottom: 0;
width: 100%;
}
.thumbnail{
width: 80px;
height: 80px;
background-color: #ffffff
}
.title-bar{
width:1000px;
height: 80px;
background-color: #1a1a23;
}
.song-name{
font-weight: 700;
text-transform: uppercase;
margin-left: 30px;
margin-top: 25px;
}
.dj-playing{
margin-left: 30px;
}
.progress-background{
width: 1000px;
height: 4px;
background-color: #313139;
position: fixed;
bottom: 0;
}
.progress-bar{
width: 400px;
height: 4px;
background-color: #fa1d57;
position: fixed;
bottom: 0;
}
.subscribe{
width: 520px;
height: 80px;
background-color: #15151d;
}
Love your questions!
switch the iframe with a div with id="player" (any name you want, it could be "my_own_player" or "XYZ_player"...)
Then now you're all set to convert your iframe player into a Youtube player object so that you can accomplish what you desire, using the "IFrame player API".
Make sure you style your div the same way you wanted your iframe.
Just add the following script :
//This function creates an <iframe> (and YouTube player)
function onYouTubeIframeAPIReady()
{
player = new YT.Player("player",
{
height: "850",
width: "477",
videoId: "2GvIq2SpVFM",
events:
{
"onReady": onPlayerReady,
"onStateChange": onPlayerStateChange
}
});
}
Replace videoId with your video's ID.
Replace height with your video's height.
Replace width with your video's width.
NOW, to get the "Video Time Stamps" like you say, in order to make the progress bar is easy. The player object has two methods that will do that:
getCurrentTime()
getDuration()
getDuration is the total time of the video in seconds. While getCurrentTime is the time where the video has played up to. Divide
getCurrentTime by getDuration and you'll get a ratio for the progress bar. Multiply it by 100 and you get the percentage you're looking for:
(player.getCurrentTime()/player.getDuration())*100;
That's it! Once you got a percentage that represents getCurrentTime / getDuration, you don't need anything else for an html progress bar. Just style that html bar element's width to that percentage. Just make sure that red "bar" has a background (another div) that's easily recognized as the outward limit for the progress bar. Or just put it inside another div that's visible on the page like so :
<div id="progress" style="width: 800px; height: 10px; border: 1px solid #fff;">
<div id="bar" style="width: 1px; height: 10px; background: #f00;"></div>
</div>
Please, just try out your modified HTML:
<!DOCTYPE html>
<html>
<head>
<title>Chat</title>
<link rel="stylesheet" href="main.css">
</head>
<body>
<div class="header-bar">
<div class="bar"></div>
<div class="dropshadow"></div>
</div>
<div class="container-middle-third">
<div class="youtube-video" style="float: left;">
<div class="DJ-text">Affinity FM DJ Room</div>
<div class="DJ-underline"></div>
<div class="transparent-layer"> <div id="player" style="width: 850px; height: 477px;"></div></div>
</div>
<div class="chat" style="float: left;">
<div class="Chat-text">Chat</div>
<div class="Chat-underline"></div>
<input type="text" class="chat-name" placeholder="Chat">
<div class="info-rect">Info</div>
<div class="chat-messages"></div>
<textarea placeholder="Join the conversation..."></textarea>
<div class="chat-status">Status: <span>Idle</span></div>
</div>
</div>
<div class="bottom-bar">
<div class="thumbnail" style="float: left"></div>
<div class="title-bar" style="float: left;">
<div class="song-name">Finding Hope - Let Go (feat. Deverano)</div>
<div class="dj-playing">Affinity FM is playing</div>
<div class="progress-background">
<div id="progress-bar" class="progress-bar"></div>
</div>
</div>
<div class="subscribe" style="float: left;"></div>
</div>
<script src="http://127.0.0.1:8080/socket.io/socket.io.js"></script>
<script>
(function() {
var getNode = function(s) {
return document.querySelector(s);
},
// Get required nodes
status = getNode('.chat-status span'),
messages = getNode('.chat-messages'),
textarea = getNode('.chat textarea'),
chatName = getNode('.chat-name'),
statusDefault = status.textContent,
setStatus = function(s){
status.textContent = s;
if(s !== statusDefault){
var delay = setTimeout(function(){
setStatus(statusDefault);
clearInterval(delay);
}, 3000);
}
};
//try connection
try{
var socket = io.connect('http://127.0.0.1:8080');
} catch(e){
//Set status to warn user
}
if(socket !== undefined){
//Listen for output
socket.on('output', function(data){
if(data.length){
//Loop through results
for(var x = 0; x < data.length; x = x + 1){
var message = document.createElement('div');
message.setAttribute('class', 'chat-message');
message.textContent = ': ' + data[x].message;
var name=document.createElement('span');
name.setAttribute('class', 'userName');
name.textContent = data[x].name;
message.insertBefore(name, message.firstChild);
//Append
messages.appendChild(message);
messages.insertBefore(message, messages.firstChild);
}
}
});
//Listen for a status
socket.on('status', function(data){
setStatus((typeof data === 'object') ? data.message : data);
if(data.clear === true){
textarea.value = '';
}
});
//Listen for keydown
textarea.addEventListener('keydown', function(event){
var self = this,
name = chatName.value;
if(event.which === 13 && event.shiftKey === false){
socket.emit('input', {
name: name,
message: self.value
});
}
});
}
})();
</script>
<script>
var time_total;
var timeout_setter;
var player;
var tag = document.createElement("script");//This code loads the IFrame Player API code asynchronously
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
//This function creates an <iframe> (and YouTube player) OR uses the iframe if it exists at the "player" element after the API code downloads
function onYouTubeIframeAPIReady()
{
player = new YT.Player("player",
{
height: "850",
width: "477",
videoId: "2GvIq2SpVFM",
events:
{
"onReady": onPlayerReady,
"onStateChange": onPlayerStateChange
}
});
}
//The API will call this function when the video player is ready
function onPlayerReady(event)
{
event.target.playVideo();
time_total = convert_to_mins_and_secs(player.getDuration(), 1);
loopy();
}
function loopy()
{
var current_time = convert_to_mins_and_secs(player.getCurrentTime(), 0);
document.getElementById("progress-bar").style.width = (player.getCurrentTime()/player.getDuration())*100+"%";
console.log( current_time + " / " + time_total);
timeout_setter = setTimeout(loopy, 1000);
}
function convert_to_mins_and_secs(seconds, minus1)
{
var mins = (seconds>=60) ?Math.round(seconds/60):0;
var secs = (seconds%60!=0) ?Math.round(seconds%60):0;
var secs = (minus1==true) ?(secs-1):secs; //Youtube always displays 1 sec less than its duration time!!! Then we have to set minus1 flag to true for converting player.getDuration()
var time = mins + ":" + ((secs<10)?"0"+secs:secs);
return time;
}
// 5. The API calls this function when the player's state changes
function onPlayerStateChange(event)
{
if (event.data == YT.PlayerState.ENDED)
{
console.log("END!");
clearTimeout(timeout_setter);
}
else
{
console.log(event.data);
}
}
</script>
</body>
</html>
With your CSS:
body {
background-color: #0f0f17;
margin: 0px;
width: 100%;
}
.container-middle-third{
margin-top: 20px;
margin-left: 155px;
}
body,
textarea,
input {
font: 13px "Raleway", sans-serif;
color: #ffffff;
}
.bar{
height: 80px;
width: 100%;
background-color: #15151d;
}
.DJ-text{
font-weight: 700;
/*position:relative;*/
text-transform: uppercase;
}
.Chat-text{
font-weight: 700;
text-transform: uppercase;
}
.DJ-underline{
width: 850px;
height: 1px;
position:relative;top:10px;
background-color: #3f3f45;
margin: 0px 0px 40px;
}
.Chat-underline{
width: 100%;
position:relative;
/*left:-140px;*/
float:right;
height: 1px;
position:relative;top:10px;
background-color: #3f3f45;
margin: 0px 0px 40px;
}
.transparent-layer{
width: 850px;
height: 477px;
pointer-events: none;
background-color: #ffffff;
}
.ad{
width: 728px;
height: 90px;
border: 1px solid #000000;
margin-left: 11px;
margin-top: 20px;
}
.chat {
min-width: 400px;
margin: 0px 0px 0px 135px;
}
.chat-messages,
.chat-textarea,
.chat-name {
border: 1px solid #1a1a23;
background-color: #1a1a23;
}
.userName{
font-weight: 700;
color: #079ce0;
}
.chat-messages {
width:380px;
height:400px;
overflow-y:scroll;
padding:10px;
}
.chat-message {
margin-bottom:10px;
}
.info-rect{
height: 40px;
width: 180px;
padding:10px;
max-width: 100%;
margin:0;
border:0;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
text-transform: uppercase;
background-color: #15151d
}
.chat-name{
height: 40px;
max-width: 100%;
width: 180px;
padding:10px;
border:0;
margin:0;
font-weight: 700;
text-transform: uppercase;
float:left;
text-align: center;
}
.chat textarea {
width:380px;
padding:10px;
margin:0;
border-top:0;
max-width:100%;
border-top: 1px solid #0f0f17;
border-bottom: 1px solid #1a1a23;
border-right: 1px solid #1a1a23;
border-left: 1px solid #1a1a23;
background-color: #1a1a23;
}
.chat-status {
color: #bbb;
opacity: 0;
background-color: #0f0f17;
}
.info-rect,
.chat textarea,
.chat-name {
max-width: 100%;
}
.bottom-bar{
position: fixed;
bottom: 0;
width: 100%;
}
.thumbnail{
width: 80px;
height: 80px;
background-color: #ffffff
}
.title-bar{
width:1000px;
height: 80px;
background-color: #1a1a23;
}
.song-name{
font-weight: 700;
text-transform: uppercase;
margin-left: 30px;
margin-top: 25px;
}
.dj-playing{
margin-left: 30px;
}
.progress-background{
width: 1000px;
height: 4px;
background-color: #313139;
position: fixed;
bottom: 0;
}
.progress-bar{
width: 400px;
height: 4px;
background-color: #fa1d57;
position: fixed;
bottom: 0;
}
.subscribe{
width: 520px;
height: 80px;
background-color: #15151d;
}
Or just look at the result there :
http://lespointscom.com/a/misc/demo/2016_06_19/main.html
IFrame player API reference:
https://developers.google.com/youtube/iframe_api_reference#Loading_a_Video_Player
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);
}