I am brand new to JavaScript so please bear with me! I'm building a slider puzzle, and I'm trying to create a form that will allow the user to pick the dimensions of their puzzle. In the past, I've had the variables for row (_r) and column (_c) set to 3 - but what I'd like now is an HTML select table where the user can pick values between 3 and 5 for each and then generate their own table.
I'm just not sure how to properly assign _r and _c based on the user's selection, and everything I've searched related to different HTML forms or wasn't otherwise helpful.
Also, if anyone knows a fix for this: Before I created the form all I had was a "New Game" button (and like I said, _r and _c were both set to 3), when I clicked the New Game button everything worked perfectly, but if I click it again it keeps generating empty tables beneath the original one which refreshes normally. Any ideas how to prevent that? (this is why I have the clearPuzzle function at the end)
Thank you for any insight.
Here is my HTML:
<p>Choose Dimensions: </p>
<select name="Rows" onchange="form()">
<option value="Rows" selected disabled>Rows</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
<select name="Columns" onchange="form()">
<option value="Columns" selected disabled>Columns</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
<input type="button" name="button" value="New Game" onclick="init(_r, _c)"></button>
and JavaScript:
/*what I had before with no form function:
_r = 3;
_c = 3;
*/
function form()
{
var _r = document.getElementsByName("Rows")[0].value;
var _c = document.getElementsByName("Columns")[0].value;
}
function init(r, c)
{
form();
var puzzle = new puzzleArray(r, c);
shuffle(puzzle);
displayPuzzle(puzzle);
addClickHandlers();
}
function puzzleArray(r, c)
{
//declare and populate array
var _array = [];
for (var i = 0; i < r*c; i++)
{
_array[i] = i;
}
return _array;
}
function shuffle(_array)
{
//shuffle tiles
for (var i = 0; i < _r*_c; i++)
{
var rand = Math.floor(Math.random() * _array.length);
var temp = _array[rand];
_array[rand] = _array[i];
_array[i] = temp;
}
//check to see if puzzle is solveable
var count = 0;
do {
for (var i = 0; i < _r*_c; i++)
{
for (var j = i; j <= _r*_c; j++)
{
if (_array[j] < _array[i])
{
count++;
}
}
}
} while (Math.floor(count/2) != count/2);
}
function displayPuzzle(anArray)
{
//create table
var table = document.createElement("table");
table.id = "myTable";
for (var i = 0; i < _r; i++)
{
var row = document.createElement('tr');
for (var j = 0; j < _c; j++)
{
var column = document.createElement('td');
row.appendChild(column);
}
table.appendChild(row);
}
document.body.appendChild(table);
//populate cells with their original and shuffled values.
for (var i = 0; i < _r*_c; i++)
{
document.getElementsByTagName("td")[i].innerHTML = "Cell: " + [i] + ", " + "Value: " + anArray[i];
if (anArray[i] == 0)
{
document.getElementsByTagName("td")[i].innerHTML = "Cell: " + [i] + ", " + "Value: " + "Blank!";
}
}
//specify classes for each cell
var _cell = document.getElementsByTagName("td");
for (var i = 0; i < _r*_c; i++)
{
_cell[i].id = "s" + [i];
}
}
function addClickHandlers()
{
for (var i = 0; i < _r*_c; i++)
{
var cells = document.getElementsByTagName("td");
cells[i].onclick = moveTile;
}
}
function moveTile()
{
this.innerHTML += "!!!"; //just experimenting
}
//not working yet
function clearPuzzle()
{
var puzzle = new puzzleArray(r, c);
shuffle(puzzle);
}
I'm concerned that the function form has local variables declarations for variables _r and _c. As local variables, they will be discarded on function exit, whereas I think you are trying to assign to (document) global variables. You should omit the var keyword there. Document global variables should be declared outside of any function scope.
/*what I had before with no form function:
_r = 3;
_c = 3;
*/
var _r; // declare _r & _c as document global variables
var _c;
function form()
{
// assign to the document global variables.
_r = document.getElementsByName("Rows")[0].value;
_c = document.getElementsByName("Columns")[0].value;
}
Figured it out:
form() was en element being used elsewhere, so I changed the function name to sndForm() and also edited the code within that function:
HTML:
<select id = "_rows" onchange="sndForm()">
<option value="Rows" selected disabled>Rows</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
<select id="_columns" onchange="sndForm()">
<option value="Columns" selected disabled>Columns</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
JavaScript:
var _r;
var _c;
var row;
var col;
function init(_r, _c)
{
//alert(_r);
//alert(_c);
sndForm();
var puzzle = new puzzleArray(_r, _c);
shuffle(puzzle);
displayPuzzle(puzzle);
//alert(puzzle);
startTimer();
addClickHandlers();
}
function sndForm()
{
row = document.getElementById("_rows");
col = document.getElementById("_columns");
_r = row.options[row.selectedIndex].value;
_c = col.options[col.selectedIndex].value;
}
Related
I need to change the contents of dropdown B based on the selection in dropdown A using javascript. There are no db queries involved--I know beforehand what the contents of B should be given the choice in A. I have found some examples using AJAX, but since there is no db query involved that's not necessary. Can anyone point me to some example code for how to do this?
function configureDropDownLists(ddl1, ddl2) {
var colours = ['Black', 'White', 'Blue'];
var shapes = ['Square', 'Circle', 'Triangle'];
var names = ['John', 'David', 'Sarah'];
switch (ddl1.value) {
case 'Colours':
ddl2.options.length = 0;
for (i = 0; i < colours.length; i++) {
createOption(ddl2, colours[i], colours[i]);
}
break;
case 'Shapes':
ddl2.options.length = 0;
for (i = 0; i < shapes.length; i++) {
createOption(ddl2, shapes[i], shapes[i]);
}
break;
case 'Names':
ddl2.options.length = 0;
for (i = 0; i < names.length; i++) {
createOption(ddl2, names[i], names[i]);
}
break;
default:
ddl2.options.length = 0;
break;
}
}
function createOption(ddl, text, value) {
var opt = document.createElement('option');
opt.value = value;
opt.text = text;
ddl.options.add(opt);
}
<select id="ddl" onchange="configureDropDownLists(this,document.getElementById('ddl2'))">
<option value=""></option>
<option value="Colours">Colours</option>
<option value="Shapes">Shapes</option>
<option value="Names">Names</option>
</select>
<select id="ddl2">
</select>
Setup mine within a closure and with straight JavaScript, explanation provided in comments
(function() {
//setup an object fully of arrays
//alternativly it could be something like
//{"yes":[{value:sweet, text:Sweet}.....]}
//so you could set the label of the option tag something different than the name
var bOptions = {
"yes": ["sweet", "wohoo", "yay"],
"no": ["you suck!", "common son"]
};
var A = document.getElementById('A');
var B = document.getElementById('B');
//on change is a good event for this because you are guarenteed the value is different
A.onchange = function() {
//clear out B
B.length = 0;
//get the selected value from A
var _val = this.options[this.selectedIndex].value;
//loop through bOption at the selected value
for (var i in bOptions[_val]) {
//create option tag
var op = document.createElement('option');
//set its value
op.value = bOptions[_val][i];
//set the display label
op.text = bOptions[_val][i];
//append it to B
B.appendChild(op);
}
};
//fire this to update B on load
A.onchange();
})();
<select id='A' name='A'>
<option value='yes' selected='selected'>yes
<option value='no'> no
</select>
<select id='B' name='B'>
</select>
Could you please have a look at: http://jsfiddle.net/4Zw3M/1/.
Basically, the data is stored in an Array and the options are added accordingly. I think the code says more than a thousand words.
var data = [ // The data
['ten', [
'eleven','twelve'
]],
['twenty', [
'twentyone', 'twentytwo'
]]
];
$a = $('#a'); // The dropdowns
$b = $('#b');
for(var i = 0; i < data.length; i++) {
var first = data[i][0];
$a.append($("<option>"). // Add options
attr("value",first).
data("sel", i).
text(first));
}
$a.change(function() {
var index = $(this).children('option:selected').data('sel');
var second = data[index][1]; // The second-choice data
$b.html(''); // Clear existing options in second dropdown
for(var j = 0; j < second.length; j++) {
$b.append($("<option>"). // Add options
attr("value",second[j]).
data("sel", j).
text(second[j]));
}
}).change(); // Trigger once to add options at load of first choice
I have a variable which contains a number. I'd like to append an option with the numeric value in each based on whatever the variable number is ( ie: if total equals 10, then I need to add 10 options to the select with each option containing the next numeric row value, so 1, 2, 3, 4...etc. I start off with one hard coded option, and then I need to add options dynamically for every case. I've tried a multitude of scripts but I"m getting " cannot use in operator to search for length.
https://jsfiddle.net/v1yyhfm8/
HTML
<select id="main">
<option selected>1</option>
</select>
I tried:
var total = dataSource.total();
for (var i = 1; 1 <= total; i++) {
var added = document.createElement('option');
var test = $('#main');
added.value = i;
added.innerHTML = i;
test.append(added);
}
and
var total = dataSource.total();
$.each(total, function (i, item) {
$('#main').append($('<option>', {
value: item.total,
text: item.text
}));
});
In your code, the for loop condition would be true always which leads to an infinite loop so change it to i <= total.
var total = dataSource.total();
for (var i = 1; i <= total; i++) {
var added = document.createElement('option');
var select1 = $('#main');
added.value = i;
added.innerHTML = i;
select1.append(added);
}
var total = 10;
for (var i = 1; i <= total; i++) {
var added = document.createElement('option');
var select1 = $('#main');
added.value = i;
added.innerHTML = i;
select1.append(added);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="main">
<option selected>1</option>
</select>
Html part :
<select id="main">
</select>
Jquery Part:
var opt = ' <option selected>1</option>';
for(var i = 2; i<= 10; i++){
opt += ' <option>' + i + '</option>';
}
$("#main").append(opt);
Jsfiddle link : https://jsfiddle.net/v1yyhfm8/
I have problem to change the value of the options from the code below, select which changes depending on other select, but I want to change the value of the select id = "numbList", thanks ....
<!DOCTYPE html>
<html>
<body>
<select id="diffList" onchange="changeList()">
<option value="">-- Difficulty --</option>
<option value="1">Easy</option>
<option value="2">Medium</option>
<option value="3">Difficult</option>
</select>
<select id="numbList"></select>
<script>
window.difficulty = {};
window.difficulty['1'] = [1,2,3];
window.difficulty['2'] = [4,5,6];
window.difficulty['3'] = [7,8,9];
function changeList() {
var diffList = document.getElementById("diffList");
var numbRange = document.getElementById("numbList");
var selectDiff = diffList.options[diffList.selectedIndex].value;
while(numbRange.options.length)
{
numbRange.remove(0);
}
var diff = window.difficulty[selectDiff];
if(diff)
{
var i;
for(i = 0; i < diff.length; i++)
{
var difficulty = new Option(diff[i], i);
numbRange.options.add(difficulty);
}
}
}
</script>
</body>
</html>
Just use diff[i] for both text and value for option:
...
for(i = 0; i < diff.length; i++)
{
var value = diff[i];
var difficulty = new Option(value, value);
numbRange.options.add(difficulty);
}
...
As the previous value is removed from select options it selects the first of the new options. So you shouldn't need to set the value of numbList.
To set value of numbList programmatically you could just do numbList.value = 1; for example.
I am trying to make a function that adds the selected number from the <select> in td's to the tr with id="spelers". But when I run it it doesn't work. Could someone tell me what I am doing wrong? Thanks in advance.
Here's the HTML:
<select id="speler_select" onchange="spelers()">
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
</select>
<table>
<tr id="spelers"></tr>
</table>
And this is the JavaScript:
// number of players
var speler_select = document.getElementById("speler_select");
var aantal_spelers = speler_select.options[speler_select.selectedIndex].value;
var spelers = document.getElementById("spelers");
function spelers() {
for (var x = 0; x < aantal_spelers; x++) {
var td = document.createElement("td");
spelers.appendChild(td);
spelers.lastChild.innerHTML = "Speler " + (x + 1);
}
}
You need to get the selected value inside the spelers() function. If you get the value outside of the spelers() function you'll get the initial value, not the actualy selected one.
Another thing: you need to convert the selected value from string to integer to be able to iterate on it.
Another thing: spelers variable and spelers function have the same name, therefore when defining spelers function it replaces spelers variable. You should use different names.
var speler_select = document.getElementById("speler_select");
var spelers_e = document.getElementById("spelers");
function spelers() {
var aantal_spelers = parseInt(speler_select.options[speler_select.selectedIndex].value, 10);
for (var x = 0; x < aantal_spelers; x++) {
var td = document.createElement("td");
spelers_e.appendChild(td);
spelers_e.lastChild.innerHTML = "Speler " + (x + 1);
}
}
Also it would be a good idea to add first option with no value, so a user can actually select the first option with a value to run the spelers() function. Like this:
<select ...>
<option value=''>Add spelers</option>
<!-- other options here -->
</select>
It doesn't work because the value you get from your select is a string, and not a number. try changing this:
var aantal_spelers = speler_select.options[speler_select.selectedIndex].value;
to this:
var aantal_spelers = parseInt(speler_select.options[speler_select.selectedIndex].value);
You should try this:-
function spelers() {
var speler_select = document.getElementById("speler_select");
var aantal_spelers = speler_select.options[speler_select.selectedIndex].value;
var spelers = document.getElementById("spelers");
for (var x = 0; x < aantal_spelers; x++) {
var td = document.createElement("td");
spelers.appendChild(td);
spelers.lastChild.innerHTML = "Speler " + (x + 1);
}
}
I think you should get selection in spelers function.
It's not working because you're variable name and function name are the same - spelers.
Which causes the following error
Uncaught TypeError: object is not a function
Changing any of this will fix the issue.
Demo
You made one mistake in getting the function to add td to the table. You need to have the selector variable inside the function in order to make it to work. fiddle
Code Snippet:
function addTDs() {
spelers.innerHTML = "";
var aantal_spelers =parseInt(speler_select.options[speler_select.selectedIndex].value);
console.log(aantal_spelers);
for (var x = 0; x < aantal_spelers; x++) {
var td = document.createElement("td");
spelers.appendChild(td);
spelers.lastChild.innerHTML = "Speler " + (x + 1);
}
}
How can I sort the <option> elements of a <select> tag using JavaScript?
Here is the HTML I have:
<form action="example.asp">
<div>
<select size="3">
<option value="op2" >Option 2</option>
<option value="op1">Option 1</option>
<option value="op4">Option 4</option>
<option value="op3">Option 3</option>
</select>
</div>
</form>
If the value is different than the text, use the following function to sort both of them. This is just an updated version of above solution and will keep both the name and associated value.
<script language="JavaScript" type="text/javascript">
function sortList()
{
var lb = document.getElementById('mylist');
arrTexts = new Array();
arrValues = new Array();
arrOldTexts = new Array();
for(i=0; i<lb.length; i++)
{
arrTexts[i] = lb.options[i].text;
arrValues[i] = lb.options[i].value;
arrOldTexts[i] = lb.options[i].text;
}
arrTexts.sort();
for(i=0; i<lb.length; i++)
{
lb.options[i].text = arrTexts[i];
for(j=0; j<lb.length; j++)
{
if (arrTexts[i] == arrOldTexts[j])
{
lb.options[i].value = arrValues[j];
j = lb.length;
}
}
}
}
</script>
<script language="JavaScript" type="text/javascript">
function sortlist() {
var lb = document.getElementById('mylist');
arrTexts = new Array();
for(i=0; i<lb.length; i++) {
arrTexts[i] = lb.options[i].text;
}
arrTexts.sort();
for(i=0; i<lb.length; i++) {
lb.options[i].text = arrTexts[i];
lb.options[i].value = arrTexts[i];
}
}
</script>
<form action="#">
<select name=mylist id=mylist size=5>
<option value="Anton">Anton
<option value="Mike">Mike
<option value="Peter">Peter
<option value="Bill">Bill
<option value="Carl">Carl
</select>
<br>
sort
</form>
You should think about it on the pre html-creation level. If you are generating them from some kind of list or by dynamic page mechanism then sort them before you generate your option elements - thats the clearest way ;)
A simpler solution, building on Yasir Al-Agl's answer:
function sortList()
{
var lb = document.getElementById('mylist');
arr = new Array();
for(i = 0; i < lb.length; i++) {
arr[i] = lb.options[i];
}
arr.sort(function(a,b) {
return (a.text > b.text)? 1 : ((a.text < b.text)? -1 : 0);
}); // or use localeCompare() if you prefer
for(i = 0; i < lb.length; i++) {
lb.options[i] = arr[i];
}
}
In short, you need only one Array, the elements of which are simply references to the original "options" Objects. The sort() function also has the freedom to choose which option property to sort on (ie, the text property, the value property, etc).
Don't forget, however, that the "selectedIndex" property of the "select" control may no longer be correct after the sort.
This function works as in the last answer, but also keeps the selection of item
// Sorts all entries of a select item (= dropdown) by their visible name, keeping the internal values and the selection
function sortSelectEntries(selItem) {
let formerSel = selItem.value;
let count = selItem.length;
let options = new Array();
for (var i = 0; i < count; i++)
options[i] = selItem.options[i];
options.sort((e1, e2) => e1.text > e2.text ? 1 : (e1.text < e2.text ? -1 : 0));
for (i = 0; i < count; i++)
selItem.options[i] = options[i];
selItem.value = formerSel; // restore selection
}