How to properly submit form to Flask with AJAX? - javascript

I'm a beginner in Python and AJAX, why when I run my app.py with app.html, the result that I want to display are replaced with a whole form?
Here is my code:
from flask import Flask, render_template, request
app = Flask(__name__,
template_folder='C:\\Users\\iyzadsyammil\\PycharmProjects\\PVT - Copy')
#app.route('/App',methods=['GET', 'POST'])
def showapp():
error = " "
finalpb= 0
x=0
logpb=0
if request.method == 'POST':
ingor = request.form['inGOR']
ingor = float(ingor)
try:
finalpb = ingor
except ValueError:
error = "Please enter an appropriate value!"
return render_template('app.html',error=error,finalpb=finalpb)
if __name__ == "__main__":
app.run(debug=True)
This is my Python Flask file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="https://media.licdn.com/mpr/mpr/shrink_200_200/AAEAAQAAAAAAAAfJAAAAJDIxMDc1NWExLTczODgtNDBhOS1iZmYwLWRmOTZjZjc2NzVhYQ.png">
<title>Invigour Tool</title>
<!-- Bootstrap core CSS -->
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom styles for this template -->
<!--<link href="dashboard.css" rel="stylesheet" type="text/css">-->
<style>
/* Move down content because we have a fixed navbar that is 50px tall */
body {
padding-top: 50px;
}
/*
* Global add-ons
*/
.sub-header {
padding-bottom: 10px;
border-bottom: 1px solid #eee;
}
/*
* Top navigation
* Hide default border to remove 1px line.
*/
.navbar-fixed-top {
border: 0;
}
/*
* Sidebar
*/
/* Hide for mobile, show later */
.sidebar {
display: none;
}
#media (min-width: 768px) {
.sidebar {
position: fixed;
top: 51px;
bottom: 0;
left: 0;
z-index: 1000;
display: block;
padding: 20px;
overflow-x: hidden;
overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
background-color: #f5f5f5;
border-right: 1px solid #eee;
}
}
/* Sidebar navigation */
.nav-sidebar {
margin-right: -21px; /* 20px padding + 1px border */
margin-bottom: 20px;
margin-left: -20px;
}
.nav-sidebar > li > a {
padding-right: 20px;
padding-left: 20px;
}
.nav-sidebar > .active > a,
.nav-sidebar > .active > a:hover,
.nav-sidebar > .active > a:focus {
color: #fff;
background-color: #428bca;
}
/*
* Main content
*/
.main {
padding: 20px;
}
#media (min-width: 768px) {
.main {
padding-right: 40px;
padding-left: 40px;
}
}
.main .page-header {
margin-top: 0;
}
/*
* Placeholder dashboard ideas
*/
.placeholders {
margin-bottom: 30px;
text-align: center;
}
.placeholders h4 {
margin-bottom: 0;
}
.placeholder {
margin-bottom: 20px;
}
.placeholder img {
display: inline-block;
border-radius: 50%;
}
/* Custom page footer */
.footer {
padding-top: 10px;
margin-top: 2cm;
color: #777;
border-top: 1px solid #e5e5e5;
}
.cal{
float: right;
box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);
width: 180px;
height: 85px;
font-size: 30px;
border-radius: 24px;
background-color: limegreen;
position: relative;
right: 0.5cm;
}
.conti{
float: right;
box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);
width: 180px;
height: 85px;
font-size: 30px;
border-radius: 24px;
background-color: limegreen;
}
.rest{
float: right;
box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);
width: 180px;
height: 85px;
font-size: 30px;
border-radius: 24px;
background-color: limegreen;
margin-top: 3cm;
position: relative;
left: 7cm;
}
input[type="number"]{
margin-left: 3cm;
}
select[id=cor4],[id=cor5]{
width: 165px;
}
select{
margin-left: 1cm;
}
p[id=pb],[id=rs],[id=bo],[id=co],[id=uo],[id=po],[id=zf],[id=bg],[id=pg],[id=ug],[id=bw],[id=uw],[id=pw],[id=cw],[id=iow],[id=iog]{
margin-left: 4cm;
}
tr:hover{
background-color:#f5f5f5}
</style>
</head>
<body>
<div>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="http://www.invigourenergy.com/">Invigour Energy</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li>Dashboard</li>
<li>PVT Tool</li>
<li>Help</li>
</ul>
<form class="navbar-form navbar-right">
<input type="text" class="form-control" placeholder="Search...">
</form>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
<ul class="nav nav-sidebar">
<li class="active">Overview <span class="sr-only">(current)</span></li>
<li> </li>
<li> </li>
</ul>
<ul class="nav nav-sidebar">
<li> </li>
<li> </li>
<li> </li>
<li> </li>
<li> </li>
</ul>
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<form method="POST" class="form" id="fm">
<h3>Basic PVT Application</h3>
<br>
<table>
<tr><td><u>Input Data</u></td><td></td><td></td></tr>
<tr><td>&nbsp</td></tr>
<tr><td>Solution GOR(Rs) </td><td><input type="number" step="any" id="inGOR" name="inGOR"></td><td>scf/bbl</td></tr>
<tr><td>Oil Gravity </td><td><input type="number" step="any" id="inOG"></td><td>API</td></tr>
<tr><td>Gas Specific Gravity </td><td><input type="number" step="any" id="inGG"></td><td>SG(air=1)</td></tr>
<tr><td>Temperature </td><td><input type="number" step="any" id="inT"></td><td>◦F</td></tr>
<tr><td>Pressure </td><td><input type="number" step="any" id="inP"></td><td>Psia</td></tr>
<tr><td>Mole Percent H2S </td><td><input type="number" step="any" id="inH2S"></td><td>%mole</td></tr>
<tr><td>Mole Percent CO2 </td><td><input type="number" step="any" id="inCO2"></td><td>%mole</td></tr>
<tr><td>Mole Percent N2 </td><td><input type="number" step="any" id="inN2"></td><td>%mole</td></tr>
<tr><td>Water Salinity </td><td><input type="number" step="any" id="inWS"></td><td>ppm</td></tr>
</table>
<br>
<table>
<tr><td><u>Correlation</u></td><td></td></tr>
<tr><td>&nbsp</td></tr>
<tr>
<td>Bubble Point Pressure(Pb) </td>
<td>
<select id="cor1">
<option value="none"></option>
<option value="VB">Vasquez and beggs</option>
<option value="AM">Al-Marhoun</option>
<option value="G">Glaso</option>
<option value="PF">Petrosky and Farshad</option>
<option value="S">Standing</option>
</select>
</td>
</tr>
<tr>
<td>Solution GOR(Rs)</td>
<td>
<select id="cor2">
<option value=" "></option>
<option value="VB">Vasquez and beggs</option>
<option value="AM">Al-Marhoun</option>
<option value="G">Glaso</option>
<option value="PF">Petrosky and Farshad</option>
<option value="S">Standing</option>
</select>
</td>
</tr>
<tr>
<td>Oil Formation Volume Factor(Bo) </td>
<td>
<select id="cor3">
<option value=" "></option>
<option value="VB">Vasquez and beggs</option>
<option value="AM">Al-Marhoun</option>
<option value="G">Glaso</option>
<option value="PF">Petrosky and Farshad</option>
<option value="S">Standing</option>
</select>
</td>
</tr>
<tr>
<td>Oil Viscosity(µo) </td>
<td>
<select id="cor4" size="">
<option value=" "></option>
<option value="CC">Chew Connally</option>
<option value="BR">Beggs Robinson</option>
</select>
</td>
</tr>
<tr>
<td>Water Viscosity(µw) </td>
<td>
<select id="cor5" size="">
<option value=" "></option>
<option value="Mc">Mccain</option>
<option value="BB">Brill and Beggs</option>
</select>
</td>
</tr>
</table>
<br>
<button type="button" class="conti" onclick="location.href='Out';" >Continue</button><button type="submit" id="cb" class="cal">Calculate</button>
<button type="button" class="rest" onclick="res()">Reset</button>
<br>
<table class="rlt">
<tr><td><u>Result</u></td><td></td></tr>
<tr><td>Pb</td><td><p id="pb">{{finalpb}}</p></td></tr>
<tr><td>Rs(Solution GOR)</td><td><p id="rs"></p></td></tr>
<tr><td>Bo</td><td><p id="bo"></p></td></tr>
<tr><td>Co</td><td><p id="co"></p></td></tr>
<tr><td>µo</td><td><p id="uo"></p></td></tr>
<tr><td>ρo</td><td><p id="po"></p></td></tr>
<tr><td>Z Factor</td><td><p id="zf"></p></td></tr>
<tr><td>Bg</td><td><p id="bg"></p></td></tr>
<tr><td>ρg</td><td><p id="pg"></p></td></tr>
<tr><td>µg</td><td><p id="ug"></p></td></tr>
<tr><td>Bw</td><td><p id="bw"></p></td></tr>
<tr><td>µw</td><td><p id="uw"></p></td></tr>
<tr><td>ρw</td><td><p id="pw"></p></td></tr>
<tr><td>Cw</td><td><p id="cw"></p></td></tr>
<tr><td>IFT oil-water</td><td><p id="iow"></p></td></tr>
<tr><td>IFT oil-gas</td><td><p id="iog"></p></td></tr>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
$('#fm').on('submit',function (e) {
$.ajax({
type: 'post',
url: '/App',
data: $('#fm').serialize(),
success: function (q) {
document.getElementById("pb").innerHTML= q;
}
});
e.preventDefault();
});
</script>
<br/>
<footer class="footer">
<p>Copyright © Invigour Energy 2016</p>
</footer>
</form>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script>
<!-- Just to make our placeholder images work. Don't actually copy the next line! -->
<script src="http://getbootstrap.com/assets/js/vendor/holder.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="http://getbootstrap.com/assets/js/ie10-viewport-bug-workaround.js"></script>
</body>
</html>
This is my html
Please have a look at my ajax part only

Updated response:
Let me rephrase my original answer: Don't use AJAX. it is completely unnecessary. Delete all of your script items. I just took your code and made it work on my local flask environment nicely without any AJAX. Here is what you need to do:
1) Update your 'buttons' so that they are inputs, type=submit and give them the value of the name of the button you desire (e.g. Calculate).
2) Your form inputs do not have a 'name' attribute. Without that, the form has no key/value association. For example, look at your inOG input. You need to give it a name...something like name="inOG".
3) I don't know why you have your C drive as a configuration item. Maybe it's a Windows thing?
Now when you debug, you should see the form values come in nicely.
You are running into problems for a few reasons:
1) Your form is far too busy. Ideally, in my experience, the form should really only contain the necessary inputs and labels. Also, it is generally not wise to format an html page using tables. You might consider using Flask-WTF if you don't feel like coding out a form in it's entirety. One of the nice things of Flask is the ability to use templates like WTF.
2) If you set up the form nicely, then you won't even need to use AJAX, which might be preferable in your case. The once the form is submitted, your Flask code should do the rest.
2) If you are bent on using AJAX it's worth noting that your AJAX post is right in the middle of your form code. Since your browser reads code sequentially, it is picking up an AJAX post before the form has finished rendering. You should insert your <script> tag either at the top of the body or at the bottom of it.
3) You are using JQuery, which means you need to wrap any executable code in a $(document).ready function. So, once you have moved your script as mentioned above, you should write is as follows:
<script>
$(document).ready(function(){
$('#fm').on('submit',function (e) {
$.ajax({
type: 'post',
url: '/App',
data: $('#fm').serialize(),
success: function (q) {
document.getElementById("pb").innerHTML= q;
}
});
e.preventDefault();
});
}
In summary, I would suggest cleaning up your form and doing away with AJAX altogether. Looking at your form data, it doesn't seem like there is anything special that would require a break away from normal form submission.
Good Luck!

So after dealing with my own issues in Flask and AJAX, I wouldn't say don't use AJAX. As an example, I had a form that needed to be submitted and it took long enough to generate a 504. Sometimes AJAX is necessary.
In the off-case where it is necessary and you happen to be using Flask (and/or FLASK-WTF) you first need to update your form element to use the new event. This can be done with the following addition.
{{ form.my_element(**{"onchange":"my_ajax_function()"}) }}
The dictionary is passed back as a kwarg to Flask forms and sets the onchange event to use my_ajax_function() (just replace this with "onclick" if it's a button)
Next update your javascript with the new function. This function should do the following:
Get any fields required to perform this work
Start the ajax request and include the url (route), the data to be sent (if any), and what action to perform on a successful/failed request.
This will update any fields as required and keep data in existing fields. I will say that it is much easier on life if you avoid AJAX and let Flask do it's thing, but sometimes this is unavoidable.
I haven't tried just returning without a response instead of using render_template, redirect, or make_response from a post request to see if the fields remain as they were, but it's definitely something to experiment with.
I've only used AJAX for creating dynamic SelectFields, but there are some promising articles on form submissions, just looks like FlaskForms doesn't know how to convert this type of request back to the Form object since they are sent as query parameters, so you'll need to manually validate the fields after they have returned. How to submit a Flask-WTF form with Ajax

Related

How can I toggle image source only during input focus?

Summary: I've created a search bar with three inputs: name, date of birth, and social security number. The functionality is all there, but I am attempting to elevate the design and am running into an issue on input focus.
When the user selects the inputs, there are focus effects in my CSS. What I am trying to do is toggle the images on input focus. Currently they are written like this:
<div class="adv-searchbar__wrapper__search-box">
<span class="column-1"><img src="/img/person-name.png" class="input-ico"/><input type="text" class="input" id="adv-input-1" placeholder="John Adam Smith"></span>
<span class="column-2"><input type="date" class="input" id="adv-input-2" placeholder="MM / DD / YY"></span>
<span class="column-3"><img src="/img/person-ssn.png" class="input-ico"/><input type="text" class="input" id="adv-input-3" placeholder="### - ## - ####"></span>
<button type="submit" class="advSearchBtn"><img src="/img/search_white.png"/></button>
</div>
The user can either click the button to execute the next function, or use the Enter key.
Effort: I've tried using if-else statements in jQuery when the user Clicks an input. The issue with that that I've found is that I am not sure how to 'measure' when the user leaves the input. So while the image will change correctly, it will not change back once the user moves on.
$('.input').click(function() {
let currIco = $(this)[0].previousSibling.src.slice(0, -4);
if ($(this).is(':focus')) {
console.log('input is focused');
currIco = currIco + '__focus.png';
$(this)[0].previousSibling.src = currIco;
} else {
console.log('input is blurred');
}
});
I've found several tutorials for changing images on click or on hover, but I haven't been able to implement those solutions to my needs.
You say in a comment that the only reason you didn't use CSS is because the images are not in the input.
As CSS is still an option for you and it is much easier to achieve in CSS (plus you haven't got a JS answer yet), take a look at the solution below.
FYI CSS-only is also a more efficient option - the more client-side processing you add, the slower the page load and the worse for SEO and user experience.
.column-1 input, .column-3 input {
background-repeat: no-repeat;
background-position: top left;
padding-left: 40px;
}
.column-1 input {
background-image: url(https://lorempixel.com/output/abstract-q-c-30-30-1.jpg);
}
.column-1 input:focus {
background-image: url(https://lorempixel.com/output/abstract-q-c-30-30-2.jpg);
}
.column-3 input {
background-image: url(https://lorempixel.com/output/abstract-q-c-30-30-3.jpg);
}
.column-3 input:focus {
background-image: url(https://lorempixel.com/output/abstract-q-c-30-30-4.jpg);
}
<div class="adv-searchbar__wrapper__search-box">
<span class="column-1">
<input type="text" class="input" id="adv-input-1" placeholder="John Adam Smith">
</span>
<span class="column-2"><input type="date" class="input" id="adv-input-2" placeholder="MM / DD / YY"></span>
<span class="column-3"><input type="text" class="input" id="adv-input-3" placeholder="### - ## - ####"></span>
<button type="submit" class="advSearchBtn"><img src="/img/search_white.png"/></button>
</div>
Obviously I haven't applied your styling to the inputs because you hadn't included it, but you can apply that the same way excluding the image.
You could, alternatively to the existing answer (provided by FluffyKitten), create a <label> element and place it after the <input>.
I too, don't recommend using JavaScript over CSS if you are indeed able to get it done in CSS.
In this case, you can separate the icon (and therefore the styling) from the rest of the input field if you so desire.
.adv-searchbar__wrapper__search-box span {
position: relative;
}
.input {
box-sizing: border-box;
padding: 2px 2px 2px 20px;
max-height: 20px;
border: 1px solid #888;
}
.input~.icon {
position: absolute;
left: 2px;
top: 0px;
height: 16px;
width: 16px;
background-image: url('https://via.placeholder.com/16?text=icon');
background-repeat: no-repeat;
}
.input:focus~.icon {
filter: blur(1px);
background-image: url('https://via.placeholder.com/16/FF9900');
}
<div class="adv-searchbar__wrapper__search-box">
<span class="column-1">
<input type="text" class="input" id="adv-input-1" placeholder="John Adam Smith">
<label class="icon" for="adv-input-1"></label>
</span>
<span class="column-2">
<input type="date" class="input" id="adv-input-2" placeholder="MM / DD / YY">
</span>
<span class="column-3">
<input type="text" class="input" id="adv-input-3" placeholder="### - ## - ####">
<label class="icon" for="adv-input-3"></label>
</span>
<button type="submit" class="advSearchBtn">
<img src="https://via.placeholder.com/16?text= "/>
</button>
</div>
Here is an other way, using focus on parent element.
span:focus-within .input-ico-focus {
display: inline-block;
}
span:focus-within .input-ico {
display: none
}
span .input-ico-focus {
display: none
}
span .input-ico {
display: inline-block;
}
.input-ico, .input-ico-focus {
width: 16px;
}
<div>
<span class="column-1">
<img src="https://i.stack.imgur.com/pd8J3.png" class="input-ico">
<img src="https://i.stack.imgur.com/XdkNO.png" class="input-ico-focus">
<input type="text" class="input" id="adv-input-1" placeholder="John Adam Smith">
</span>
</div>

html - make column appear after clicking on button

I've been playing around with HTML and I created a column that immediately appears when I open my file in a browser. I tried moving the column and row classes around but I can't figure out how to get it so that the column doesn't appear until after I select an option from the dropdown menu. I was wondering how I could fix this issue?
<html>
<head>
<title>Testing Display</title>
</head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.center{
text-align: center;
border: 3px solid #73AD21;
}
{
box-sizing: border-box;
}
.column {
float: left;
width: 30%;
padding: 10px;
height: 2000px;
}
.row:after {
content: "";
display: table;
clear: both;
}
</style>
<body>
<div class ="center">
<p><div><h1>Testing Display</h1></div><br /><p>
<div class="dropdown">
<form>
<select name="list" id="list" accesskey="target" onchange="display(this)">
<option value="none">Choose an option</option>
<option value="one">Option one</option>
</select>
<input type=button value="Select" onclick="display()"/>
<div id="add"></div>
</form>
</div>
</div>
<div class="row">
<div class="column" style="background-color:#aaa;">
<h2>Column 1</h2>
<p>Some text..</p>
<div id="div"></div>
</div>
</div>
<script src="order.js"></script>
</body>
</html>
Have the initial visibility of column to hidden.
Have a Javascript function to add a new class to column onChange. Something like this
function onSelect() {
//or add id to easily access unique single element.
var element = document.getElementByClassName("column")[0];
element.classList.add("showCol");
}
.column {
visibility: hidden;
...
}
.showCol {
visibility: visible;
...
}
Can also add styles and remove style onChange instead of toggling classes.
Javascript Solution, call this method in onchange event of drop down list:
function ddlChange(){
if (document.getElementById("list").value === "one"){
document.getElementsByClassName("column").style.display = "table-cell";
}
}
Using jQuery:
$("#list").change(function () {
if($('#list option:selected').val() === "one")
$(".column").css("display","table-cell");
});
Alternatively, you can also try to add or remove a class instead of changing inline CSS value.

What would be the best way to make a sort of drop-down-more-info div?

I have 4 divs with a more-info button on the bottom of each, like so:
http://codepen.io/anon/pen/VpVbPq
And when a user presses ' more info ' I would like for it to extend to the bottom and show extra info, obviously.
The problem is under the more-info div, text is seen, but what if I want to hide whats under it, even if its opacity is 0.6 ?
I thought it would've been the best if I draw what I need, so here:
Codepen code below:
html
<body>
<div class="wrapper">
<div class="info">
<p>
dummy text
</p>
<div class="more-info">more info</div>
</div>
<div class="info"><div class="more-info">more info</div></div>
<div class="info"><div class="more-info">more info</div></div>
<div class="info"><div class="more-info">more info</div></div>
</div>
</body>
css
.wrapper {
width: 1045px;
margin: 0 auto;
}
.info {
width: 500px; height: 200px;
background-color: #1A5AB6;
display: inline-block;
margin: 10px;
position: relative;
font-size: 20px;
overflow: hidden;
}
.more-info {
width: 100%; height: 40px;
background-color: #0C1B44;
bottom: 0; left: 0;
display: inline-block;
position: absolute;
font-size: 20px;
color: white;
line-height: 35px;
text-align: center;
opacity: 0.6;
}
.more-info:hover {background-color: #010716;}
In order to have the text expand, you can use a little jQuery to set the height to automatically adapt to however much text there is, and hide the 'more info' button entirely:
$(".more-info").on("click", function() {
$(this).css("opacity", "0");
$(this).parent().css("height", "auto");
});
With regards to not having the text visible behind the 'more info' button, you would need to set the opacity to 1:
.more-info {
opacity: 1;
}
This naturally distorts the colour a little, but you can always change the background colour and hover colour to cover this.
I've created an updated pen showcasing this here.
Hope this helps! :)
change your class selector definition as shown below:
.more-info {
width: 100%; height: 20%;
background-color: #0C1B44;
font-size: 20px;
color: white;
display: block;
text-align: center;
opacity: 0.6;
}
Then add this css for your paragraph element:
p {
height: 75%;
overflow: hidden;
margin: 5px;
}
Your question: "what would be the best way to make a sort of drop-down-more-info div?"
There is a built in function in Boot Strap that allows you to use a "data" class that does all the crunching for you. Just call on their css and js files externally or host on your server. Familiarize yourself with their data classes and call on their css/js classes to simplify previously arduous coding, like revealing a hidden DIV on click!
Note the data-toggle="collapse" and data-target="#more_info" lines in my div that holds the span tag that is the control for revealing the hidden <div id="more_info">:
`<div data-toggle="collapse" data-target="#more_info"><span class="glyphicon glyphicon-search"></span> <span title="Click for more info">more info</span></div>`
Then note the class in my hidden div. Note the id of the hidden div and the data-target #more_info. This can be used for classes as well, ie: .more_info. Everything is explained in more detail at bootstrap Github or their official site: http://getbootstrap.com/
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"> </script>
</head>
<body>
<div class="wrapper">
<div class="info">
<p>
Honestly, Bootstrap would be the easiest way to accomplish this without a doubt. Just click the more info button below.
</p>
<div data-toggle="collapse" data-target="#more_info"><span class="glyphicon glyphicon-search"></span> <span title="Click for more info">more info</span></div>
<div id="more_info" class="collapse">Some hidden infomration you ony want to be seen when the user click on the control link.</div>
</div>
or add three divs floating perfectly without all the css, each with drop downs more info.
<body>
<div class="wrapper row">
<div class="col-md-4">
<p>
Honestly, Bootstrap would be the easiest way to accomplish this without a doubt. Just click the more info button below.
</p>
<div data-toggle="collapse" data-target="#more_info">
<span class="glyphicon glyphicon-search"></span>
<span title="Click for more info">more info</span> </div>
<div id="more_info" class="collapse">
Some hidden information you only want to be seen when the user click on the control link.
</div>
</div>
<div class="col-md-4">
<p>
Some other information we want to have a hidden drop down with more info for.
</p>
<div data-toggle="collapse" data-target="#more_info2">
<span class="glyphicon glyphicon-search"></span>
<span title="Click for more info">more info</span>
</div>
<div id="more_info2" class="collapse">
Some hidden information you only want to be seen when the user click on the control link.</div>
</div>
<div class="col-md-4">
<p>
Yet another div with info that has a drop down menu for more info included below.
</p>
<div data-toggle="collapse" data-target="#more_info3">
<span class="glyphicon glyphicon-search"></span>
<span title="Click for more info">more info</span>
</div>
<div id="more_info3" class="collapse">
Some hidden infomration you ony want to be seen when the user click on the control link.
</div>
</div>
Best of luck.

Two listboxes with equal width in one container div

I try to create complex control in my online application. Control have two listboxes and two buttons between. Width of listboxes (listbox-target, listbox-source) must be equal. Width of control-buttons can be fixed. Height of all controls must be equal too. HTML and JS code below.
I try to make this with css, but can't. I wrote javascript to calculacte width and height of each element.
Width of listbox-target = listbox-source = ('fullwidth of attributeref-two-listboxes' - 'width of control-buttons') / 2.
It work good, but must be called everytime from resize event. Sometimes resize event is not fire and width of controls not change.
I think, best of all is make this with css only, but how?! Please, help!
function resizeAttributerefTwoListboxes() {
var is_ff = navigator.userAgent.toLowerCase().indexOf('firefox') > -1,
is_ie = navigator.userAgent.toLowerCase().indexOf('MSIE') > -1 || /Trident.*rv[ :]*(\d+\.\d+)/.test(navigator.userAgent);
$("div.attributeref-two-listboxes div").removeAttr("style");
$("div.attributeref-two-listboxes").each(function(){
var that = $(this),
target = that.find(".listbox-target"),
source = that.find(".listbox-source"),
control = that.find(".control-buttons");
if (this.offsetWidth < 420) {
control.find('a[method="add"] > i').addClass("fa-angle-up").removeClass("fa-angle-left");
control.find('a[method="remove"] > i').addClass("fa-angle-down").removeClass("fa-angle-right");
target.css({"width":"100%"});
control.css({"width":"100%"});
control.children().css({"display":"inline-block"});
source.css({"width":"100%"});
} else { //horizontal alignment
control.find('a[method="add"] > i').addClass("fa-angle-left").removeClass("fa-angle-up");
control.find('a[method="remove"] > i').addClass("fa-angle-right").removeClass("fa-angle-down");
var w = Math.ceil((this.offsetWidth - control[0].offsetWidth - (is_ff || is_ie ? 2 : 1))/2);
target.css({"width":w+"px"});
source.css({"width":w+"px"});
control.children().css({"height":(target[0].offsetHeight-20)+"px"}); //20 - paddings from top and bottom (10+10)
control.css({"height":target[0].offsetHeight+"px"});
}
});
}
<div class="attributeref-two-listboxes">
<div class="listbox-target" style="width: 549px;">
<select id="Objectint_chg_management_change_user" acode="chg_management_change_user" atype="8" astyle="3" aislist="0" class="form-control tooltipstered" multiple="multiple" style="max-width: 750px;" size="4" name="Objectint[chg_management_change_user][]"></select>
</div>
<div class="control-buttons" style="height: 90px;">
<div style="height: 70px;">
<a class="btn btn-primary option mover" target="Objectint_chg_management_change_user" source="Objectint_chg_management_change_user_select" method="add" href="#">
<i class="fa fa-angle-left"></i>
</a>
<a class="btn btn-primary option mover" target="Objectint_chg_management_change_user" source="Objectint_chg_management_change_user_select" method="remove" href="#">
<i class="fa fa-angle-right"></i>
</a>
</div>
</div>
<div class="listbox-source" style="width: 549px;">
<select id="Objectint_chg_management_change_user_select" acode="chg_management_change_user" atype="8" astyle="3" aislist="0" class="form-control" multiple="multiple" style="max-width: 750px;" size="4" name="[]">
<option value="68">User 1</option>
<option value="61">User 2</option>
<option value="76">User 3</option>
</select>
</div>
this is my control after right resize
this is my control after wrong resize
Flex-box allow to avoid using JS in some cases like your.
Link to jsfiddle
.
#media screen and (max-width: 500px) {
.flex_container {
flex-direction: column;
flex-basis: 100%;
}
.arrays_v {display : none}
.arrays_h {display : inline}
}
I suppose my my solution will be useful for you.
Use float: left and min-width.
The min-width should be at least the widths of the elements. If the section can span the entire width of the page, using 960px is not a bad idea because it displays well in most form factors (tablets, smartphones, PCs, occupies 1/2 of a 1080p display).
This way you can also avoid using display: inline-block which is not supported in older browsers (though that window keeps sliding forward so this isn't much of a problem these days except for enterprise web apps,etc.).
.attributeref-two-listboxes {
min-width: 960px;
overflow: hidden;
font-size: 0;
}
.chooser
{
float: left;
width: 300px;
height: 100px;
font-size: 14px;
}
.buttons
{
float: left;
}
.buttons input
{
width: 30px;
height: 30px;
background-color: rgb(34,131,203);
color: #fff;
border: 1px solid #333;
display: block;
margin: 13px 16px;
font-size: 16px;
}
<div class="attributeref-two-listboxes">
<select multiple size=4 class='chooser'>
<option>Uno</option>
<option>Dos</option>
<option>Tres</option>
</select>
<div class='buttons'>
<input type='button' value='<' />
<input type='button' value='>' />
</div>
<select multiple size=4 class='chooser'>
<option>Uno</option>
<option>Dos</option>
<option>Tres</option>
</select>
</div>

Image Radio Button Checked Display Issues

I am using image radio buttons which are working fine. However one of the radio buttons needs to be checked by default. However when this is set, it will not display the border around the checked image as it will when you click to select.
I have tried quite a few different things such has checked via html as well as javascript onload to no avail.
(Note there is only one radio button to select, this is because currently there is no 2nd option however there will be in the near future hence why we are pre checking it)
Any ideas?
<script type="text/javascript">
$(document).ready(function() {
$("a.radio-color-picture").click(function(){
var $id = $(this).attr('id');
$("a.radio-color-picture").removeClass('radio-color-border');
$("a#" + $id).addClass('radio-color-border');
});
});
function set_radio($inputid) {
$("input#" + $inputid).click();
}
</script>
<style type="text/css">
a.radio-color-picture {
border: 2px solid transparent;
display: inline-block;
height: 160px;
margin-right: 10px;
text-decoration: none;
width: 160px;
}
a.radio-color-picture:hover {
border:2px solid #d13a7a;
}
a.radio-color-border {
border:5px solid #d13a7a;
}
a#color {
background: url("<?php echo get_bloginfo('wpurl');?>/wp-content/themes/Impreza/_customimages/thumbnail.jpg") no-repeat scroll 0 0 white;
}
.hidden {
left: -10000px;
position: absolute;
top: -1000px;
}
</style>
<input type="radio" value="CHAR" name="color" id="color" class="hidden" checked="checked" />
<a id="color" href="javascript:set_radio('color');" class="radio-color-picture"> </a>
Cheers :)
This could actually be done much simpler :
Demo
Javascript :
$(document).ready(function(){
$('a.radio-color-picture').click(function(){
$(this).prev('input.hidden').click();
return false;
});
});
HTML (make sure you use unique ids !)
<input type="radio" value="CHAR" name="color" id="color" class="hidden" />
<a data-idinput="color" id="link" class="radio-color-picture"> </a>
<input type="radio" value="CHAR2" name="color" id="color2" class="hidden" checked="checked" />
<a data-idinput="color2" id="link2" class="radio-color-picture"> </a>
<input type="radio" value="CHAR3" name="color" id="color3" class="hidden" />
<a data-idinput="color3" id="link3" class="radio-color-picture"> </a>
And this is the main trick in CSS (only for IE >= 9) :
input.hidden:checked + a {
border:5px solid #d13a7a;
}
Edit : Demo for older versions of IE compatibility
to show the css to default checked you have to add the css 'class' or 'id' by default to the pre checked radio button and its respective href tag.

Categories

Resources