I am not sure if Select tag is the best way to go, but here is what I have:
<select size="20" style="width:25%;">
<option>State 01</option>
<option>City 01</option>
<option>City 02</option>
<option>City 03</option>
<option>State 02</option>
<option>City 01</option>
<option>State 03</option>
<option>City 01</option>
<option>City 02</option>
</select>
Currently I am seeking advice and suggestions. Long story short, this box will be placed next to a map and when a specific state is selected, it will be shown on the map and I am hoping to show a list of cities for that state (only when the state is selected, not before). And then the user can select a city from the options to see on the map. If another state is selected, a new "dropdown" of cities will be shown for the newly selected state and the previously selected state's cities will go into hiding again.
I have seen code with select optgroup tag (https://stackoverflow.com/a/9892421/5003918), but I am wanting the hide-show functionality as well.
Should I just have two separate select boxes? One with states filled in, and another (initially empty) which will be filled in with cities when a state is selected? Or perhaps an unordered list? Zero or one state will be selected at any given time.
There are couple of ways to achieve what you're looking for. One way to have two separate drop-down menus , one for states and one for cities that got populated automatically based on the selected state.
Next thing will be , the data source , where would you get the list of states/cities with association (which cities belong to which state). Once again there are a lot of options here , In the example i am sharing , I chose a JSON ' s like structure but you can pick anything else.
I used pure JS code but you can easily use another library suck as JQuery and it will shorten the lines of code.
JS CODE
var States = [{
key: 13,
name: "State1",
cities: ["City1", "City2", "Silver Spring"]
}, {
key: 2,
name: "State2",
cities: ["City5", "City9", "City8","San Diego"]
}];
//populate states
for (var i = 0; i < States.length; i++) {
var opt = States[i];
var el = document.createElement("option");
el.textContent = opt.name;
el.value = opt.key;
StatesList.appendChild(el);
}
//Populate initial cities
populateCities();
//populate cities
function populateCities() {
//clear the cities list
document.getElementById('CitiesList').options.length = 0;
var e = document.getElementById("StatesList");
var selectedState = e.options[e.selectedIndex].value;
var listOfCities;
for (var i = 0; i < States.length; i++) {
if (States[i].key == selectedState) {
listOfCities = States[i].cities;
break;
}
}
//populate Cities DropDown menu
for (var i = 0; i < listOfCities.length; i++) {
var opt = listOfCities[i];
var el = document.createElement("option");
el.textContent = opt;
el.value = opt;
CitiesList.appendChild(el);
}
}
HTML
<div class="DDStyle" id="states" onChange="populateCities()">
States :
<select id="StatesList" class="DDStyle" >
</select>
</div>
<div id="Cities" class="DDStyle">
Cities :
<select id="CitiesList" class="DDStyle">
</select>
</div>
http://codepen.io/anon/pen/wKzqYG
Related
I was trying to copy monthly performance data from investing.com
When I type "http://www.investing.com/indices/stoxx-600-historical-data" for the website, it presents, at default value, only daily data.
However, I want to catch monthly performance. On the website, I can simply click drop down menu and click "monthly".
I find the webpage code (maybe called xml?) for the drop down menu:
<div class="float_lang_base_1">
<select class="newInput selectBox float_lang_base_1" id="data_interval">
<option value="Daily" selected="">Daily</option>
<option value="Weekly">Weekly</option>
<option value="Monthly">Monthly</option>
</select>
</div>
I have tried to change the "selected" attribute to monthly, by such vba code:
html.getElementsByTagName("select")("data_interval").Children(0).removeAttribute("selected", "=") = ""
html.getElementsByTagName("select")("data_interval").Children(2).setAttribute("selected", "") = ""
The page will present "monthly" in the time frame drop down menu, but it did not work out. The data I download will still be daily.
I have also tried to change the value of "time frame" to "Monthly", I got the same result. The code is as follows:
html.getElementsByTagName("select")("data_interval").Value = "Monthly"
Both present the webpage like this: click me
Is there any method to solve the problem?
There is also code in the webpage.
function historical_submit(isInterval) {
var isDatePicked = !isInterval;
if(!firstTimePicker) isDatePicked=true;
var dateFormat = $.datepicker.regional[''].dateFormat;
var dateTo =new Date();
var dateFrom = new Date();
var intervalInDays=30;
if(isDatePicked) {
var dates = $.datepicker._getFromToDates($.datepicker._curInst,'yy-mm-dd');
if (dates !== null) {
dateFrom=dates.dateFrom;
dateTo=dates.dateTo;
}
}
else {
if ($('#data_interval').val() === 'Weekly') {intervalInDays = 52 * 7}; //365 - full year
if ($('#data_interval').val() === 'Monthly') {intervalInDays = 30 * 24}; //~ 2 years
var dateFromObj=new Date();
dateFromObj.setDate(dateFromObj.getDate() - intervalInDays);
dateFrom= dateFromObj;//$.datepicker.formatDate(dateFormat,dateFromObj);
}
I think this should work:
html.getElementById("data_interval").options.selectedIndex = 2;
REVISION
After further investigation, the onchange event must be triggered. Let's try this:
var selected = html.getElementById("data_interval");
selected.options.selectedIndex = 2;
selected.onchange();
REVISION-2
Dim html As New HTMLDocument
Set thtml = html.createDocumentFromUrl("http://bunkerhill.com/test.html", vbNull)
Dim sel As HTMLSelectElement
sel = html.getElementsByClassName("newInput selectBox")
sel.selectedIndex = 2
sel.FireEvent ("afterupdate")
Pure JavaScript jsFiddle
I'm trying to show the parent child elements in dropdown select list.as the following image
i have the code as in foreach
#helper GetOption(List<Project_Cost_Management_System.Models.ChartOfAccount> model1, Guid? parentid)
{
foreach (var item3 in model1.Where(s => s.ParentAccountId.Equals(parentid)))
{
var zs3 = model1.Where(s => s.ParentAccountId == item3.Id);
int count3 = zs3.Count();
if (count3 >= 0)
{
if(#item3.ParentAccountId == null)
{
<option value="#item3.Id">#item3.Name</option>
}
else
{
var cout = model1.Count();
<option value="#item3.Id"> #item3.Name #model1.Where(s => s.dataid == #item3.dataparentid).Select(d => d.Name).First(). </option>
}
}
if (count3 > 0)
{
#GetOption(model1, item3.Id)
}
}
}
but it showed as
How can i display as the first picture.
You can sort of achieve what you're looking for using <optgroup>, so your rendered HTML would end up being something like:
<option value="...">Professional Fees</option>
<optgroup label="Property Related Expenses">
<option value="...">Maintenance Contribution</option>
...
</optgroup>
...
The only problem you might have with this, is that your actual groupings are not valid options themselves, i.e. you can't pick "Property Related Expenses", because it's just a grouping label. You also can't really control your right aligned descriptive text this way. In general, the HTML select element is pretty restrictive and doesn't allow a whole lot of customization.
When you need more advance functionality, you must move some sort of library that creates a "control" that mimics the functionality of a select list with more customizable HTML elements. There's a million and one different such libraries out on the interwebs, but I'm particular fond of Select2.js. In particular to your scenario, see the section there on "Templating".
I Got Answer.
Adding another field in model class as Hierarchy.
Adding space using the hierarchy. I add my code for refer.
#helper GetOption(List<Project_Cost_Management_System.Models.ChartOfAccount> model1, Guid? parentid)
{
foreach (var item3 in model1.Where(s => s.ParentAccountId.Equals(parentid)))
{
var zs3 = model1.Where(s => s.ParentAccountId == item3.Id);
int count3 = zs3.Count();
if (count3 >= 0)
{
if (#item3.ParentAccountId == null)
{
<option value="#item3.Id">#item3.Name</option>
}
else
{
int str = #item3.Hierarchy * 3;
string str1 = " ".ToString().PadRight(str);
str1 = str1.Replace(" ", "\u00a0");
<option value="#item3.Id">#str1 #item3.Name</option>
}
}
if (count3 > 0)
{
#GetOption(model1, item3.Id)
}
}
}
I am attempting to find a way so that when a user enters text into the data list, they can come across the same entry by course number (E.G. "CS 101") or course name (E.G. "Intro to Computer Science).
Currently, what I have is only searchable by the value field:
<datalist id="tagList">
<option value=""></option>
<option value="CSCI 4950">Senior Software Project</option>
<option value="CSCI 5117">Developing the Interactive Web</option>
<option value="CSCI 5421">Advanced Algorithms</option>
<option value="CSCI 5980">Design Methods for Comp. Sci.</option>
</datalist>
The solution needs to work in the Android Webkit web browser (Phonegap) -- Chrome seems to handle Datalists the same as Android's native browser so if it works in Chrome I should be ok.
It needs to display both the course name and course number to the user
This needs to be generalizable and not hard-coded as I am using AngularJS to actually populate the full list of courses.
What I've tried
https://stackoverflow.com/a/22827978/2831961 -- For some reason, this didn't work.
I've also tried a similar strategy, but with the data-value attribute. That didn't work either. Unless I am responsible for some behind the scenes Javascript work that I am unaware of.
http://jsfiddle.net/rh48cgrj/3/
Here's a fiddle. I put the option values/text into key:value pairs in a javascript object. NOTE: the key is an index number and the value is the option value attribute AND the text. This makes it easier to search them for our text.
var i = 0;
var selectItems = {}
$('#tagList option').each(function() {
var listvalue = $(this).val();
var listtext = $(this).text();
selectItems[i] = listvalue + " " + listtext + ",";
i++;
});
Then I split them into rows that included both value and text.
count = i;
for(i=0; i < count;i++) {
var blockoftext = blockoftext + " " + selectItems[i].toLowerCase() + ",";
}
I then setup a search function that would search those rows to see if any returned a match, and if they did the result was outputted to a div below the search box.
var texttosplit = blockoftext.split(",");
var searchresults;
for(i=0; i < texttosplit.length; i++) {
(texttosplit[i].indexOf(searchvalue.toLowerCase()) != -1) ?
(searchresults = texttosplit[i] + "<br>") : false;
$("#searched").html(searchresults);
}
There's an example for all of the above in the fiddle.
EDIT: The below is the commented code for the loop to check if search text is in the datalist per op request.
for (i = 0; i < texttosplit.length; i++) {
//The above loops through our array of class values and titles
(texttosplit[i].indexOf(searchvalue.toLowerCase()) != -1) ?
// The above determines if our search text is in class title using a ternary operator
// our array of class values and titles is lowercase so we make
//sure our search text is lowercase as well
// if we find a match between the search text and the class title/values perform the following:
(searchresults = texttosplit[i].replace(/\b[a-z]/g, function(letter) {
return letter.toUpperCase();
})
// The above replaces the first char of every word with an uppercase char
.replace("Csci", "CSCI") + "<br>",
// The above finds Csci and changes it to CSCI since all THOSE letters should be uppercase
prevtext = $("#searched").html(),
//get current text of element with id "searched" and place it in prevtext
$("#searched").html(prevtext + searchresults))
//append "searched" by adding it's current text with the new searchresults
:
//if search text is not in the class title return false
false;
}
That's a pretty long winded statement.
I'm building a faceted search which implements WebAPI in .Net and utilizes Knockout on the front end. My search response includes two lists of objects, the Resources (object with data for presentation) and Resource Facets (array of strings).
\"ResourceFacets\": [\r\n \"Book\",\r\n \"Video\",\r\n \"DVD\",\r\n \"eBook\",\r\n \"Audio\"\r\n ]\r\n}"
My ViewModel contains both the facets and the resources along with a presentation object to handle a custom row count:
function ViewModel() {
this.facets = ko.observableArray(results.ResourceFacets);
this.resources = ko.observableArray(results.ResourceResults);
this.resourceRows = ko.computed(function() {
var rows = [],
rowIndex = 0,
itemsPerRow = 2;
var resourceList = this.resources();
for (var index = 0; index < resourceList.length; index++) {
if (!rows[rowIndex]) {
rows[rowIndex] = [];
}
rows[rowIndex].push(resourceList[index]);
if (rows[rowIndex].length == itemsPerRow) {
rowIndex++;
}
}
return rows;
});
};
This allowed me to create a dynamic list of checkboxes to handle the facets and also display the resource results. What I'm trying to do now is add a Select All checkbox which will, by default, select all the boxes. From other examples I've seen, my understanding is that I need an observable property, something like "Selected", on that ResourceFacet. I just feel like that is too much that the API needs to know about my presentation.
So my question is how can I avoid having to add a "selected" bool value to the ResourceFacets but still be able to select all checkboxes or deselect the "All" checkbox when a user deselects a facet?
You can keep the list of booleans necessary to track the selection on a separate member of your view model, in addition to facets and resources. Just create a new observableArray of booleans of the same size of facets and bind those values to the checkboxes.
Another solution is to create the objects necessary to bind the checkboxes on the fly, based on results.ResourceFacets, keeping your API clean. For example:
var realModel = [];
for (var i = 0; i < results.ResourceFacets; i++) {
realModel.push({ name: results.ResourceFacets[i], chkBoxVal: ko.observable(false) });
}
this.facets = ko.observableArray(realModel);
I have a requirement for a select html element that can be duplicated multiple times on a page. The options for these select elements all come from a master list. All of the select elements can only show all of the items in the master list that have not been selected in any of the other select elements unless they just were duplicated.
When you select a new item from a duplicated select element, it seems to select the option after the one you selected even though the model still has the correct one set. This always seems to happen in IE11 and it happens sometimes in Chrome.
I realize this sounds convoluted, so I created a jFiddle example.
Try these steps:
Select Bender
Click the duplicate link
Select Fry (on the duplicated select)
Notice that the one that is selected is Leela but the model still has Fry (id:2) as the one selected
Can anyone tell me how I might get around this or what I might be doing wrong?
Here is the relevant Angular code:
myapp.controller('Ctrl', function ($scope) {
$scope.selectedIds = [{}];
$scope.allIds = [{ name: 'Bender', value: 1},
{name: 'Fry', value: 2},
{name: 'Leela', value: 3 }];
$scope.dupDropDown = function(currentDD) {
var newDD = angular.copy(currentDD);
$scope.selectedIds.push(newDD);
}
});
angular.module('appFilters',[]).filter('ddlFilter', function () {
return function (allIds, currentItem, selectedIds) {
//console.log(currentItem);
var listToReturn = allIds.filter(function (anIdFromMasterList) {
if (currentItem.id == anIdFromMasterList.value)
return true;
var areThereAny = selectedIds.some(function (aSelectedId) {
return aSelectedId.id == anIdFromMasterList.value;
});
return !areThereAny;
});
return listToReturn;
}
});
And here is the relevant HTML
<div ng-repeat="aSelection in selectedIds ">
Duplicate
<select ng-model="aSelection.id" ng-options="a.value as a.name for a in allIds | ddlFilter:aSelection:selectedIds">
<option value="">--Select--</option>
</select>
</div>
Hi I have just made a small change in your dupDropDown function as follows
$scope.dupDropDown = function(currentDD) {
$scope.selectedIds.push({});
}
Please check if this works for you.