I would like to know the best way to populate a select element using jQuery given a hash as seed data.
Ex:
var select_options = {
"option1": ["item1", "item2"],
"option2": ["item3", "item4"]
};
Using different hash keys to set up the select seed data.
Are you looking for something like this. But have to check if somebody has a better way of doing this.
var select_options = {
"option1": ["item1", "item2"],
"option2": ["item3", "item4"]
};
$(function() {
var selectedOption = "option1";
$.map(select_options, function(val, key) { //object
if (key == selectedOption) {
$.map(val, function(item, index) { //array
console.log(item + " " + index);
});
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Compare key of the object or directly access value of object with key. Here are two working example.
Comparing key.
var select_options = {
"option1": ["item1", "item2"],
"option2": ["item3", "item4"]
};
$(function() {
var selectedOption = "option1";
createDropdown(selectedOption);
function createDropdown(selectedOption){
$('select').html("");
$.map(select_options, function(val, key) { //object
if (key == selectedOption) {
$.map(val, function(item, index) { //array
$('select').append($("<option>").attr('value',index).text(item));
});
}
});
}
$('div').on('click', function() {
createDropdown($(this).attr('data-option'));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-option="option1">click for option1</div>
<div data-option="option2">click for option2</div>
<select>
</select>
Accessing value with key.
var select_options = {
"option1": ["item1", "item2"],
"option2": ["item3", "item4"]
};
$(function() {
var selectedOption = "option1";
createDropdown(selectedOption);
function createDropdown(selectedOption){
$('select').html("");
var array = select_options[selectedOption];
$.map(array, function(item, index) { //array
$('select').append($("<option>").attr('value',index).text(item));
});
}
$('div').on('click', function() {
createDropdown($(this).attr('data-option'));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-option="option1">click for option1</div>
<div data-option="option2">click for option2</div>
<select>
</select>
Related
I got the values from json and pass to the autocomplete search field.
[{"id":1,"name":"JAVA"},{"id":2,"name":"cake PHP"},"id":3,"name":"Android"}]
For example, when I click the JAVA, I want to get the id of JAVA like www.example.com/1
Jquery code:
<script>
$('#search').typeahead({
ajax: '/searchendpoint/search',
onSelect: function() {
window.location = "/home/view/" + $(this).val().id; }
});
</script>
When you want to use object array as a source you need to provide the logic for:
which object property to use for matching user input
which property to use for displaying text of the matching items
which property to use when user selects an item
More info:
http://api.jqueryui.com/autocomplete/#option-source
http://api.jqueryui.com/autocomplete/#method-_renderItem
http://api.jqueryui.com/autocomplete/#event-select
var tags = [
{"id":1,"name":"JAVA"},
{"id":2,"name":"cake PHP"},
{"id":3,"name":"Android"}
];
$( "#search" ).autocomplete({
source: function( request, response ) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex( request.term ), "i" );
response( $.grep( tags, function( item ){
return matcher.test( item.name ); // match user request with item.name
}) );
},
select: function( event, ui ) {
event.preventDefault();
$("#search").val( ui.item.name ); // display user selection in textbox
console.log('selected: ' + JSON.stringify(ui) );
console.log('execute window.location = "example.com/' + ui.item.id + '"'); // use id of the selected item to generate required URL
}
});
// provide rendering logic for each matched item
$w = $( "#search" ).data("ui-autocomplete");
$w._renderItem = function( ul, item ) {
//console.log(JSON.stringify(item) );
return $( "<li>" )
.attr( "data-value", item.id )
.append( item.name )
.appendTo( ul );
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<input id="search">
Edit: Using typeahead.js as per your comment.
var data =
[
{"id":1,"name":"JAVA"},
{"id":2,"name":"cake PHP"},
{"id":3,"name":"Android"}
];
$(function(){
var substringMatcher = function(strs) {
return function(q, cb) {
var matches, substringRegex;
// an array that will be populated with substring matches
matches = [];
// regex used to determine if a string contains the substring `q`
substrRegex = new RegExp(q, 'i');
// iterate through the pool of strings and for any string that
// contains the substring `q`, add it to the `matches` array
$.each(strs, function(i, str) {
if (substrRegex.test(str.name)) {
matches.push(str);
}
});
cb(matches);
};
};
$('.typeahead').bind('typeahead:select', function(ev, suggestion) {
console.log('Selection: ' + JSON.stringify(suggestion) );
console.log('execute window.location = "example.com/' + suggestion.id + '"');
});
// passing in `null` for the `options` arguments will result in the default
// options being used
$('.typeahead').typeahead({
hint: true,
minLength: 1
}, {
source: substringMatcher(data),
display: 'name'
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://twitter.github.io/typeahead.js/releases/latest/typeahead.bundle.js"></script>
<div id="prefetch">
<input class="typeahead" type="text" placeholder="">
</div>
More Info:
https://github.com/twitter/typeahead.js/blob/master/doc/jquery_typeahead.md
https://twitter.github.io/typeahead.js/examples/#the-basics
Please follow the solution as below.
HTML
<select id="search">
<option value="1">JAVA</option>
<option value="2">cake PHP</option>
<option value="3">Android</option>
</select>
Javascript
document.addEventListener('change', function(){
window.location = "www.example.com/" + document.getElementById('search').value;
})
Try this. Add event select on bind autocomplete.
$(function () {
var availableTags = [
{"id":1,"value":"JAVA"},
{"id":2,"value":"cake PHP"},
{"id":3,"value":"Android"}
];
$("#search").autocomplete({
source: availableTags,
select: function(event, ui) {
window.location = "www.example.com/" + ui.item.id;
}
});
});
I am not sure that I understand your question, but do you mean something like this?
JSON:
[{"id":1,"name":"JAVA"},{"id":2,"name":"cake PHP"},"id":3,"name":"Android"}]
jQuery:
<script>
var url = "http://example.com/";
$('#search').change(function() {
window.location = url + $(this).val().id;
});
</script>
onSelect function pass itemas variable you can use it in select event and it's structure like below
{
value: "1",
text: "Toronto"
}
and please try below code
<script>
$('#search').typeahead({
ajax: '/searchendpoint/search',
onSelect: function(item) {
//console.log(item);
window.location = "/home/view/" + item.value;
}
});
</script>
var data = [{
"id": 1,
"name": "JAVA"
}, {
"id": 2,
"name": "cake PHP"
}, {
"id": 3,
"name": "Android"
}]
var data_text = [];
var data_obj = [];
$.each(data, function(index, _data) {
data_text.push(_data.name);
data_obj[_data.name] = _data;
});
$('#search').typeahead({
source: data_text,
updater: function(item) {
alert(data_obj[item].id)
window.location = "/home/view/" + data_obj[item].id;
}
});
This is almost same answer as Vevik but just adjusted version of what the question actually wanted and tried to do. I have tested it.
<html>
<head>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
$(function(){
var data = [{
"id": 1,
"name": "JAVA"
}, {
"id": 2,
"name": "cake PHP"
}, {
"id": 3,
"name": "Android"
}];
var data_labels = [];
var data_dictionay = [];
$.each(data, function(index, _data) {
data_labels.push(_data.name);
data_dictionay[_data.name] = _data.id;
});
$('#search').autocomplete({
source : data_labels,
select: function(ui, item) {
if(data_dictionay[item.item.value]){
window.location = "/home/view/" + data_dictionay[item.item.value];
}
}
});
});
</script>
</head>
<body>
<input id="search" type="text">
</body>
</html>
I dont know which typeahead you used, but i try to make an example
Try this:
$('#my-autoc').typeahead({
name: 'search',
remote: {
url: 'https://suggestqueries.google.com/complete/search?client=chrome&q=%QUERY',
dataType: 'jsonp',
cache: false,
filter: function(parsedResponse){
return (parsedResponse.length > 1) ? parsedResponse[1] : [] ;
}
}
}).on('typeahead:selected', function(e, data){
// its example
//window.location = "http://www.example.com/" + data.value
console.log("window.location = \"http://www.example.com/" + data.value + "\"")
// for your code
// window.location = "http://www.example.com/" + data.id
});
#import url('https://getbootstrap.com/dist/css/bootstrap.css');
#import url('https://rawgithub.com/jharding/typeahead.js-bootstrap.css/master/typeahead.js-bootstrap.css');
body{
padding: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://rawgithub.com/zeMirco/typeahead.js/master/dist/typeahead.min.js"></script>
<form id="my-form">
<input class="form-control" name="search" type="text" placeholder="type something ..." id="my-autoc">
<br>
</form>
Bootstrap's typeahead uses the properties label and value.
Try mapping your current array to these before passing it to typeahead.
results.map((item) => {
return {
"label": item.name,
"value": item.id
}
}
I need to convert an entire UL and it's children elements into a JSON object.
This is what we did:
function getData(el) {
el.find('li').each(function () {
data.push({ "nome": $(this).find('span').html(), "cargo": $(this).find('strong').html() });
});
}
JS Fiddle: https://jsfiddle.net/cbzo0ef2/2/
But all elements are in the same level. In this case, all levels need to be kept.
$(this).parents("ul").length would be trick for you:
function getData(el) {
el.find('li').each(function () {
data.push({ "nome": $(this).find('span').html(), "cargo": $(this).find('strong').html(), "dept": $(this).parents("ul").length })
});
}
You need extra work to render dept to your json structure
see fiddle
This solution will retain the levels in your HTML:
(function($) {
function getData(el) {
var data = [];
el.children('li').each(function () {
var currentElement = $(this);
var nomeElement = currentElement.children('span')[0];
var cargoElement = currentElement.children('strong')[0];
var item = {};
if (nomeElement && cargoElement) {
item.nome = $(nomeElement).html();
item.cargo = $(cargoElement).html();
}
data.push(item);
var child = currentElement.children('ul')[0];
if (child != null) {
item.children = getData($(child));
}
});
return data;
}
var data = getData($('.root'));
console.log(data);
})(jQuery);
See fiddle: https://jsfiddle.net/52t58551/
Using jQuery Children and some recursion you can get every node.
(function($) {
function getData(el) {
var curr = [];
el.children('li, ul').each(function(i, child) {
curr.push({
nodeName: child.nodeName,
nome: $(child).find("> span").text(),
cargo: $(child).find("> strong").text(),
subLevel: getData($(child))
});
});
return curr
}
var result = getData($('.root'));
console.log(JSON.stringify(result));
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="root"> <li><span>a</span><strong>b</strong></li><li><span>c</span><strong>d</strong></li><li><span>e</span><strong>f</strong></li><li> <ul> <li><span>g</span><strong>h</strong></li><li><span>i</span><strong>j</strong></li><li> <ul> <li><span>k</span><strong>l</strong></li></ul> </li></ul> </li></ul>
I'm working with list of checkboxes and I have next logic behavior for it:
if all items selected, checkbox "select all" is checked
if one of all selected items has been unchecked, checkbox "select all" is unchecked as well
This logic is clear. Depends of what item is checked I extract its id to an additional array and then using this array for request that to get data.
For pushing everything works fine, but for slicing the logic is strange. So I can slice the array until first item is checked, however I unchecked the first item, pushed and sliced items no more related with checkboxes.
I have reproduced plunker with it, so I appreciate if anybody could help me to find what I'm missing.
$scope.modelClass = {
selectedAll: false
};
$scope.selectAllClass = function (array) {
angular.forEach(array, function (item) {
item.selected = $scope.modelClass.selectedAll;
$scope.param =''
});
};
$scope.checkIfAllClassSelected = function (array) {
$scope.modelClass.selectedAll = array.every(function (item) {
return item.selected == true
});
$scope.checked = array.filter(function (item) {
return item.selected == true
}).length;
angular.forEach(array, function (obj) {
if(obj.selected == true){
requestClass(obj)
}
});
};
var selectedClass = [];
var requestClass = function (obj) {
selectedClass.push(obj);
angular.forEach(selectedClass, function (val) {
if (val.selected != true) {
selectedClass.splice(selectedClass.indexOf(val.id), 1);
}
else {
selectedClass = selectedClass.filter(function (elem, index, self) {
return index == self.indexOf(elem);
})
}
});
$scope.param = _.map(selectedClass, 'id')
};
$scope.classes = [
{"id":4,"name":"Achievement","selected":false},
{"id":13,"name":"Information","selected":false},
{"id":6,"name":"Issue","selected":false},
{"id":5,"name":"Message","selected":false},
{"id":9,"name":"Request","selected":false}
]
The logic looks good for me, not sure what's wrong here. I've took the first solution from this post (it looks like you are using the second one) and slightly modified it for your needs.
$scope.model = {
selectedClass : []
}
$scope.isSelectAll = function(){
$scope.model.selectedClass = [];
if($scope.master){
$scope.master = true;
for(var i=0;i<$scope.classes.length;i++){
$scope.model.selectedClass.push($scope.classes[i].id);
}
}
else{
$scope.master = false;
}
angular.forEach($scope.classes, function (item) {
item.selected = $scope.master;
});
$scope.param = $scope.model.selectedClass
}
$scope.isChecked = function() {
var id = this.item.id;
if(this.item.selected){
$scope.model.selectedClass.push(id);
if($scope.model.selectedClass.length == $scope.classes.length ){$scope.master = true;
}
} else {
$scope.master = false;
var index = $scope.model.selectedClass.indexOf(id);
$scope.model.selectedClass.splice(index, 1);
}
$scope.param = $scope.model.selectedClass
}
$scope.classes = [
{"id":4,"name":"Achievement","selected":false},
{"id":13,"name":"Information","selected":false},
{"id":6,"name":"Issue","selected":false},
{"id":5,"name":"Message","selected":false},
{"id":9,"name":"Request","selected":false}
]
html
<div ng-class="{'selected': master, 'default': !master}">
<div>
<input type="checkbox" ng-model="master" ng-change="isSelectAll()" > Select all
</div>
</div>
<div ng-repeat="item in classes | orderBy : 'id'" ng-class="{'selected': item.selected, 'default': !item.selected}">
<div >
<input type="checkbox" ng-model="item.selected" ng-change="isChecked()">
{{ item.name }}
</div>
</div>
this is fixed plunker
I'm trying to write a jQuery code that works in this way:
When the page is loaded, it is presents only one field.
Selecting an option from that field, a new field is opened and the option have to be all the option of the first , except the option selected. And so on, also for the other created.
The jsfiddle is shown here
var globalObj = {};
var selectedObj = {};
var unselectedObj = {};
var currentSelection = "";
function deleteByVal(obj,val) {
for (var key in obj) {
if (obj[key] == val) delete obj[key];
}
}
$(document).ready(function () {
$(document).on('click', 'target', function(){
var curSelected = $(this).find(":selected").text();
});
$("#select1").one('click',function(){
$(this).children().each(function () {
globalObj[this.value] = this.innerHTML;
});
unselectedObj = globalObj;
});
$(document).on('change', '.prova > .target', function () {
$('div').removeClass('prova');
var $mySelect = $('<select>', {
class: 'target'
});
var selectedValue = $(this).find(":selected").text();
var found = 0;
$.each(selectedObj, function (val, text) {
if (val === selectedValue) {
found++;
}
});
if (found===0) {
selectedObj[this.value] = selectedValue;
deleteByVal(unselectedObj,selectedValue);
}
console.log(selectedValue);
console.log(selectedObj);
console.log(unselectedObj);
var obj = {}; //create an object
$(this).children().each(function () {
if (this.innerHTML!=selectedValue) {
//code
obj[this.value] = this.innerHTML;
}
});
console.log("Questo rappresenta obj:");
console.log(obj);
console.log("stampa obj conclusa");
$( "select" ).not(this).each(function( index ) {
var temp = {}; //create an object
$(this).children().each(function () {
if (this.innerHTML === selectedValue) {
console.log("eliminazione");
$(this).remove();
}
});
$this = $(this);
console.log("stampa temp");
console.log(temp);
console.log("fine stampa temp");
});
$.each(unselectedObj, function (val, text) {
$mySelect.append($('<option />', {
value: val,
text: text
}));
});
var $input = $('<input>', {
type: 'number',
style: 'width: 35px',
min: '1',
max: '99',
value: '1'
});
var $button = $('<button>', {
type: 'button',
class: 'remove_item',
text: 'delete'
});
$(this).parent().after($('<br>', {
class: 'acapo'
}), $('<div>', {
class: 'prova'
}).append($mySelect, $input, $button));
$(this).unbind('change');
$(this).unbind('click');
$(this).on('click', function(){
currentSelection = $(this).find(":selected").text();
});
$(this).on('change',function(){
console.log("nuovo bind");
var selectedValue = $(this).find(":selected").text();
if (currentSelection !== selectedValue) {
console.log(currentSelection + " to "+ selectedValue);
$( "select" ).not(this).each(function( index ) {
$(this).append($('<option />', {
value: currentSelection,
text: currentSelection
}));
$(this).children().each(function () {
if (this.innerHTML === selectedValue) {
console.log("eliminazione");
$(this).remove();
}
});
});
}
});
});
});
The code has some problems and I was thinking to use an existing plugin instead of that code. Is there anyone that knows a plug-in which makes that work?
Here's an option using javascript templating. I'm declaring my available options at the top in an array, thus separating my data model from the UI. I'm using the handlebars library to then compile a template and append it into the DOM. Fiddle: http://jsfiddle.net/LNP8d/1/
HTML/Handlebars
<script id="select-template" type="text/x-handlebars-template">
<div>
<select class="target" id ="select-{{id}}">
<option value="">Select an option…</option>
{{#each options}}
{{#unless selected}}
<option data-option-key="{{#key}}" value="{{value}}">{{label}}</option>
{{/unless}}
{{/each}}
</select>
<input type="number" style="width: 35px" min="1" max="99" value="1">
</div>
</script>
<div id="container">
</div>
Javascript
//Declare the available options
var options = {
option1: {
value: 1,
label: "Option 1"
},
option2: {
value: 2,
label: "Option 2"
},
option3: {
value: 3,
label: "Option 3"
},
option4: {
value: 4,
label: "Option 4"
},
}
source = $("#select-template").html(),
template = Handlebars.compile(source),
onScreen = 0;
//Adds another select menu
var showSelect = function(){
onScreen++;
$("#container").append(template({id:onScreen, options:options}))
};
//Listens to change events
$("body").on("change", ".target", function(){
options[$(this).find(":selected").data("option-key")].selected = true;
showSelect();
});
//Initialises the UI
showSelect();
Please note: this is not a complete example. If you decide to use this method, you'll need to add some checks for what happens when the options run out and if someone changes an option. I hope it's successful in showing you an alternative a potentially more flexible method though.
I think you are looking for something like this:
http://codeassembly.com/Simple-chained-combobox-plugin-for-jQuery/
I have a list of checkboxes. Upon clicking on each of the checkboxes i am adding the value to the hidden variable. But the question is if I want to remove the value from the list upon unchecking the checkbox . How this piece cab be done
here is the hidden form variable
<input name="IDList[]" type="hidden" id="IDList" value="" />
and the jquery
$(".myCheckboxClass").change(function() {
var output = 0;
$(".myCheckboxClass").change(function() {
if ($(this).is(":checked")) {
output += ", " + $(this).val();
} else {
output = $.grep(output, function(value) {
return value != $(this).val();
});
}
$("#IDList").val(output);
});
});
Something like this: (demo) http://jsfiddle.net/wesbos/5N2kb/1/
we use an object called vals to store the info. ADding and removing as we check/uncheck.
var vals = {};
$('input[type=checkbox]').click(function() {
var that = $(this);
if (that.is(':checked')) {
console.log(this.name);
vals[this.name] = "In your Object";
}
else {
delete vals[this.name];
}
console.log(vals);
});
Following your logic, you could do this:
$('#IDList').data('value', []);
$(".myCheckboxClass").change(function() {
var list = $('#IDList').data('value');
if ($(this).is(":checked")) {
list.push($(this).val());
} else {
var indexToRemove = list.indexOf($(this).val());
list.splice(indexToRemove, 1);
}
$('#IDList').val(list);
});
But if you only care about the value of #IDList upon data submission or other actions, you probably want to consider an alternative approach: collating the checked values when you need them.
$('#form').submit(function() {
var list = $('input.myCheckboxClass:checked', this).map(function() {
return $(this).val();
}).get();
$('#IDList').val(list);
});
See both of the above in action: http://jsfiddle.net/william/F6gVg/1/.