How do I make a link open in an option - jquery-select2

I added a link to the options, but when clicked only the option is selected. How do I make the link open without making a selection?
$(document).ready(function() {
$('.js-select-multi').select2({
placeholder: 'Select an option',
templateResult: formatOption
});
function formatOption(option) {
var $option_text = '';
var $option_details = '';
var $option_url = '';
$option_head = $(
'<div style="display: flex; flex-direction: column; flex-wrap: wrap; justify-content: space-between;">'
);
$option_text = $(
'<div style="font-size: 14px; min-width: 70%; height: 100%;">' + option.text + '</div>'
);
if ($(option.element).data('details')) {
$option_details = $(
'<div style="font-size: 10px; min-width: 70%; height: 100%;">' + $(option.element).data('details') + '</div>'
);
}
if ($(option.element).data('url')) {
$option_url = $(
'<div style="font-size: 9px; height: 100%; width: 30%;">Preview</div>'
);
}
$option_foot = $(
'</div>'
);
return $option_head.append($option_text).append($option_details).append($option_url).append($option_foot);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2#4.1.0-rc.0/dist/js/select2.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/select2#4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<div id="main">
<select class="js-select-multi" name="demos[]" id="userInput" style="width: 650px;" multiple="multiple">
<optgroup label="Opt Group 1">
<option value="90d1aba6" data-details="Customer" data-url="https://yahoo.com">Option #1</option>
<option value="238e894f" data-details="Customer" data-url="https://yahoo.com">Option #2</option>
</optgroup>
<optgroup label="Opt Group 2">
<option value="574b18e9" data-details="Customer" data-url="https://yahoo.com">Option #3</option>
<option value="5b626e8b" data-details="Customer" data-url="https://yahoo.com">Option #4</option>
</optgroup>
</select>
</div>

I was able to get this to work with version 3.5.4 of select2. Does not work on select2 4.x
$(document).ready(function() {
var select2 = $(".js-select-multi").select2({
formatResult: format,
allowClear: true
}).data('select2');
select2.onSelect = (function(fn) {
return function(data, options) {
var target;
if (options != null) {
target = $(options.target);
}
if (target && target.hasClass('link')) {
target_url = $(data.element).data('url');
//alert(target_url);
var win = window.open(target_url, '_blank');
if (win) {
//Browser has allowed it to be opened
win.focus();
} else {
//Browser has blocked it
alert('Please allow popup to preview demoboards');
}
} else {
return fn.apply(this, arguments);
}
}
})(select2.onSelect);
function format(option) {
if (!option.id) {
return option.text; // optgroup
} else {
var $option_text = '';
var $option_details = '';
var $option_url = '';
$option_head = $(
'<div style="display: flex; flex-direction: column; flex-wrap: wrap; justify-content: space-between;">'
);
$option_text = $(
'<div style="font-size: 14px; min-width: 70%; height: 100%;">' + option.text + '</div>'
);
if ($(option.element).data('details')) {
$option_details = $(
'<div style="font-size: 10px; min-width: 70%; height: 100%;">' + $(option.element).data('details') + '</div>'
);
}
if ($(option.element).data('url')) {
$option_url = $(
'<div style="font-size: 9px; height: 100%; width: 30%;"><a class="link" href="' + $(option.element).data('url') + '">Preview</a></div>'
);
}
$option_foot = $(
'</div>'
);
return $option_head.append($option_text).append($option_details).append($option_url).append($option_foot);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.4/select2.min.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.4/select2.min.js"></script>
<select class="js-select-multi" name="demos[]" id="userInput" style="width: 650px;" multiple="multiple">
<optgroup label="Opt Group 1">
<option value="90d1aba6" data-details="Customer" data-url="https://yahoo.com">Option #1</option>
<option value="238e894f" data-details="Customer" data-url="https://yahoo.com">Option #2</option>
</optgroup>
<optgroup label="Opt Group 2">
<option value="574b18e9" data-details="Customer" data-url="https://yahoo.com">Option #3</option>
<option value="5b626e8b" data-details="Customer" data-url="https://yahoo.com">Option #4</option>
</optgroup>
</select>

Related

Why does my CSS code renders incorrectly on iOS/MacOS?

We developed a web app on Vue 3 and it displays perfectly on every browser except on iOS and Mac OS devices.
This is worse if you're using Safari, however some issues occur even on Chrome for Mac.
This problem causes forms to always be shown blank, without displaying a placeholder or user input. It also makes several other elements to misalign.
We even tried making a new form and removing all stylesheets, but the problem persists.
Here is the code for one of the forms:
<template>
<div>
<form class="contactus" #submit.prevent="saveMessage">
<div class="row">
<h1 class="titleFormAbout">
{{ $t("contactus.componentForm.text1") }}
</h1>
</div>
<p style="margin-bottom: 30px;">{{ $t("contactus.componentForm.text9") }}</p>
<input type="text" class="form-control formContact" :placeholder="$t('contactus.componentForm.text2')" id="name" required />
<input type="email" class="form-control formContact" :placeholder="$t('contactus.componentForm.text3')" id="email" required />
<vue-tel-input
v-model="phone"
id="phone"
class="formControl formContact"
></vue-tel-input>
<br />
<textarea
class="form-control formContact"
name=""
id="message"
rows="10"
:placeholder="$t('contactus.componentForm.text5')"
required
></textarea>
<br />
<vue-recaptcha
style="margin-bottom: 14px"
#validate="validated"
/>
<div class="row">
<div class="col-6">
<input
class="form-control "
type="Submit"
id="submitButton"
:value="$t('contactus.componentForm.text6')"
disabled
/>
</div>
<div class="col-6">
<button class="form-control clear" #click="clearForm" >
{{ $t("contactus.buttonClear") }}
</button>
</div>
</div>
<br />
<div class="alert" id="Response" role="alert"></div>
</form>
</div>
</template>
<script>
import axios from "axios";
import VueRecaptcha from "../forms/vue-recaptcha.vue";
const hostName = location.port =="" ?location.protocol + "//" + location.host:'http://'+location.hostname+':3000';
export default {
components: {
VueRecaptcha,
},
data() {
return {
config: {
headers: {
//'Content-Type': 'application/x-www-form-urlencoded'
"Content-Type": "multipart/form-data",
},
},
};
},
methods: {
validated(){
const htmlElement=document.getElementById('submitButton');
htmlElement.classList.add('submit');
htmlElement.disabled=false;
},
clearForm() {
document.getElementById("name").value = "";
document.getElementById("email").value = "";
document.getElementsByName("telephone")[0].value = "";
document.getElementById("message").value= "";
},
saveMessage() {
//alert(document.getElementsByClassName("highlighted")[0].getElementsByTagName('span')[0].innerHTML)
const responseBox = document.getElementById("Response");
const params = new FormData();
const countryPhone = document.getElementsByClassName("highlighted");
var countryPhoneid = "+52";
if (countryPhone.length > 0) {
countryPhoneid =
countryPhone[0].getElementsByTagName("span")[0].innerHTML;
}
params.append("name", document.getElementById("name").value);
params.append("email", document.getElementById("email").value);
params.append("phone",countryPhoneid + " " + document.getElementsByName("telephone")[0].value);
params.append("message", document.getElementById("message").value);
axios
.post(hostName + "/api/contact", params, this.config)
.then((response) => {
responseBox.innerHTML = this.$t("contactus.componentForm.text7");
responseBox.classList.add("alert-success");
setTimeout(() => {
responseBox.classList.remove("alert-success");
}, 5000);
console.log(response);
})
.catch((err) => {
responseBox.innerHTML = this.$t("contactus.componentForm.text8");
responseBox.classList.add("alert-danger");
setTimeout(() => {
responseBox.classList.remove("alert-danger");
}, 5000);
console.log(err);
});
responseBox.hidden = false;
setTimeout(() => {
responseBox.hidden = true;
}, 5000);
document.getElementById("name").value = "";
document.getElementById("email").value = "";
document.getElementsByName("telephone")[0].value = "";
document.getElementById("message").value = "";
},
},
mounted() {
document.getElementsByName("telephone")[0].placeholder=this.$t('contactus.componentForm.text10');
const listcountry = document.getElementsByClassName("vti__dropdown-list");
listcountry[0].getElementsByTagName("li")[137].classList.add("highlighted");
document.getElementsByName("telephone")[0].required = true;
document
.getElementsByName("telephone")[0]
.addEventListener("input", (textin) => {
const telephone = document.getElementsByName("telephone")[0];
//console.log(parseInt(textin.data));
//console.log(Number.isInteger(textin.data));<
if (Number.isInteger(parseInt(textin.data))) {
// console.log(telephone.value);
} else {
telephone.value = telephone.value.slice(
0,
telephone.value.length - 1
);
}
});
},
};
</script>
<style>
.contactus .submit {
background: #008b9e;
color: white;
font-weight: bold;
}
.contactus .formContact{
border: 2px solid #BAD1FF;
margin-top: 2vh;
margin-bottom: 2vh;
}
.contactus .clear {
background: rgba(0, 0, 0, 0.25);
font-weight: bold;
}
.contactus .titleFormAbout {
margin-top: 20px;
margin-bottom: 20px;
text-align: left;
color: #00a8c6;
font-weight: bolder;
margin-left: 12px;
text-transform: none;
}
form.contactus {
padding-left: 5vw;
padding-right: 5vw;
}
.contactus form li {
color: black;
}
.contactus .alet {
text-align: center;
}
.contactus .contactus p{
text-align: justify;
}
</style>
Here you can see the type of behaviour we're getting:
On iOS/MacOS:
The same elements on Windows/Android devices:
Can anyone please tell me if this is a common issue and if there's a solution? We have been stuck with this problem for two weeks and we're losing our minds.
Thanks.

select2 multiple select as count in select2 search box

Need to get just values and number of selection in multiple-select search box
Please check first screenshot using select2 multiselect,
I wants it like bellow one because the above selection is not looking good if I have multiple selectboxes as filters.
var elm = $('#error-type');
$(elm).select2({
placeholder: "Select features",
data: [
{ id: 0, text: "enhancement" },
{ id: 1, text: "bug" },
{ id: 2, text: "duplicate" },
{ id: 3, text: "invalid" },
{ id: 4, text: "wontfix" },
{ id: 5, text: "sdfsadf" },
{ id: 6, text: "ihfgdhfgdh" },
{ id: 7, text: "Vijaysinh" },
{ id: 8, text: "Parmar" },
{ id: 9, text: "invalid" },
{ id: 10, text: "Test device morel laravel" },
{ id: 11, text: "sky is blue" },
]
}).change(function () {
var selectedIDs = $.map($(elm).select2('data'), function (val, i) {
return val.id;
}).join(",");
$('#selectedIDs').text(selectedIDs);
});
#error-type {
width: 300px;
}
p {
margin: 1em 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.full.min.js"></script>
<p>Selected IDs: <span id="selectedIDs"></span></p>
<select id="error-type" multiple>
</select>
Try using select2:close event
$('select').select2()
$('.select1').on('select2:close', function() {
let select = $(this)
$(this).next('span.select2').find('ul').html(function() {
let count = select.select2('data').length
return "<li>" + count + " options selected</li>"
})
})
$('.select2').on('select2:close', function() {
let select = $(this)
select.next('span.select2').find('ul').html(function() {
return "<li>" + $(select).val() + "</li>"
})
})
.select2-selection__rendered li {
margin: 6px 0px 4px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.full.min.js"></script>
<select class="select1" multiple style="width:100%">
<option value="Alaska">Alaska</option>
<option value="Alaska">Alaska</option>
<option value="California">California</option>
<option value="Nevada">Nevada</option>
<option value="Oregon">Oregon</option>
<option value="Washington">Washington</option>
<option value="Arizona">Arizona</option>
</select>
<br/><br/>
<select class="select2" multiple style="width:100%">
<option value="Alaska">Alaska</option>
<option value="Alaska">Alaska</option>
<option value="California">California</option>
<option value="Nevada">Nevada</option>
<option value="Oregon">Oregon</option>
<option value="Washington">Washington</option>
<option value="Arizona">Arizona</option>
</select>
UPDATE (with search)
$('select').select2()
$('.select1').on('select2:close', function() {
let select = $(this),
ul = select.next('span.select2').find('ul');
ul.find('.select2-selection__choice').remove();
ul.prepend(function() {
let count = select.select2('data').length
return "<li class='select2-selection__choice'>" + count + " options selected</li>"
})
})
.select2-selection__rendered li {
margin: 6px 0px 4px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.full.min.js"></script>
<select class="select1" multiple style="width:100%">
<option value="Alaska">Alaska</option>
<option value="Alaska">Alaska</option>
<option value="California">California</option>
<option value="Nevada">Nevada</option>
<option value="Oregon">Oregon</option>
<option value="Washington">Washington</option>
<option value="Arizona">Arizona</option>
</select>

Add a button to Select2 Dropdown list

I am using the lastest version of Select2. Want to add an Insert New button at the end of the dropdown list. I tried these two solutions I found online
Solution 1:
$(".select2-drop").append('<table width="100%"><tr><td class="row"><button class="btn btn-block btn-default btn-xs" onClick="modal()">Add new Item</button></div></td></tr></table>');
Solution 2
$("#itemId0").select2("container").find("div.select2-drop").append('<table width="100%"><tr><td class="row"><button class="btn btn-block btn-default btn-xs" onClick="modal()">Add new Item</button></div></td></tr></table>');
With Solution 1 nothing happens. With solution 2 I get the error message in the select 2 js file
0x800a138f - JavaScript runtime error: Unable to get property 'apply'
of undefined or null reference
Can anyone please help?
Here is my HTML
<select id='itemId0' name='product[0][name]' class='form-control col-lg-5 itemSearch' >
<option></option>
</select>
AND the full select2 javascritp
function productFormatResult(product) {
if (product.loading) product.text;
var html = "<table><tr>";
html += "<td>";
html += product.text;
html += "</td></tr></table>";
return html;
}
// alert(html);
function productFormatSelection(product) {
var selected = "<input type='hidden' name='itemId' value='" + product.id + "'/>";
return selected + product.text;
}
//$("#itemId0").select2();
$("#itemId0").select2({
ajax: {
url: "#Url.Action("GetProducts", "Inventories")",
dataType: 'json',
data: function (params) {
return {
q: params.term
};
},
processResults: function (data, params) {
return { results: data };
},
cache: true
},
escapeMarkup: function (markup) { return markup; },
minimumInputLength: 1,
templateResult: productFormatResult,
templateSelection: productFormatSelection,
dropdownClass: 'bigdrop'
});
// $(".select2-drop").append('<table width="100%"><tr><td class="row"><button class="btn btn-block btn-default btn-xs" onClick="modal()">Add new Item</button></div></td></tr></table>');
$("#itemId0").select2("container").find("div.select2-drop").append('<table width="100%"><tr><td class="row"><button class="btn btn-block btn-default btn-xs" onClick="modal()">Add new Item</button></div></td></tr></table>');
check it
$('#select2').select2({
placeholder: 'This is my placeholder',
language: {
noResults: function() {
return `<button style="width: 100%" type="button"
class="btn btn-primary"
onClick='task()'>+ Add New Item</button>
</li>`;
}
},
escapeMarkup: function (markup) {
return markup;
}
});
Update: (Explanation)
If you need to add button in select2 if no result found you just need to returnHTML Button code from noResults function and Add escapeMarkup function to render custom templates.
language: {
noResults: function() {
return `<button style="width: 100%" type="button"
class="btn btn-primary"
onClick='task()'>+ Add New Item</button>
</li>`;
}
},
escapeMarkup: function (markup) {
return markup;
}
Try below example to see how it looks.
https://jsfiddle.net/Hamza_T/yshjqw85/32/
Here is an example in codepen
html is below
<select id="CustomSelect" multiple="multiple">
<option value="volvo">BMW</option>
<option value="saab">Jaquar</option>
<option value="mercedes">RR</option>
<option value="audi">Audi</option>
</select>
CSS is below
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#banner-message {
background: #fff;
border-radius: 4px;
padding: 20px;
font-size: 25px;
text-align: center;
transition: all 0.2s;
margin: 0 auto;
width: 300px;
}
button {
background: #0084ff;
border: none;
border-radius: 5px;
padding: 8px 14px;
font-size: 15px;
color: #fff;
}
#banner-message.alt {
background: #0084ff;
color: #fff;
margin-top: 40px;
width: 200px;
}
#banner-message.alt button {
background: #fff;
color: #000;
}
Script is below
$("#CustomSelect").select2({
width: '100%',
allowClear: true,
closeOnSelect: false
}).on('select2:open', function () {
let a = $(this).data('select2');
if (!$('.select2-link').length) {
a.$results.parents('.select2-results')
.append('<div class="select2-link2 select2-close"><button>Close</button></div>')
.on('click', function (b) {
});
}
});
I think this can be done with Select2's Adapters and Decorators (https://select2.org/advanced/default-adapters). However, personally I find this approach really heavy and to be honest I don't understand the documentation regarding this area.
What I personally do, is binding on the select2:open-event and appending a add-new-button container.
Here is an example:
// create new container
$('#select2').select2CreateNew("Create new");
// generic function
$.fn.select2CreateNew = function( text ) {
// bind to "open"-event
this.on( 'select2:open', function( e ) {
let name = $( this ).attr( 'name' );
let html = '<div class="s-add-new-container">' + text + '</div>';
let $resultContainer = $( '[aria-controls="select2-' + name + '-results"]' )
.closest( '.select2-dropdown' ).find( '.select2-results' );
// avoid duplicates ~ append "create new" to result bottom
if ( $resultContainer.find( '.s-add-new-container' ).length === 0 ) $resultContainer.append( html );
} );
}
Customize the code or add some click-event handler for whenever the user clicks on the container.
For styling I'm using this CSS:
.s-add-new-container {
padding: 7px;
background: #f1f1f1;
border-top: 1px solid #c7c7c7;
}
.select2-dropdown.select2-dropdown--below {
border-radius: 0px;
box-shadow: 0px 5px 10px #6b6b6b59;
}
.s-add-new-container:hover {
background: #3db470;
color: white;
cursor: pointer;
}

calculateDistances() function doesn't work taking start/end value from a select

I'd like to calculate the distance between 2 points, taking coordinates for each point from a select. The following is the code so far
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Calcola il tuo itinerario</title>
<style>
html, body, #map-canvas {
height: 100%;
margin: 0;
padding: 0;
}
#panel {
position: absolute;
top: 5px;
left: 20%;
margin-left: -180px;
z-index: 5;
background-color: #fff;
padding: 5px;
border: 1px solid #999;
width: 300px;
}
/*
Provide the following styles for both ID and class,
where ID represents an actual existing "panel" with
JS bound to its name, and the class is just non-map
content that may already have a different ID with
JS bound to its name.
*/
#panel, .panel {
font-family: 'Roboto','sans-serif';
line-height: 30px;
padding-left: 10px;
}
#panel select, #panel input, .panel select, .panel input {
font-size: 15px;
}
#panel select, .panel select {
width: 100%;
}
#panel i, .panel i {
font-size: 12px;
}<br>
#outputDiv {
font-size: 11px;
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true"></script>
<script>
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
function initialize() {
directionsDisplay = new google.maps.DirectionsRenderer();
var chiesamadre = new google.maps.LatLng(37.485558, 13.987883);
var mapOptions = {
zoom:17,
center: chiesamadre
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
directionsDisplay.setMap(map);
}
function calcRoute() {
var start = document.getElementById('start').value;
var end = document.getElementById('end').value;
var request = {
origin:start,
destination:end,
travelMode: google.maps.TravelMode.WALKING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
}
function calculateDistances() {
var start = new google.maps.Map(document.getElementById('start').value);
var end = new google.maps.Map(document.getElementById('end').value);
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origin:start,
destination:end,
travelMode: google.maps.TravelMode.WALKING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
}, callback);
}
function callback(response, status) {
if (status != google.maps.DistanceMatrixStatus.OK) {
alert('Error was: ' + status);
} else {
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
var outputDiv = document.getElementById('outputDiv');
outputDiv.innerHTML = '';
deleteOverlays();
for (var i = 0; i < origins.length; i++) {
var results = response.rows[i].elements;
addMarker(origins[i], false);
for (var j = 0; j < results.length; j++) {
addMarker(destinations[j], true);
outputDiv.innerHTML += origins[i] + ' to ' + destinations[j]
+ ': ' + results[j].distance.text + ' in '
+ results[j].duration.text + '<br>';
}
}
}
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="panel">
<b>Partenza: </b>
<select id="start" onChange="calcRoute();">
<option value="37.485558, 13.987883">Chiesa Madre</option>
<option value="37.484813, 13.983602">Calvario</option>
<option value="37.484474, 13.986312">Torre civica con orologi</option>
<option value="37.485703, 13.986480">Chiesa di San Giuseppe</option>
<option value="37.491049, 13.988843">Torre Con Orologi Cristo re</option>
<option value="37.484507, 13.989363">Chiesa Santa Maria del Rosario</option>
<option value="37.472353, 13.945771">Vassallaggi</option>
</select>
<b>Arrivo: </b>
<select id="end" onChange="calcRoute();">
<option value="37.485558, 13.987883">Chiesa Madre</option>
<option value="37.484813, 13.983602">Calvario</option>
<option value="37.484474, 13.986312">Torre civica con orologi</option>
<option value="37.485703, 13.986480">Chiesa di San Giuseppe</option>
<option value="37.491049, 13.988843">Torre Con Orologi Cristo re</option>
<option value="37.484507, 13.989363">Chiesa Santa Maria del Rosario</option>
<option value="37.472353, 13.945771">Vassallaggi</option>
</select>
<b>Distanza: </b>
<p><button type="button" onClick="calculateDistances();">Calculate
distances</button></p>
<p> <div id="outputDiv"></div></p>
</div>
<div id="map-canvas"></div>
</body>
</html>
calcRoute() function works fine but calculateDistances() function doesn't work, in fact if I click on the "Calculate distances" button after selecting start and end, no text is showed in the white space on the button, where is the div with the expected result of calculated distance. Maybe I did something wrong with the start and end variables of calculateDistances() function. I added this JSfiddle: https://jsfiddle.net/Lnq91j0c/
and this is the link of the page online: http://turismosancataldo.it/calcolo-itinerario-piedi-dist.html
How to fix the function? Thank You for any help.

Select2 with a checkbox list for a multiple select

I need to implement a select similar to this http://www.erichynds.com/examples/jquery-ui-multiselect-widget/demos/
I want to use select2 for this, but I haven't been able to find anything from the creator of the select2 that would support this style of dropdown with checkboxes in it. Does anyone know a way to do this?
I've faced a similar need but was not able to find it.
The solution I've came across was using the flag closeOnSelect set to false
$("#yadayada").select2({closeOnSelect:false});
http://jsfiddle.net/jEADR/521/
Seems this is old post, but as it is very common issue, I`m posting this here.
I found that the author already added a plugin to select2 for this feature to have checkbox-like selection and the dropdown does not hide on click:
https://github.com/wasikuss/select2-multi-checkboxes
Example:
$('.select2-multiple').select2MultiCheckboxes({
placeholder: "Choose multiple elements",
})
http://jsfiddle.net/wasikuss/gx93rwnk/
All other features of select2 are preserved. There are few more predefined options set to work properly.
I managed to put something together, not perfect, but it works.
https://jsfiddle.net/Lkkm2L48/7/
jQuery(function($) {
$.fn.select2.amd.require([
'select2/selection/single',
'select2/selection/placeholder',
'select2/selection/allowClear',
'select2/dropdown',
'select2/dropdown/search',
'select2/dropdown/attachBody',
'select2/utils'
], function (SingleSelection, Placeholder, AllowClear, Dropdown, DropdownSearch, AttachBody, Utils) {
var SelectionAdapter = Utils.Decorate(
SingleSelection,
Placeholder
);
SelectionAdapter = Utils.Decorate(
SelectionAdapter,
AllowClear
);
var DropdownAdapter = Utils.Decorate(
Utils.Decorate(
Dropdown,
DropdownSearch
),
AttachBody
);
var base_element = $('.select2-multiple2')
$(base_element).select2({
placeholder: 'Select multiple items',
selectionAdapter: SelectionAdapter,
dropdownAdapter: DropdownAdapter,
allowClear: true,
templateResult: function (data) {
if (!data.id) { return data.text; }
var $res = $('<div></div>');
$res.text(data.text);
$res.addClass('wrap');
return $res;
},
templateSelection: function (data) {
if (!data.id) { return data.text; }
var selected = ($(base_element).val() || []).length;
var total = $('option', $(base_element)).length;
return "Selected " + selected + " of " + total;
}
})
});
});
CSS:
.select2-results__option .wrap:before{
font-family:fontAwesome;
color:#999;
content:"\f096";
width:25px;
height:25px;
padding-right: 10px;
}
.select2-results__option[aria-selected=true] .wrap:before{
content:"\f14a";
}
Add just two emoji with css
.select2-results__options {
&[aria-multiselectable=true] {
.select2-results__option {
&[aria-selected=true]:before {
content: '☑';
padding: 0 0 0 4px;
}
&:before {
content: '◻';
padding: 0 0 0 4px;
}
}
}
}
You see this sample a RTL select2 with emoji based checkbox
Here is very simple snippet, without strange modyfing of js - pure and simple css (with "Font Awesome")
$('.select2[multiple]').select2({
width: '100%',
closeOnSelect: false
})
#body{
padding: 30px
}
.select2-results__options[aria-multiselectable="true"] li {
padding-left: 30px;
position: relative
}
.select2-results__options[aria-multiselectable="true"] li:before {
position: absolute;
left: 8px;
opacity: .6;
top: 6px;
font-family: "FontAwesome";
content: "\f0c8";
}
.select2-results__options[aria-multiselectable="true"] li[aria-selected="true"]:before {
content: "\f14a";
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.10/css/select2.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.10/js/select2.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/js/all.min.js"></script>
<div id="body">
<select name="fabric_color_en[]" id="fabric_color_en[]" multiple="multiple" class="form-control select2">
<option value="Beige">
Beige
</option>
<option value="Red">
Red
</option>
<option value="Petrol">
Petrol
</option>
<option value="Royal Blue">
Royal Blue
</option>
<option value="Dark Blue">
Dark Blue
</option>
<option value="Bottle Green">
Bottle Green
</option>
<option value="Light Grey">
Light Grey
</option>
</select>
</div>
Now the code is ready to use for you to implement the multiple checkboxes select2 dropdown.
Enjoy :)
//===============================================
//Start - Select 2 Multi-Select Code======================================================
var Select2MultiCheckBoxObj = [];
var id_selectElement = 'id_SelectElement';
var staticWordInID = 'state_';
function AddItemInSelect2MultiCheckBoxObj(id, IsChecked) {
if (Select2MultiCheckBoxObj.length > 0) {
let index = Select2MultiCheckBoxObj.findIndex(x => x.id == id);
if (index > -1) {
Select2MultiCheckBoxObj[index]["IsChecked"] = IsChecked;
}
else {
Select2MultiCheckBoxObj.push({ "id": id, "IsChecked": IsChecked });
}
}
else {
Select2MultiCheckBoxObj.push({ "id": id, "IsChecked": IsChecked });
}
}
function IsCheckedAllOption(trueOrFalse) {
$.map($('#' + id_selectElement + ' option'), function (option) {
AddItemInSelect2MultiCheckBoxObj(option.value, trueOrFalse);
});
$('#' + id_selectElement + " > option").not(':first').prop("selected", trueOrFalse); //This will select all options and adds in Select2
$("#" + id_selectElement).trigger("change");//This will effect the changes
$(".select2-results__option").not(':first').attr("aria-selected", trueOrFalse); //This will make grey color of selected options
$("input[id^='" + staticWordInID + "']").prop("checked", trueOrFalse);
}
$(document).ready(function () {
//Begin - Select 2 Multi-Select Code
$.map($('#' + id_selectElement + ' option'), function (option) {
AddItemInSelect2MultiCheckBoxObj(option.value, false);
});
function formatResult(state) {
if (Select2MultiCheckBoxObj.length > 0) {
var stateId = staticWordInID + state.id;
let index = Select2MultiCheckBoxObj.findIndex(x => x.id == state.id);
if (index > -1) {
var checkbox = $('<div class="checkbox"><input class="select2Checkbox" id="' + stateId + '" type="checkbox" ' + (Select2MultiCheckBoxObj[index]["IsChecked"] ? 'checked' : '') +
'><label for="checkbox' + stateId + '">' + state.text + '</label></div>', { id: stateId });
return checkbox;
}
}
}
let optionSelect2 = {
templateResult: formatResult,
closeOnSelect: false,
width: '100%'
};
let $select2 = $("#" + id_selectElement).select2(optionSelect2);
//var scrollTop;
//$select2.on("select2:selecting", function (event) {
// var $pr = $('#' + event.params.args.data._resultId).parent();
// scrollTop = $pr.prop('scrollTop');
// let xxxx = 2;
//});
$select2.on("select2:select", function (event) {
$("#" + staticWordInID + event.params.data.id).prop("checked", true);
AddItemInSelect2MultiCheckBoxObj(event.params.data.id, true);
//If all options are slected then selectAll option would be also selected.
if (Select2MultiCheckBoxObj.filter(x => x.IsChecked === false).length === 1) {
AddItemInSelect2MultiCheckBoxObj(0, true);
$("#" + staticWordInID + "0").prop("checked", true);
}
});
$select2.on("select2:unselect", function (event) {
$("#" + staticWordInID + "0").prop("checked", false);
AddItemInSelect2MultiCheckBoxObj(0, false);
$("#" + staticWordInID + event.params.data.id).prop("checked", false);
AddItemInSelect2MultiCheckBoxObj(event.params.data.id, false);
});
$(document).on("click", "#" + staticWordInID + "0", function () {
//var b = !($("#state_SelectAll").is(':checked'));
var b = $("#" + staticWordInID + "0").is(':checked');
IsCheckedAllOption(b);
//state_CheckAll = b;
//$(window).scroll();
});
$(document).on("click", ".select2Checkbox", function (event) {
let selector = "#" + this.id;
let isChecked = Select2MultiCheckBoxObj[Select2MultiCheckBoxObj.findIndex(x => x.id == this.id.replaceAll(staticWordInID, ''))]['IsChecked'];
$(selector).prop("checked", isChecked);
});
});
//====End - Select 2 Multi-Select Code==
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.6.0/dist/js/bootstrap.bundle.min.js" integrity="undefined" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js"></script>
<div class="container-fluid">
<hr/>
<p>Here, you can select any item by clicking on row or checked in on checkbox and can unselect in reverse way.</p>
<p>But I didn't give the option to select "SelectAll" option by clicking on his row, you can select-all and unselect-all by click on checkbox only rather than row.</p>
<div class="row" style="width:50%">
<label for="id_SelectElement" class="col-sm-2">Part Name: </label>
<div class="col-sm-4">
<select id="id_SelectElement" placeholder="Select Text" multiple>
<option value="0" disabled>Select All</option>
<option value="11">Php</option>
<option value="22">Bootstrap</option>
<option value="33">sql</option>
<option value="44">Node Js</option>
<option value="55">Laravel</option>
<option value="66">Jquery</option>
<option value="77">React</option>
<option value="88">Vew.JS</option>
<option value="99">MVC</option>
<option value="10">DotNetCore</option>
<option value="12">Java</option>
<option value="13">Artifical Intiligence</option>
<option value="14">Data Structure</option>
<option value="15">Data Science</option>
<option value="16">Robotics</option>
<option value="17">Node Js 2</option>
<option value="18">Laravel 23</option>
<option value="19">Jquery 3.4</option>
</select>
</div>
</div>
</div>
Another workaround is to "prepend" checkbox icons using CSS. I use bootstrap theme - your select2-container may be different.
.select2-container--bootstrap .select2-results__option[aria-selected=true]:before { content:'\e067 '; padding:0 8px 0 0px; font-family:'Glyphicons Halflings' }
.select2-container--bootstrap .select2-results__option:before { content:'\e157 '; padding:0 8px 0 0px; font-family:'Glyphicons Halflings' }

Resources