Issue
I have 8 option boxes on my UI that I'm designing. The goal is to have the dropdowns ask what CPU your computer has and auto populate the rest of the information.
I have code that will populate the dropdowns with "Intel", then display "Intel Family" (Core i7), but I need that to then ask what processor it has. This is going to be a large amount of information, as an Intel i7 has 77 Different versions. Just like an i3,i5,i9.In total there are 693 unique options.
e.g.
Intel > Core i7 > 7700
Intel > Core i3 > 9300...
I just have my data stored on excel in a pivot table but I'm assuming ill need it in a JSON file which I'm not familiar with yet.
I have a screenshot of what I'm trying to explain, but the code at the moment is very messy.
Here is my current code with JS,
https://jsfiddle.net/f745nq0b/2/
$('#env-select').on('change', function(e) {
var source = $(this),
val = $.trim(source.val()),
target = $('#family-select');
$(target).empty();
if (typeof(_data[val]) != "undefined") {
var options = (typeof(_data[val]) != "undefined") ? _data[val] : {};
$('<option>-- Select --</option>').appendTo(target);
$.each(options, function(value, index) {
$('<option value="' + value + '">' + index + '</option>').appendTo(target);
});
}
});
.form-control {
margin: 10px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Test</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css" />
<link rel="stylesheet" href="./style.css" />
<script>
var _data = {};
var _data = {
"Intel": {
"Celeron": "Celeron",
"Celeron D": "Celeron D",
"Celeron Dual-Core": "Celeron Dual-Core",
"Celeron M": "Celeron M",
"Core 2 Duo": "Core 2 Duo",
"Core 2 Extreme": "Core 2 Extreme",
"Core 2 Quad": "Core 2 Quad",
"Core i3": "Core i3",
"Core i5": "Core i5",
"Core i7": "Core i7",
"Core i7 Extreme Edition": "Core i7 Extreme Edition",
"Core i9": "Core i9",
"Core i9 Extreme Edition": "Core i9 Extreme Edition",
"Pentium": "Pentium",
"Pentium 4": "Pentium 4",
"Pentium D": "Pentium D",
"Pentium Dual-Core": "Pentium Dual-Core",
"Pentium Extreme Edition": "Pentium Extreme Edition",
"Pentium III": "Pentium III",
},
"AMD": {
"APU A10-Series": "APU A10-Series",
"APU A12 Series": "APU A12 Series",
"APU A4-Series": "APU A4-Series",
"APU A6-Series": "APU A6-Series",
"APU A8-Series": "APU A8-Series",
"APU E-Series": "APU E-Series",
"Athlon": "Athlon",
"Athlon 64": "Athlon 64",
"Athlon 64 X2": "Athlon 64 X2",
"Athlon Dual Core": "Athlon Dual Core",
"Athlon II": "Athlon II",
"Athlon X2 Series": "Athlon X2 Series",
"Athlon X4 Series": "Athlon X4 Series",
"Athlon XP": "Athlon XP",
"Duron": "Duron",
"FX": "FX",
"K6": "K6",
"Opteron": "Opteron",
"Phenom": "Phenom",
"Phenom II": "Phenom II",
"Ryzen 3": "Ryzen 3",
"Ryzen 5": "Ryzen 5",
"Ryzen 7": "Ryzen 7",
"Ryzen 9": "Ryzen 9",
"Sempron": "Sempron",
"Threadripper": "Threadripper",
}
};
</script>
</head>
<body>
<div class="advanced_search_container">
<div class="advanced_search_title">
<span>Search for CPU</span>
</div>
<lable>Type</lable>
<select class="form-control" id="env-select">
<option value="">-- Select --</option>
<option value="Intel">Intel</option>
<option value="AMD">AMD</option>
</select>
<lable>Family</lable>
<select class="form-control" id="family-select">
<option value="">-- Select --</option>
</select>
<lable>Processor</lable>
<select class="form-control" id="processor-select">
<option value="">-- Select --</option>
</select>
<br>
<lable>Codename</lable>
<select class="form-control" id="codename-autoselect">
<option value="">Auto Selected</option>
</select>
<lable>Frequency</lable>
<select class="form-control" id="frequency">
<option value="">Auto Selected</option>
</select>
<br>
<lable>CPU Cores</lable>
<select class="form-control" id="cpu-cores">
<option value="">Auto Selected</option>
</select>
<lable>CPU Threads</lable>
<select class="form-control" id="cpu-threads">
<option value="">Auto Selected</option>
</select>
<br>
<lable>CPU Memory</lable>
<select class="form-control" id="cpu-memory">
<option value="">Auto Selected</option>
</select>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="./script.js"></script>
</body>
</html>
Solution
Taking the cited XLS file and converting that to a JSON file using some simple PHP:
# codenames are based upon this array - for the dummy data only
$dictionary=[
'degree','bicone','moneme','ibexes','eringo','dallan','condit','result','pyrene','joffre','humour','reemit','phenix',
'naseby','baffle','melder','crakow','anvers','swatch','snoozy','joanne','mitzie','bogong','steels','uniate','vestry',
'astron','fascia','murine','galosh','mudded','nebula','enmity','advert','pewter','jequi','waggon','sneesh','phuket',
'ifugao','elsene','bailie','outman','acetum','zillah','lauric','unnigh'
];
# function to build the dummy codename.
function gencodename(){
global $dictionary;
$a=mt_rand(0,count($dictionary)-1);
$b=mt_rand(1,9);
$c=chr( mt_rand(65,90) );
return sprintf('%s-%s%s',$dictionary[$a],$b,$c);
}
# The saved CSV file taken from the original XLS.
$file='cpu-info.csv';
$out=array();
$csv=new SplFileObject( $file );
$csv->setFlags( SplFileObject::READ_CSV );
foreach( $csv as $index => $line ){
if( $index > 1 && !empty( $line ) && array_key_exists( 1, $line ) && array_key_exists( 2, $line ) ){
/*
No fields for threads or codename so we generate our own numpty values.
Otherwise extend the below list(a,b,c,d,e....)=$line to include more vars
& use those values rather than the dummy ones.
*/
list( $family, $processor, $codename, $speed, $cores, $memory, $notes )=$line;
$out[]=array(
'processor' => $processor,
'family' => $family,
'frequency' => $speed,
'memory' => $memory,
'cores' => $cores,
'notes' => $notes,
'codename' => gencodename(),
'threads' => mt_rand(1,16)
);
}
}
$json=sprintf('const json=%s;', json_encode( $out, JSON_PRETTY_PRINT ) );
$file='cpu-extra.js';
file_put_contents( $file, $json );
I note that the source XLS file has changed since first inspection and now has some rudimentary attempts at generating JSON strings using concatenation so it should be noted that the order within the PHP code above within list($a,$b..)=$line
etc is dependant upon the column order in the spreadsheet/csv file!
With the JSON data saved as cpu-extra.js
within the same working directory as the HTML that follows I believe you get the desired output.
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title></title>
<style>
body *{
box-sizing:border-box;
font-family:monospace;
}
.form-control {
margin:0.25rem;
padding:0.5rem;
background:whitesmoke;
}
section{
display:flex;
flex-direction:row;
background:white;
}
label{
flex:1;
display:flex;
flex-direction:row;
justify-content:space-between;
align-content:center;
align-items:center;
padding:0.25rem;
max-width:33.4%;
}
.advanced_search_container{
width:50%;
border:1px solid black;
border-radius:1rem;
padding:1rem;
background:whitesmoke;
}
select{
min-width:140px;
background:white!important;
}
.advanced_search_title{
margin:0 0 1rem;
background:whitesmoke;
}
.advanced_search_title > span{
font-size:150%;
font-weight:bolder;
}
.active{
border:1px solid yellowgreen;
}
section.notes,
section.notes label{ max-width:100% }
textarea{
width:83%;
resize:none;
height:5rem;
}
</style>
</head>
<body>
<div class="advanced_search_container">
<div class="advanced_search_title">
<span>Search for CPU</span>
</div>
<!--
Important to note that the names of the select
menus are keys within the individual JSON records.
The JSON used was created in PHP after fudging around
with the raw XLS file cited in link. The XLS file was
used to generate a simple CSV file which is easily read
in PHP.
Some parts of the generated JSON are nonsense - added only
so that the menus received some content. Items such as
"codename" and "threads" are ALL bogus unless by accident.
Each Select menu has the ID removed as they served no purpose
in this code and some have new classes assigned. Menus are
grouped within `section` elements according to previous `break`
tags - mostly.
Modifying this DOM structure will have unforseen effects
upon the javascript below.
-->
<section class='controls'>
<label>Type:
<select class="form-control" id="env-select" data-next='family' data-recycle='true'>
<option selected hidden disabled>-- Select --
<option>Intel
<option>AMD
</select>
</label>
<label>Family:
<select class="form-control" name='family' data-next='processor' data-recycle='true'>
<option selected hidden disabled>-- Select --
</select>
</label>
<label>Processor:
<select class="form-control dependant" name='processor'>
<option selected hidden disabled>-- Select --
</select>
</label>
</section>
<section class='details'>
<label>Codename:
<select class="form-control dependant" name='codename'>
<option selected hidden disabled>Auto Selected
</select>
</label>
<label>Frequency:
<select class="form-control dependant" name='frequency'>
<option selected hidden disabled>Auto Selected
</select>
</label>
<label>CPU Cores:
<select class="form-control dependant" name='cores'>
<option selected hidden disabled>Auto Selected
</select>
</label>
</section>
<section class='details'>
<label>CPU Threads:
<select class="form-control dependant" name='threads'>
<option selected hidden disabled>Auto Selected
</select>
</label>
<label>CPU Memory:
<select class="form-control dependant" name='memory'>
<option selected hidden disabled>Auto Selected
</select>
</label>
</section>
<section class='notes'>
<label>Notes:
<textarea name='notes' class='dependant'></textarea>
</label>
</section>
</div>
<!--
cpu-extra.js contains the PHP generated JSON data.
This could be generated "on-the-fly" using PHP or
other server side language that can read the csv
file.
-->
<script src='cpu-extra.js'></script>
<script>
var _data = {
"Intel": {
"Celeron": "Celeron",
"Celeron D": "Celeron D",
"Celeron Dual-Core": "Celeron Dual-Core",
"Celeron M": "Celeron M",
"Core 2 Duo": "Core 2 Duo",
"Core 2 Extreme": "Core 2 Extreme",
"Core 2 Quad": "Core 2 Quad",
"Core i3": "Core i3",
"Core i5": "Core i5",
"Core i7": "Core i7",
"Core i7 Extreme Edition": "Core i7 Extreme Edition",
"Core i9": "Core i9",
"Core i9 Extreme Edition": "Core i9 Extreme Edition",
"Pentium": "Pentium",
"Pentium 4": "Pentium 4",
"Pentium D": "Pentium D",
"Pentium Dual-Core": "Pentium Dual-Core",
"Pentium Extreme Edition": "Pentium Extreme Edition",
"Pentium III": "Pentium III",
},
"AMD": {
"APU A10-Series": "APU A10-Series",
"APU A12 Series": "APU A12 Series",
"APU A4-Series": "APU A4-Series",
"APU A6-Series": "APU A6-Series",
"APU A8-Series": "APU A8-Series",
"APU E-Series": "APU E-Series",
"Athlon": "Athlon",
"Athlon 64": "Athlon 64",
"Athlon 64 X2": "Athlon 64 X2",
"Athlon Dual Core": "Athlon Dual Core",
"Athlon II": "Athlon II",
"Athlon X2 Series": "Athlon X2 Series",
"Athlon X4 Series": "Athlon X4 Series",
"Athlon XP": "Athlon XP",
"Duron": "Duron",
"FX": "FX",
"K6": "K6",
"Opteron": "Opteron",
"Phenom": "Phenom",
"Phenom II": "Phenom II",
"Ryzen 3": "Ryzen 3",
"Ryzen 5": "Ryzen 5",
"Ryzen 7": "Ryzen 7",
"Ryzen 9": "Ryzen 9",
"Sempron": "Sempron",
"Threadripper": "Threadripper",
}
};
/*
shorthand utility functions
*/
const d=document;
const q=(e,n=d)=>n.querySelector(e);
const qa=(e,n=d)=>n.querySelectorAll(e);
/*
nodelist of ALL select menus
*/
const col=qa('.advanced_search_container > section > label > select');
/*
utility to clear the HTML from within
a select menu but retain the first
element - the default value.
*/
const recycle=(n)=>{
if( n.type!=='select-one' ){
n.value='';
return false;
}
let clone=n.firstElementChild.cloneNode( true );
n.innerHTML='';
n.appendChild( clone );
n.classList.remove('active')
return n;
};
const setactive=(n)=>n.classList.add('active')
col.forEach( select=>select.addEventListener('change',e=>{
setactive( e.target );
/*******************************************
populate the initial Intel/AMD dropdown..
let battle commence!
*/
if( e.target.id=='env-select' ){
// find the NEXT select menu to add options to
// done using the dataset attribute ( data-next )
let sel=q('select[name="'+e.target.dataset.next+'"]');
let obj=_data[ e.target.value ]; // using original data variable
// ensure the next element is empty
recycle( sel );
// add all options based upon which Type is selected
Object.keys( obj ).forEach( k=>{
sel.appendChild( new Option( k, obj[k] ) );
});
return;
}
// If the Type or Family is changed, clear all dependant select menus
if( e.target.dataset.recycle ){
qa('.dependant').forEach( n=>recycle(n) )
}
/*******************************************
Events registered on other dropdowns
*/
if( e.target.hasAttribute('name') && json[0].hasOwnProperty( e.target.name ) ){
Object.keys( json ).some( key=>{
// The "name" is that of the SELECT menu
let name=e.target.name;
// The "item" is the value from selected menu
let item=json[ key ][ name ];
if( item==e.target.value ) {
let value;
// Now search through entire JSON file to find matches to the selected "item"
Object.keys( json ).forEach( k=>{
obj=json[ k ];
if( obj[ name ]==item ){
/*
Once the "processor" has been selected any dependant
select menus will have their values added and set as
selected.
Changing the "family" will clear all dependant select
menus in readiness for a new Processor & associated
details.
*/
if( e.target.dataset.next ){
/*
Find the next select menu
*/
value=obj[ e.target.dataset.next ];
q( 'select[ name="'+e.target.dataset.next+'" ]' ).appendChild( new Option( value, value ) );
}else{
/*
target all dependant menus
*/
qa( 'section.details select.dependant' ).forEach(n=>{
recycle(n);
value=obj[ n.name ];
n.appendChild( new Option( value, value ) );
n.value=value;
});
q('textarea[name="notes"]').value=obj.notes
}
}
});
console.info( name, item );
return true
}
});
}
}));
</script>
</body>
</html>
Answered By - Professor Abronsius
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.