Use HTML dropdown list values with JavaScript - javascript

This is what I'm trying to do:
The user selects either option "One" or option "Two".
If the user select "One" the result is 66 + 45 or if the user select "Two" the result is 35 + 45.
How can I implement this using HTML and JavaScript?
This is what I've done so far:
HTML:
<select id="number">
<option>One</option>
<option>Two</option>
</select>
...
// Result
<div id="result"></div>
JAVASCRIPT:
function test(eventInfo) {
var userSelection = document.getElementById("number").value;
if () {
result = 66 + 45;
} else {
result = 35 + 45;
}
var greetingString = userSelection;
document.getElementById("result").innerText = greetingString;
}

Consider:
<select id="number">
<option value="66">One</option>
<option value="35">Two</option>
</select>
then:
result = 45 + +document.getElementById("number").value;

How about this. Set the values in data-attribute and calculate the sum.
<select id="number">
<option value="1" data-Values="66,45">One</option>
<option value="2" data-Values="35,28">Two</option>
</select>
<div id="result"></div>
JS
var values = this.options[this.selectedIndex].getAttribute('data-Values');
var sum = eval(values.split(',').join('+')); //Use with caution eval.
document.getElementById("result").innerHtml = sum;
Demo

Why don't you use value:
<select id="number">
<option value="66+45">One</option>
<option value="35+45">Two</option>
</select>
var greetingString = $("#number option:selected").val();
// or document.getElementById("number").value;
document.getElementById("result").innerText = greetingString;

Use Switch Statement:
Html:
<select id="number">
<option value="66">One</option>
<option value="35">Two</option>
</select>
Javascript:
var userSelection = document.getElementById("number").value;
switch (userSelection)
{
case 66:
result = 66 + 45;
break;
case 35:
result = 35 + 45;
break;
}

You can try this one:
<select id="number" onchange="test(this.value);">
<option value="66+45">One</option>
<option value="35+45">Two</option>
</select>
...
// Result
<div id="result">here</div>
JS
<script>
function test(val) {
document.getElementById("result").innerHtml = val;
}
</script>

Related

html select element that its options depends on another select

I have two select element and I want to show some options in second select based on what user choose at first select.
consider first select have two options : a , b ...
if user choose 'a' from first select :
the second select optiones should be -> c , d ...
and if user choose 'b' from first select :
the second select optiones should be : e , f ...
I have done some coding but the problem is at the start when user doesnt choose any option from first select the second select is always empty(it should show c , d)
<!DOCTYPE html>
<html>
<body>
<select id="s1" required>
<option value="a">a</option>
<option value="b">b</option>
</select>
<select id="s2" required > </select>
<script>
document.getElementById("s1").onchange = function() {
document.getElementById('s2').disabled = false; //enabling s2 select
document.getElementById('s2').innerHTML = ""; //clear s2 to avoid conflicts between options values
var opt0 = document.createElement('option');
var opt1 = document.createElement('option');
if (this.value == 'a') {
opt0.textContent = "c";
opt1.textContent = "d";
document.getElementById('s2').appendChild(opt0);
document.getElementById('s2').appendChild(opt1);
} else if (this.value == 'b') {
opt0.textContent = "e";
opt1.textContent = "f";
document.getElementById('s2').appendChild(opt0);
document.getElementById('s2').appendChild(opt1);
}
};
</script>
</body>
</html>
If you can save the option values in a lookup object (or JSON):
function setOptions(select, values) {
for (var i = select.length = values.length; i--; )
select[i].innerText = values[i]
}
function value(select) { return select.value || select[0].value } // 1st item by default
var data = { 1: { 1.1: [1.11, 1.12], 1.2: [1.21, 1.22] },
2: { 2.1: [2.11, 2.12], 2.2: [2.21, 2.22], 2.3: [2.31, 2.32, 2.33] } }
s2.onchange = function() { setOptions(s3, data[value(s1)][value(s2)]) }
s1.onchange = function() { setOptions(s2, Object.keys(data[value(s1)])); s2.onchange() }
setOptions(s1, Object.keys(data)); s1.onchange(); // fill the options
<select id=s1 required size=3></select>
<select id=s2 required size=3></select>
<select id=s3 required size=3></select>
This code is based on JavaScript (No need for jQuery)
change Id name and value (x=="desire_value") according to your code
function myFunction() {
var x = document.getElementById("select1").value;
if (x == "3") document.getElementById("select2").style.display = "block";
else document.getElementById("select2").style.display = "none";
}
<select id="select1" onchange="myFunction()">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<select id="select2" style="display: none;">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
You have to write the functionality outside of onchange(). Try the following:
document.getElementById("s1").onchange = function() {
document.getElementById('s2').disabled = false; //enabling s2 select
document.getElementById('s2').innerHTML = ""; //clear s2 to avoid conflicts between options values
var opt0 = document.createElement('option');
var opt1 = document.createElement('option');
if (this.value == 'a') {
opt0.textContent = "c";
opt1.textContent = "d";
document.getElementById('s2').appendChild(opt0);
document.getElementById('s2').appendChild(opt1);
} else if (this.value == 'b') {
opt0.textContent = "e";
opt1.textContent = "f";
document.getElementById('s2').appendChild(opt0);
document.getElementById('s2').appendChild(opt1);
}
};
let element = document.getElementById("s1");
let selOption = element.options[element.selectedIndex].value;
if(selOption == 'a'){
var opt0 = document.createElement('option');
var opt1 = document.createElement('option');
opt0.textContent = "c";
opt1.textContent = "d";
document.getElementById('s2').appendChild(opt0);
document.getElementById('s2').appendChild(opt1);
}
<select id="s1" required>
<option value="a">a</option>
<option value="b">b</option>
</select>
<select id="s2" required > </select>
Why don't you just put that hard coded...
<!DOCTYPE html>
<html>
<body>
<select id="s1" required>
<option value="a">a</option>
<option value="b">b</option>
</select>
<select id="s2" required >
<option value="c">c</option>
<option value="d">d</option>
</select>
<script>
document.getElementById("s1").onchange = function() {
document.getElementById('s2').disabled = false; //enabling s2 select
document.getElementById('s2').innerHTML = ""; //clear s2 to avoid conflicts between options values
var opt0 = document.createElement('option');
var opt1 = document.createElement('option');
if (this.value == 'a') {
opt0.textContent = "c";
opt1.textContent = "d";
document.getElementById('s2').appendChild(opt0);
document.getElementById('s2').appendChild(opt1);
} else if (this.value == 'b') {
opt0.textContent = "e";
opt1.textContent = "f";
document.getElementById('s2').appendChild(opt0);
document.getElementById('s2').appendChild(opt1);
}
};
</script>
</body>
</html>
One approach to contemplate is populating the dependant dropdowns with all values and use a data attribute for the parent-child relationship. Javascript then clones and removes the options for later insertion.
The functional javascript is now very lean and the dependency relationships are maintained in the DOM.
var s2Clone;
// Doesn't work in older IEs
//CLone the Dependant drop down and hide
document.addEventListener('DOMContentLoaded', function(){
s2Clone = document.getElementById("s2").cloneNode(true);
document.getElementById("s2").innerHTML = "";
}, false);
document.getElementById("s1").onchange = function() {
var selected = this.value;
//Get the nodes with a parent attribute of the selected data
var optionsToInsert = s2Clone.querySelectorAll("[data-parent='" + selected +"']");
//clear existing
var s2 = document.getElementById("s2");
s2.innerHTML = "";
//Add The new options.
for(i = 0; i < optionsToInsert.length; i++)
{
s2.appendChild(optionsToInsert[i]);
}
}
<select id="s1" required>
<option value="">Please select</option>
<option value="a">a</option>
<option value="b">b</option>
</select>
<select id="s2" required >
<option value="a1" data-parent="a">a - 1</option>
<option value="a2" data-parent="a">a - 2</option>
<option value="a3" data-parent="a">a - 3</option>
<option value="b1" data-parent="b">b - 1</option>
<option value="b2" data-parent="b">b - 2</option>
<option value="b3" data-parent="b">b - 3</option>
</select>

How to select maximum date from select box show alert message in Js

In the below snippet, the maximum date is 29-July-2017. If I select the maximum date we should display an alert box. Is it possible using Javascript or jQuery?
Note: Options display in random order.
HTML:
<select id="period" name="PeriodCollection" style="border-radius: 4px; ">
<option value="3">10-July-2017</option>
<option value="12">15-July-2017</option>
<option value="9">29-July-2017</option>
<option value="5">23-July-2017</option>
</select>
You can try something like this:
Logic:
Create a variable that will either hold value or text(in below sample) of max date.
Then add an eventListener to check the necessary attribute on change.
If this attribute is same as Max computed in step 1, alert the user.
Note: Both the approaches assumes that there will be no dynamic elements and so the computation of max date is done beforehand on document.ready. Also, I'm keeping value or text in variable. This will allow us to bypass the step to create date on every change.
Approach with Text
$(function(){
var maxValue = null;
function computeMaxValue(arr){
arr.reduce(function(_max, cur){
var t = new Date(cur).getTime();
if(t > _max) {
_max = t;
maxValue = cur;
}
return _max;
}, 0)
}
var dates = $('#period option').map(function(){ return $(this).text() }).get();
computeMaxValue(dates);
$('#period').on('change', function(){
var text = $('option:selected', this).text();
if(text === maxValue){
console.log('You have selected Max value');
}
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<select id="period" name="PeriodCollection" style="border-radius: 4px; ">
<option value="3">10-July-2017</option>
<option value="12">15-July-2017</option>
<option value="9">29-July-2017</option>
<option value="5">23-July-2017</option>
</select>
Approach with Value
$(function(){
var maxValue = null;
function computeMaxValue(selector){
var temp = 0;
$(selector).each(function (index, el){
var time = new Date(el.textContent).getTime();
if(time >= temp) {
temp = time;
maxValue = el.value;
}
})
}
computeMaxValue('#period option');
$('#period').on('change', function(){
if(this.value === maxValue){
console.log('You have selected Max value');
}
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<select id="period" name="PeriodCollection" style="border-radius: 4px; ">
<option value="3">10-July-2017</option>
<option value="12">15-July-2017</option>
<option value="9">29-July-2017</option>
<option value="5">23-July-2017</option>
</select>
Sample with 1 option
$(function(){
var maxValue = null;
function computeMaxValue(selector){
var temp = 0;
$(selector).each(function (index, el){
var time = new Date(el.textContent).getTime();
if(time >= temp) {
temp = time;
maxValue = el.value;
}
})
}
computeMaxValue('#period option');
$('#period').on('change', function(){
if(this.value === maxValue){
console.log('You have selected Max value');
}
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<select id="period" name="PeriodCollection" style="border-radius: 4px; ">
<option>--Select Period--</option>
<option value="5">23-July-2017</option>
</select>
Hope the below code helps
<!DOCTYPE html>
<html>
<head>
<title> Stack Overflow Question </title>
<style>
</style>
</head>
<body>
<select id="period" name="PeriodCollection" style="border-radius: 4px; ">
<option value="3">10-July-2017</option>
<option value="12">15-July-2017</option>
<option value="9">29-July-2017</option>
<option value="5">23-July-2017</option>
</select>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
$('#period').on('change',function(){
//Array to Store the dates from the options
var datesArr = [];
//Get the date from the Selected option
var d = new Date($('#period option:selected').text()).getDate();
//Pushing the dates to the Array
$('#period option').each(function(){
var d = new Date($(this).text());
datesArr.push(d.getDate());
});
//Getting the Max value from the Array
var max = Math.max(...datesArr);
//Converting to integers
d = parseInt(d);
max = parseInt(max);
//Comparing
if(d == max){
alert("Selected the Maximum Date");
}
});
</script>
</body>
</html>
Try Below Code:
$("#period").change(function(){
var selectedValue = $(this).find("option:selected").text();
var data = selectedValue.split("-");
var month = new Date(Date.parse(data['1']+data['0'], data['2'])).getMonth();
var selectedDate = new Date(data['2'],month,data['0']);
var dates = [];
$("#period").find("option").each(function(e){
var currentText = $(this).text();
var currenData = currentText.split("-");
var currentMonth = new Date(Date.parse(data['1']+data['0'], data['2'])).getMonth();
dates.push(new Date(currenData['2'],currentMonth,currenData['0']));
});
var maxDate=new Date(Math.max.apply(null,dates));
if(selectedDate.getTime() === maxDate.getTime()){
alert(maxDate);
}
});
<select id="period" name="PeriodCollection" style="border-radius: 4px; ">
<option value="3">10-July-2017</option>
<option value="12">15-July-2017</option>
<option value="9">29-July-2017</option>
<option value="5">23-July-2017</option>
</select>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Turn options into ms and get the max value, then check if the selected date is as same as the max value.(use pure js)
var periodSelector = document.getElementById('period');
var options = periodSelector.options;
periodSelector.onchange = function(e) {
// get the selected date and convert it to ms
var selectedIndex = this.selectedIndex;
var selectedDate = new Date(options[selectedIndex].text).valueOf();
// convert all date to ms and get the max date
var maxDate = Array.prototype.reduce.call(options, function(maxValue, curValue) {
return Math.max(new Date(curValue.text), maxValue);
}, 0);
// check if selected date is same as max date
if (selectedDate === maxDate) {
alert('Max Date is selected');
}
};
<select id="period" name="PeriodCollection" style="border-radius: 4px; ">
<option value="3">10-July-2017</option>
<option value="12">15-July-2017</option>
<option value="9">29-July-2017</option>
<option value="5">23-July-2017</option>
</select>

JavaScript if statement from select box

I can't figure out where I'm going wrong - when "Europe" is selected nothing happens.
When I take away the if statement it works, so the output code is definitely okay. The problem seems to be with the if condition.
<script>
function shipping_calc() {
var val = document.getElementById.("country").value;
if(val === "Europe") {
document.getElementById("output").innerHTML = "£2.40";
}
}
</script>
<select id="country" onchange="shipping_calc()">
<option value="United Kingdom">United Kingdom</option>
<option value="Europe">Europe</option>
<option value="Worldwide">Worldwide</option>
</select>
<p id="output"></p>
You had an extra . in your javascript. This works.
function shipping_calc() {
var val = document.getElementById("country").value;
if (val === "Europe") {
document.getElementById("output").innerHTML = "£2.40";
}
}
<select id="country" onchange="shipping_calc()">
<option value="United Kingdom">United Kingdom</option>
<option value="Europe">Europe</option>
<option value="Worldwide">Worldwide</option>
</select>
<p id="output"></p>
You had document.getElementById.("country") and it should have been document.getElementById("country").
Try this...
var vall = document.getElementById("country");
var val = vall.options[vall.selectedIndex].value;
if (val === "Europe") {
document.getElementById("output").innerHTML = "£2.40";
}
Here's a fiddle: https://jsfiddle.net/6dvgbjr0/
You had an error in your code, with an extra period:
var val = document.getElementById.("country").value;

How to dynamically generate a dropdown menu [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
In my php, I have created two dropdown or selection lists. My drop down list below:
<select name="food">
<option value="">...</option>
<option value="Fruits">Fruits</option>
<option value="Vegetables">Vegetables</option>
</select>
<select name="type">
<option value="">--</option>
<option value="Apple">Apple</option>
<option value="Lettuce">Lettuce</option>
<option value="Orange">Orange</option>
<option value="Tomato">Tomato</option>
<option value="Carrots">Carrots</option>
<option value="Mango">Mango</option>
</select>
m one page to the next.
It's possible to do this using jQuery, but it will quickly become unmanageable in a large-scale app or website.
If you go this route, I would avoid using two different select boxes, as this will force you to choose two different names for the form POST, unless you use more jQuery hackery to remedy this problem.
My suggestion is to look at a lightweight JS framework. Knockoutjs has what you need.
Look at this JSFiddle.
var fruitOpts = ["Apple", "Orange", "Mango"];
var vegOpts = ["Lettuce", "Tomato", "Carrots"];
$("#food").change(function () {
var val = $(this).val();
if (val === "") {
return;
}
$("#type").find('option').not(':first').remove().end();
$.each(val === "Fruits" ? fruitOpts : vegOpts, function (i, v) {
$("#type").append("<option value=\"" + v + "\">" + v + "</option>");
});
$.each(val === "Fruits" ? vegOpts : fruitOpts, function (i, v) {
$("#type").append("<option value=\"" + v + "\">" + v + "</option>");
});
});
It's version for two different php pages:
1.php
<script src="1.js"></script>
<a id='link' href='2.php'>go to another page</a>
<select id="food" name="food" onchange="selectFoodType()">
<option value="">...</option>
<option value="Fruits">Fruits</option>
<option value="Vegetables">Vegetables</option>
<option value="Berries">Berries</option>
</select>
1.js
function selectFoodType()
{
var link = $('#link');
var type = $('select#food option:selected').val();
link.attr('href', link.attr('href') + '?type=' + type);
}
2.php
<script src="2.js"></script>
<select id='type' name="type" data-type='<?=$_GET['type']?>'>
<option value="">--</option>
<option data-type='Fruits' value="Apple">Apple</option>
<option data-type='Vegetables' value="Tomato">Tomato</option>
<option data-type='Vegetables' value="Carrots">Carrots</option>
<option data-type='Berries' value="Strawberry">Strawberry</option>
</select>
2.js
$(function() {
var type = $('select#type').data('type');
var itemsId = document.getElementById("type");
var items = itemsId.getElementsByTagName("option");
var selected_type = [], other_types = [];
selected_type[0] = items[0];
for (var i = 1; i < items.length; i++){
if ($(items[i]).data('type') === type) {
selected_type.push(items[i]);
continue;
}
other_types.push(items[i]);
}
selected_type = selected_type.sort(sortByName);
other_types = other_types.sort(sortByName);
$.merge(selected_type, other_types);
var list = '';
for (i=0; i<selected_type.length; i++) {
list += selected_type[i].outerHTML;
}
$(items).remove();
$(itemsId).append(list);
});
function sortByName(a, b) {
if (a.text > b.text) return 1;
else if (a.text < b.text) return -1;
return 0;
}
You should assign all Fruits and Vegetables contents in JavaScript object and display related contents of food value in another drop down, see below demo
Food:
<select name="food" id="food">
<option value="">...</option>
<option value="Fruits">Fruits</option>
<option value="Vegetables">Vegetables</option>
</select>
Content
<select name="contents" id="contents">
<option value="">...</option>
</select>
JS code
var data = {
'Fruits':['Apple', 'Lettuce', 'Orange', 'Mango'],
'Vegetables': ['Tomato', 'Carrots']
};
document.getElementById("food").onchange = function(Event){
var contents = document.getElementById("contents");
contents.innerHTML = "";
for(var i in data[this.value]){
var option = document.createElement("option");
option.setAttribute('value',data[this.value][i]);
option.text = data[this.value][i];
contents.appendChild(option);
}
var expect_data = Event.target.value == "Fruits" ? "Vegetables" : "Fruits";
for(var i in data[expect_data]){
var option = document.createElement("option");
option.setAttribute('value',data[expect_data][i]);
option.text = data[expect_data][i];
contents.appendChild(option);
}
}
FIDDLE DEMO
you need to use JQuery for this purpose.
See My Solution: http://jsfiddle.net/inventorx/YU4vJ/
Code Here:
HTML
<select name="food" >
<option value="">...</option>
<option value="Fruits">Fruits</option>
<option value="Vegetables">Vegetables</option>
</select>
<select name='type' >
<option>-- Select Food Type --</option>
</select>
<select id='Fruits' style='display:none' >
<option value="">--</option>
<option value="Apple">Apple</option>
<option value="Orange">Orange</option>
<option value="Mango">Mango</option>
</select>
<select id='Vegetables' style='display:none' >
<option value="">--</option>
<option value="Lettuce">Lettuce</option>
<option value="Tomato">Tomato</option>
<option value="Carrots">Carrots</option>
</select>
JQUERY
$(document).ready(function(){
$("select[name='food']").on("change", function(){
var value = $(this).val();
$("select[name='type']").html($("#" + value).html());
});
});
Another option.
The list splits into two arrays: food, corresponding to the selected type; and does not correspond to the selected type. Each of these arrays, in turn, is sorted by name:
JSFIDDLE
HTML:
<select id="food" name="food" onchange="selectFoodType()">
<option value="">...</option>
<option value="Fruits">Fruits</option>
<option value="Vegetables">Vegetables</option>
<option value="Berries">Berries</option>
</select>
<select id='type' name="type">
<option value="">--</option>
<option data-type='Fruits' value="Apple">Apple</option>
<option data-type='Vegetables' value="Lettuce">Lettuce</option>
<option data-type='Vegetables' value="Tomato">Tomato</option>
<option data-type='Berries' value="Strawberry">Strawberry</option>
</select>
JQuery:
function selectFoodType()
{
var type = $('select#food option:selected').val();
var itemsId = document.getElementById("type");
var items = itemsId.getElementsByTagName("option");
var selected_type = [], other_types = [];
selected_type[0] = items[0];
for (var i = 1; i < items.length; i++){
if ($(items[i]).data('type') === type) {
selected_type.push(items[i]);
continue;
}
other_types.push(items[i]);
}
selected_type = selected_type.sort(sortByName);
other_types = other_types.sort(sortByName);
$.merge(selected_type, other_types);
var list = '';
for (i=0; i<selected_type.length; i++) {
list += selected_type[i].outerHTML;
}
$(items).remove();
$(itemsId).append(list);
}
function sortByName(a, b) {
if (a.text > b.text) return 1;
else if (a.text < b.text) return -1;
return 0;
}

Compose a link based in select's option value

I have 2 dropdown menus, and I need to compose a link with it's values.
Here is the code:
<form id="dropdown1">
<select id="linha">
<option value="G12">Option 1</option>
<option value="G11">Option 2</option>
<option value="H89">Option 3</option>
</select>
<select id="dia">
<option value="all">Every day</option>
<option value="work">working days</option>
<option value="sat">saturday</option>
<option value="sun">sunday</option>
</select>
</form>
I need something in JavaScript to "compose" a link with http://somewebsite.com/*selected_linha_value*/*selected_dia_value*
How can I do that?
<select name="dia" id="dia">
<option value="all">Every day</option>
<option value="http://stackoverflow.com">working days</option>
<option value="http://anotherSite.com">saturday</option>
<option value="http://anotherSite2.com">sunday</option>
</select>
<script>
$("#dia").change(function () {
var selctedValue = "";
$("select option:selected").each(function () {
selctedValue += $(this).val();
window.location.href = selctedValue;
});
});
i think u need something like this.
<script type="text/javascript">
params = getParams();
var name1 = unescape(params["linha"]);
switch(name1)
{
case "g12":
window.location = "http://www.google.com"
}
function getParams(){
var idx = document.URL.indexOf('?');
var params = new Array();
if (idx != -1) {
var pairs = document.URL.substring(idx+1, document.URL.length).split('&');
for (var i=0; i<pairs.length; i++){
nameVal = pairs[i].split('=');
params[nameVal[0]] = nameVal[1];
}
}
return params;
}
Its not the full code. It will give you some idea. If you have any doubt just comment
Take a look at: http://jsfiddle.net/ERHhA/
You can use jQuery val() to get the value of the select boxes. Then just append these values to the base url.
var url = "http://somewebsite.com/" + $('#linha').val() + "/" + $('#dia').val();
What about this one?
function make_url(){
var linha = document.getElementById('linha').value;
var dia = document.getElementById('dia').value;
var url=window.location.href;
var pos=url.indexOf('?');
if (pos>-1){
url = url.substr(0,pos);
}
//alert(url + '?linha='+linha+'&dia='+dia); return;
document.location.href = url + '?linha='+linha+'&dia='+dia;
}
fiddle
HTML
<div class="container">
<select class="small-nav">
<option value="" selected="selected">Go To</option>
<option value="http://whiterabbitexpress.com">Services</option>
<option value="http://shop.whiterabbitjapan.com">Shop</option>
</div><!-- container -->
JScript:
$(".small-nav").change(function() {
window.location = $(this).find("option:selected").val();
});

Categories