My elements are created from data in a CSV file that updates every 1 minute.
I'm trying to update these elements as follows:
Remove those whose data is no longer in the CSV file
Create new ones that appeared in the CSV file
Keep without edit those that still exist in the CSV file
The CSV file looks like this:
label,value,market,numbergame
A,www.siteA.com,www.webA.com,1
B,www.siteB.com,www.webB.com,2
C,www.siteC.com,www.webC.com,3
D,www.siteD.com,www.webD.com,4
And an example of an update from it would be this (Disappearing B and D and appearing G, Z and Y):
label,value,market,numbergame
A,www.siteA.com,www.webA.com,1
G,www.siteG.com,www.webG.com,2
C,www.siteC.com,www.webC.com,3
Z,www.siteZ.com,www.webZ.com,4
Y,www.siteY.com,www.webY.com,5
To call the function that updates every 1 minute the data I use this script:
<script id="auto-update-csv">
let interval_csv
window.addEventListener('DOMContentLoaded', () => {
interval_csv = setInterval(refresh_csv, 30000); // refresh every 60 secs
})
function refresh_csv() {
d3.csv("Lista_de_Jogos.csv", function(data){caixa_suspensa_5(data)});
}
</script>
The general script that contains the function called by autoupdate for this job (create the elements and update) is described like this:
<body style="background-color:black;">
<div style="color:white;font-weight:bold;overflow:hidden;overflow-y:scroll;" class="grid games" id="Lista-de-Jogos-Lateral">
<script id="script-da-caixa-de-selecao-suspensa-5">
var select_5 = d3.select("#Lista-de-Jogos-Lateral")
.append("div")
.attr("id","select-box-5")
.style("width","100%")
.style("max-height","574px");
function valorparaiframe(iframevalue) {
let link = iframevalue;
let newurl = link.split("OB_EV")[1];
newurl = newurl.split("/")[0];
return "https://sports.staticcache.org/scoreboards/scoreboards-football/index.html?eventId=" + newurl;
}
function caixa_suspensa_5(data) {
let update_5 = select_5.selectAll("div")
.data(data);
update_5.exit().remove();
const div = update_5.enter().append("div").attr("class","matches")
div.append("iframe").merge(update_5)
.attr("src",d => valorparaiframe(d.value))
.style("width","100%")
.style("height","282");
div.append("form").merge(update_5)
.attr("action",d => d.market)
.attr("target","_blank")
.style("width","100%")
.append("input").merge(update_5)
.attr("type","submit")
.attr("target","_blank")
.style("width","100%")
.attr("value","Jogo Betfair")
div.append("form").merge(update_5)
.append("input").merge(update_5)
.attr("type","text")
.attr("id",d => "barra-de-texto-para-grafico-" + d.numbergame)
.style("width","100%")
div.append("img").merge(update_5)
.attr("type","text")
.attr("src","https://sitedeapostas-com.imgix.net/assets/local/Company/logos/betfair_logo_transp.png?auto=compress%2Cformat&fit=clip&q=75&w=263&s=c1691b4034fd0c4526d27ffe8b1e839c")
.attr("name",d => "grafico-betfair-" + d.numbergame)
}
d3.csv("Lista_de_Jogos.csv", function(data){caixa_suspensa_5(data)});
</script>
</div>
</body>
As seen, I tried to work with this part in the idea of trying to update the elements:
let update_5 = select_5.selectAll("div")
.data(data);
update_5.exit().remove();
const div = update_5.enter().append("div").attr("class","matches")
But when the trigger is activated, it becomes a huge mess with new elements being created and the old ones not being removed properly.
Which model should I use so that it works according to my need?
I use d3.js version 4:
<script src="https://d3js.org/d3.v4.js"></script>
The page template with multiple columns that are created and updated would look like this:
But when it updates every 1 minute, it turns this around, totally different from what I expected, the other elements disappear and keep only the <iframe>:
Here is the <style> used inside the <head> for those who want more ease to recreate the page:
<style>
{
box-sizing: border-box;
}
.matches {
text-align:center;
float: left;
width: 355px;
border: 1px solid white;
border-collapse: collapse;
}
.column {
text-align:center;
float: left;
width: 355px;
border: 1px solid white;
border-collapse: collapse;
}
.grid {
float: left;
width: 1431px;
}
.row:after {
content: "";
display: table;
clear: both;
}
.button {
background-color: #33ccff;
color: black;
font-weight: bold;
}
input[type=submit] {
background-color: #33ccff;
color: black;
font-weight: bold;
}
html {
overflow: scroll;
overflow-x: hidden;
}
::-webkit-scrollbar {
width: 0px; /* remove scrollbar space /
background: transparent; / optional: just make scrollbar invisible /
}
/ optional: show position indicator in red */
::-webkit-scrollbar-thumb {
background: #FF0000;
}
</style>
"it becomes a huge mess". Yes it will. Let's look at part of your code. Remember that when you use append you return a selection of the appended elements:
div // a selection of entered div elements
.append("form") // append forms to the divs, return a selection of forms
.merge(update_5) // merge a selection of forms with a the update selection of divs
... // style the selection of divs and forms
.append("input") // append inputs to the selection of divs and forms
.merge(update_5) // merge the update selection of divs with the inputs
... // style the inputs and the divs
The above is clearly going to cause elements to be appended all over the place where you don't want.
First, we're merging different types of elemenrts, and because of this, second, we're appending inputs to divs and forms when we probably don't want to. Essentially we're appending things to all sorts of things that shouldn't have things appended to them. The divs that remain each iteration get more and more contaminated with excess elements, and no where do you remove those elements (you shouldn't look to remove those excess elements, you should look to not add them in the first place).
Rather than fix the code you have as is, I'm going to suggest an approach suggested by Altocumulus in the comments: "Instead of binding data by index, which is the default, try using a key function to properly match data records": If the data for a single entry doesn't change, there is no need to update it once it is appended. Instead we only need to remove div elements for which the data has been removed, this means we only need to append and modify elements on enter:
let update_5 = select_5.selectAll(".matches")
.data(data,d=>d.label);
update_5.exit().remove();
// Enter new divs:
const enter = update_5.enter()
.append("div")
.attr("class","matches")
...
// Append the children to entered divs:
enter.append("form")
.attr("action",d => d.market)
.attr("target","_blank")
.style("width","100%")
.append("input")
.attr("type","submit")
.attr("target","_blank")
.style("width","100%")
.attr("value","Jogo Betfair");
...
There's no need to merge here as we aren't modifying existing elements if the data for those elements still exists in the data array (regardless of index).
Here's an example with everything except the iframe (as you haven't included example data with valid paths):
let csv1 = d3.csvParse(d3.select("#csv1").remove().text());
let csv2 = d3.csvParse(d3.select("#csv2").remove().text());
let csv = [csv1, csv2];
let i = 0;
var select_5 = d3.select("#Lista-de-Jogos-Lateral")
.append("div")
.attr("id","select-box-5")
.style("width","100%")
.style("max-height","574px");
function update() {
let data = csv[i++%2];
let update_5 = select_5.selectAll(".matches")
.data(data,d=>d.label);
update_5.exit().remove();
// Enter new divs:
const enter = update_5.enter()
.append("div")
.attr("class","matches")
// Append the children to entered divs:
enter.append("form")
.attr("action",d => d.market)
.attr("target","_blank")
.style("width","100%")
.append("input")
.attr("type","submit")
.attr("target","_blank")
.style("width","100%")
.attr("value","Jogo Betfair");
enter.append("form")
.append("input")
.attr("type","text")
.attr("id",d => "barra-de-texto-para-grafico-" + d.numbergame)
.style("width","100%")
.attr("value", d=>d.label);
enter.append("img")
.attr("type","text")
.attr("src","https://sitedeapostas-com.imgix.net/assets/local/Company/logos/betfair_logo_transp.png?auto=compress%2Cformat&fit=clip&q=75&w=263&s=c1691b4034fd0c4526d27ffe8b1e839c")
.attr("name",d => "grafico-betfair-" + d.numbergame);
}
update();
setInterval(update,2000);
{
box-sizing: border-box;
}
.matches {
text-align:center;
float: left;
width: 355px;
border: 1px solid white;
border-collapse: collapse;
}
.column {
text-align:center;
float: left;
width: 355px;
border: 1px solid white;
border-collapse: collapse;
}
.grid {
float: left;
width: 1431px;
}
.row:after {
content: "";
display: table;
clear: both;
}
.button {
background-color: #33ccff;
color: black;
font-weight: bold;
}
input[type=submit] {
background-color: #33ccff;
color: black;
font-weight: bold;
}
html {
overflow: scroll;
overflow-x: hidden;
}
::-webkit-scrollbar {
width: 0px; /* remove scrollbar space /
background: transparent; / optional: just make scrollbar invisible /
}
/ optional: show position indicator in red */
::-webkit-scrollbar-thumb {
background: #FF0000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.1.1/d3.min.js"></script>
<div style="color:white;font-weight:bold;overflow:hidden;overflow-y:scroll;" class="grid games" id="Lista-de-Jogos-Lateral">
<pre id="csv1">label,value,market,numbergame
A,www.siteA.com,www.webA.com,1
B,www.siteB.com,www.webB.com,2
C,www.siteC.com,www.webC.com,3
D,www.siteD.com,www.webD.com,4</pre>
<pre id="csv2">label,value,market,numbergame
A,www.siteA.com,www.webA.com,1
G,www.siteG.com,www.webG.com,2
C,www.siteC.com,www.webC.com,3
Z,www.siteZ.com,www.webZ.com,4
Y,www.siteY.com,www.webY.com,5</pre>
</div>
The above uses d3.csvParse() instead of d3.csv() to create csv data - which allows the snippet to be entirely self-contained, this requires the use of the pre elements to hold the csv data.
Is there any way to have a show more option/link in jsTree?
I want to show only part of the children and have a link to expand to show all elements.
I tried a few google searches but could not find a solution. Any help/hint would be useful.
Let's say parent-1 has 10 child nodes and the Main Root has 5 parent nodes.
Main Parent
- Parent - 1
- child-1
- child-2
- child-3
show 7 more parent-1 elements //LINK
- Parent - 2
- child-1
- child-2
- Parent - 3
- child-1
- child-2
show 2 more Main Parent elements //LINK
I'm trying to achieve the following result
Is this possible? Are there any available plugins for this? Are there any alternatives for jsTree that support this?
You could feasibly use classes/childElement count to work this. Depending on what you want to show, you could use ids/classes to leave the elements you want to stay visible or optionally show/hide. The same principle can be applied to both child elements (say list items in a list) and higher parent elements, so once you have the first function, it can easily be adapted.
I've included a list example here to give you the idea (it's in plain javascript and you could tweak it a bit..) Jquery would make the js shorter, but it's always good to know the vanilla i reckon..
var x = document.getElementById("show");
//var root = document.getElementsByTagName('body')[0];
var count = x.childElementCount;
var btn1 = document.getElementById("ulmore");
btn1.innerHTML = "+ Show all " + count + " li children";
document.getElementById("ulmore").addEventListener("click", showmore);
function showmore() {
//var d = document.getElementsByClassName("tg1").length;
//use d if you want to show "show d more children" instead of the full amount of children
var el = document.getElementsByTagName("li");
var i;
for (i = 0; i < el.length; i++) {
if (el[i].classList.contains("tg1")) {
//el[i].style.display = "block"; works
el[i].classList.toggle('more');
if (el[i].classList.contains("more")) {
btn1.innerText = "Hide children";
} else {
btn1.innerText = "+ Show all " + count + " li children";
}
}
}
}
body {
padding: 1em;
font-size: 10pt;
}
ul {
list-style: none;
width: 10em;
padding: 0px;
}
li {
text-align: left;
line-height: 1.5;
background: lightblue;
border: 1px solid #444;
margin: 1px 0px;
padding: 2px;
}
span {
display: inline-block;
}
div {
display: inline-block;
width: 100%;
float: left;
margin: 1em 2em 1em 0em;
}
.tg1 {
background: lightsteelblue;
display: none;
}
.more {
background: lightsteelblue;
display: block;
}
/*.tog2 {
display: none;
}
.grow {
background: yellow;
display: inline-block;
}*/
<body>
<div id="ulbit">
<h4>Demo List</h4>
<ul id="show">
<li>One</li>
<li>Two</li>
<li class="tg1">Three</li>
<li class="tg1">Four</li>
<li class="tg1">Five</li>
<li class="tg1">Six</li>
<li class="tg1">Seven</li>
<li class="tg1">Eight</li>
</ul>
<span id="ulmore"></span>
</div>
<!-- <div class="tog2">
Div 2 hello
</div>
<div class="tog2">
Div 3
</div>
<span id="divmore"></span>-->
</body>
Here's a fiddle link (with body 'parent' elements) included in code.
(Note: even a <br> tag [when used between divs] will be regarded as a top-level element .. I'd think that count by tagName (or className) would be most useful if you want to count different types of 'parent' elements (as opposed to counting children of body). Examples of both (children of body and getElementsByTagName) are included in the fiddle)
Hope this helps
did you try to use "before_open.jstree" event to show the tree the way you need?
see the example (I use part of the demo page from the jstree site):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jstree basic demos</title>
<style>
html { margin:0; padding:0; font-size:62.5%; }
body { max-width:800px; min-width:300px; margin:0 auto; padding:20px 10px; font-size:14px; font-size:1.4em; }
h1 { font-size:1.8em; }
.demo { overflow:auto; border:1px solid silver; min-height:100px; }
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" />
</head>
<body>
<h1>Interaction and events demo</h1>
<button id="evts_button">select node with id 1</button> <em>either click the button or a node in the tree</em>
<div id="evts" class="demo"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
<script>
// interaction and events
$('#evts_button').on("click", function () {
var instance = $('#evts').jstree(true);
instance.deselect_all();
instance.select_node('1');
});
$('#evts')
.on("changed.jstree", function (e, data) {
if(data.selected.length) {
alert('The selected node is: ' + data.instance.get_node(data.selected[0]).text);
}
})
.on("before_open.jstree", function (e, data,a,b,c,d) {
$('#' + data.node.id + ' ul li:nth-child(n + 2)').hide();
var str = '<li class="jstree-node jstree-leaf jstree-last" role="treeitem">press to show ' + $('#' + data.node.id + ' ul li:nth-child(n + 2)').length + ' more items</li>';
var li = $(str).on('click', function(a,b,c,d) {$(a.target).parent().find('li').show(); $(a.target).hide()});
$('#' + data.node.id + ' ul').append(li);
})
.jstree({
'core' : {
'multiple' : false,
'data' : [
{ "text" : "Root node", "children" : [
{ "text" : "Child node 1", "id" : 1 },
{ "text" : "Child node 2" }
]}
]
}
});
</script>
</body>
</html>
I hope this helped.
There are random number of div's as show below, I am trying to clone these div on click. when cloning I want to change the content to actual content + no of clones it has (based on content of span , not the id or classes of "clone-this")
eg.
If I click the first "chrome" div, since the body already have "chrome (1) and chrome (2)" , div with content "chrome (3)" Should appear .
If I click the 2nd div ie. "Mozilla Firefox", since there is no cloned version, a div with content "Mozilla Firefox (1)" should appear.
and so on.
I tried to make this, but when i clone the count is based on class , not the content . so clicking on "chrome" div will clone "chrome (5)" not "chrome (3)" .
Also in my implementation when i click the "chrome (1)" div, it will clone as "chrome (1)(5)" . I want this to be like "chrome (3)"
how can i achieve this?
note that there will be any number of divs at first. 5 is just for and example.
jsfiddle here
$(document).on('click', '.clone-this', function(){
var CloneContainer = $(this).clone();
var no = $('.clone-this').size();
CloneContainer.html(CloneContainer.html() + " (" + no + ")");
CloneContainer.appendTo('body');
});
.clone-this{
padding: 15px;
width: 100px;
text-align: center;
border: 1px solid #ccc;
margin: 10px auto;
cursor: pointer;
color: #444;
border: 1px solid #ccc;
border-radius: 3px;
font-family: monospace;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="clone-this"><span>Chrome</span></div>
<div class="clone-this"><span>Mozilla Firefox</span></div>
<div class="clone-this"><span>Safari</span></div>
<div class="clone-this"><span>Chrome (1)</span></div>
<div class="clone-this"><span>Chrome (2)</span></div>
To accomplish that, you should check "content" of each item and count the number of elements which have same text. But, there is one problem here; each element (for example Chrome, Chrome (1), Chrome (2)) has different content. So, you may split the text using parenthesis or you may use RegEx (recommended).
$(document).on('click', '.clone-this', function(){
var CloneContainer = $(this).clone();
var content = CloneContainer.find('span').html().split(' (')[0];
var no = $(".clone-this:contains('"+content+"')").size();
CloneContainer.html( CloneContainer.html() .split(' (')[0] + " (" + no + ")" );
CloneContainer.appendTo('body');
});
.clone-this{
padding: 15px;
width: 100px;
text-align: center;
border: 1px solid #ccc;
margin: 10px auto;
cursor: pointer;
color: #444;
border: 1px solid #ccc;
border-radius: 3px;
font-family: monospace;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="clone-this"><span>Chrome</span></div>
<div class="clone-this"><span>Mozilla Firefox</span></div>
<div class="clone-this"><span>Safari</span></div>
<div class="clone-this"><span>Chrome (1)</span></div>
<div class="clone-this"><span>Chrome (2)</span></div>
On the snippet above, you may see basic version of it. But you MUST consider the "similar content" issue like following.
Chrome
Chrome Mobile
Firefox
Firefox Mobile
Here is another way to get you going. I "trim" the clicked div to its base name and then loop through the divs and get the length of all which contain the same base name.
After that I modify the cloned element to fill in the right count of the cloned element appropriately:
var regExp = /\([0-9]+\)/;
$('.clone-this').click(function(e){
var target = e.target.textContent;
var matches = regExp.exec(target);
var elements = $('.clone-this');
var count = elements.length;
var index = 0;
if (null != matches) {
target = matches.input.substr(0, matches.input.lastIndexOf(" "));
}
for(var i = 0; i < count; i++){
index += (elements[i].textContent.indexOf(target) > -1) ? 1: 0;
}
var CloneContainer = $(this).clone();
CloneContainer.html(CloneContainer.html().split('(')[0] + "(" + index + ")" );
CloneContainer.appendTo('body');
});
.clone-this{
padding: 15px;
width: 100px;
text-align: center;
border: 1px solid #ccc;
margin: 10px auto;
cursor: pointer;
color: #444;
border: 1px solid #ccc;
border-radius: 3px;
font-family: monospace;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="clone-this"><span>Chrome</span></div>
<div class="clone-this"><span>Mozilla Firefox</span></div>
<div class="clone-this"><span>Safari</span></div>
<div class="clone-this"><span>Chrome (1)</span></div>
<div class="clone-this"><span>Chrome (2)</span></div>
MY code below lets me take an HTML selection and provide a more user friendly image clickable version. When an image is clicked, it selects the proper value in a hidden selection filed in the DOM.
I just need help in adjusting my code below to work on a selection that is on the page multiple times.
If it is on the page 10 times, I need to run this code 10 times.
I am not sure how to target each one separately though
Preview
HTML Selection gets turned into clickable Images like this below. The JavaScript reads the HTML Selection filed already on the page and clones it and replaces each value with images. It then hides the original selection field. When an image is clicked on, and appears selected, it is using JavaScript to select that value in the real hidden selector as well!...
Live Demo
http://jsfiddle.net/jasondavis/ov1a4apc/
JavaScript
jQuery(document).ready(function($) {
if ($('#page_template').length) {
//$('#page_template').hide().after('<div id="page_template_visual"></div>');
$('#page_template').after('<div id="page_template_visual"></div>');
$('#page_template option').each(function() {
var classname = $(this).val().replace('.php', '');
if ($(this).is("[selected]")) {
classname = classname + ' selected';
}
$('#page_template_visual').append('<small></small>' + $(this).text() + '');
});
if (!$('#page_template option[selected]').length) {
$('#page_template_visual a:first-child').addClass('selected');
}
$('#page_template_visual a').on('click', function() {
$('#page_template_visual a').removeClass('selected');
theValue = $(this).addClass('selected').attr('href');
$("#page_template").val(theValue).attr('selected', true);
return false;
});
}
});
HTML Select
<select name="page_template" id="page_template" selected="selected">
<option value="default">Default Template</option>
<option value="custom-archives.php">Archives Template</option>
<option value="wpi/pdf_quote_bold.php">Bold</option>
<option value="SOONcontact.php">Contact</option>
<option value="page-invoice.php">Invoice</option>
<option value="wpi/pdf_quote_modern.php">Modern</option>
<option value="wpi/pdf_quote.php">Traditional</option>
</select>
CSS
#page_template{
/* display: none; */
}
#page_template_visual {
margin: 0 -10px;
}
#page_template_visual a {
display: inline-block;
width: 129px;
height: 100px;
margin: 0 5px 5px;
text-align: center;
color: #333333;
font-weight: bold;
text-decoration: none;
background: url('http://i.imgur.com/7S9yzTY.png') no-repeat left top;
}
#page_template_visual a small {
height: 64px;
width: 119px;
display: inline-block;
margin: 5px 5px 5px 5px;
}
/* You can define images for the options here based on the classnames */
#page_template_visual a.template-both-sidebar-page {background-position: right -100px;}
#page_template_visual a.template-left-sidebar-page {background-position: right top;}
#page_template_visual a.template-right-sidebar-page {background-position: left -100px;}
#page_template_visual a.selected {
color: #559a08;
text-shadow: 1px 1px 0px #fff;
}
#page_template_visual a.selected small {
background: rgba(106,189,15,0.1) url('http://i.imgur.com/P0E1jmh.png') no-repeat center;
}
First, you need to change the page_template and page_template_visual ids to classes (in the HTML, JavaScript & CSS).
Then loop through all the elements with the page_template class, like this:
jQuery(document).ready(function($) {
$('.page_template').each(function() {
var $select = $(this);
// Keep a reference to this element so you can use it below.
var $visual = $('<div class="page_template_visual"></div>');
$select.after($visual);
$select.find('option').each(function() {
var $option = $(this);
var classname = $option.val().replace('.php', '');
if ($option.is("[selected]")) {
classname = classname + ' selected';
}
$visual.append('<small></small>' + $option.text() + '');
});
if (!$select.find('option[selected]').length) {
$visual.find('a:first-child').addClass('selected');
}
// The next line could have been:
// $visual.find('a').on('click', function() {
// But instead it uses event delegation, so only one
// event handler is registered, instead of one for each <a>.
$visual.on('click', 'a', function() {
$visual.find('a').removeClass('selected');
var value = $(this).addClass('selected').attr('href');
$select.val(value);
return false; // You don't need this, unless you really don't want the click event to bubble up.
});
});
});
jsfiddle
The below HTML/CSS/Javascript (jQuery) code displays the #makes select box. Selecting an option displays the #models select box with relevant options. The #makes select box sits off-center and the #models select box fills the empty space when it is displayed.
How do you style the form so that the #makes select box is centered when it is the only form element displayed, but when both select boxes are displayed, they are both centered within the container?
var cars = [
{
"makes" : "Honda",
"models" : ['Accord','CRV','Pilot']
},
{
"makes" :"Toyota",
"models" : ['Prius','Camry','Corolla']
}
];
$(function() {
vehicles = [] ;
for(var i = 0; i < cars.length; i++) {
vehicles[cars[i].makes] = cars[i].models ;
}
var options = '';
for (var i = 0; i < cars.length; i++) {
options += '<option value="' + cars[i].makes + '">' + cars[i].makes + '</option>';
}
$("#make").html(options); // populate select box with array
$("#make").bind("click", function() {
$("#model").children().remove() ; // clear select box
var options = '';
for (var i = 0; i < vehicles[this.value].length; i++) {
options += '<option value="' + vehicles[this.value][i] + '">' +
vehicles[this.value][i] +
'</option>';
}
$("#model").html(options); // populate select box with array
$("#models").addClass("show");
}); // bind end
});
.hide {
display: none;
}
.show {
display: inline;
}
fieldset {
border: #206ba4 1px solid;
}
fieldset legend {
margin-top: -.4em;
font-size: 20px;
font-weight: bold;
color: #206ba4;
}
fieldset fieldset {
position: relative;
margin-top: 25px;
padding-top: .75em;
background-color: #ebf4fa;
}
body {
margin: 0;
padding: 0;
font-family: Verdana;
font-size: 12px;
text-align: center;
}
#wrapper {
margin: 40px auto 0;
}
#myFieldset {
width: 213px;
}
#area {
margin: 20px;
}
#area select {
width: 75px;
float: left;
}
#area label {
display: block;
font-size: 1.1em;
font-weight: bold;
color: #000;
}
#area #selection {
display: block;
}
#makes {
margin: 5px;
}
#models {
margin: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<div id="wrapper">
<fieldset id="myFieldset">
<legend>Cars</legend>
<fieldset id="area">
<label>Select Make:</label>
<div id="selection">
<div id="makes">
<select id="make"size="2"></select>
</div>
<div class="hide" id="models">
<select id="model" size="3"></select>
</div>
</div>
</fieldset>
</fieldset>
</div>
It's not entirely clear from your question what layout you're trying to achieve, but judging by that fact that you have applied "float:left" to the select elements, it looks like you want the select elements to appear side by side. If this is the case, you can achieve this by doing the following:
To centrally align elements you need to add "text-align:center" to the containing block level element, in this case #selection.
The position of elements that are floating is not affected by "text-align" declarations, so remove the "float:left" declaration from the select elements.
In order for the #make and #model divs to sit side by side with out the use of floats they must be displayed as inline elements, so add "display:inline" to both #make and #model (note that this will lose the vertical margin on those elements, so you might need to make some other changes to get the exact layout you want).
As select elements are displayed inline by default, an alternative to the last step is to remove the #make and #model divs and and apply the "show" and "hide" classes to the model select element directly.
Floating the select boxes changes their display properties to "block". If you have no reason to float them, simply remove the "float: left" declaration, and add "text-align: center" to #makes and #models.