I have the latest version of select2 collection of products, and i want to show the image of the product on a single img tag dynamically according to my select2 cursor while I'm browsing for the product so I can make sure that the product i'm about to choose is the right product since some product have a similiar name.
My select2 options is based on the chosen customer ny onchange using ajax
so far I tried to use 'on' and select2:selecting listener, and it's not working.
here's my progress:
the html:
<select type="text"
style="width: 100%" id="search" onchange="toCart()">
</select>
the JQuery:
$('#search').on('select2:selecting', function () {
console.log($(this).val());
});
If you find my question is vague, please kindly leave a comment so I can improve my question. thank you.
CodePudding user response:
This is a demo using vanilla javascript to fetch the selected option from a dropdown both using the onchange event handler and a css selector relative to the document; and to retrieve all the options of a given select:
function getOptionsFromSelect(selectId){
const options = document.querySelectorAll(`#${selectId} option`);
const values = [...options].map(option => option.value);
console.log(values);
}
function toCart(selectEl){
//gets the value of the selected option coming from the element triggering the event
const value = selectEl.value;
console.log(`you selected the option with value: ${value}`);
}
function findSelectedOption(){
//selects the selected option using am absolute css selector relative to the whole document
const selectedOption = document.querySelector('#search option:checked');
const value = selectedOption?.value;
console.log(`you selected the option with value: ${value}`);
}
<select id="search" onchange="toCart(this);">
<option value="NONE" selected>Select an option...</option>
<option value="A">Option A</option>
<option value="B">Option B</option>
<option value="C">Option C</option>
<option value="D">Option D</option>
</select>
<button onclick="findSelectedOption();">Click to know selected option</button>
<button onclick="getOptionsFromSelect('search');">Click to know available options</button>
CodePudding user response:
It sounds for me like you are looking for a way to get the highlighted option text and value from the select2 dropdown menu.
The selecting event is not made for this. It is fired just before you select something, in the moment you click on it or press enter.
select2 doesn't provide a "highlight/hover"-event and getting the highlighted field requires you to use the capture-event-phase or a mutation observer if you don't want to modify it.
Here is an example with the capture events:
$('#example').select2()
.on("select2:opening", () => ($(img).show(), onHighlight()))
.on("select2:closing", () => ($(img).hide(), onHighlight()));
function onHighlight(event) {
/*
both events are stopped at the element to prevent the
page from scrolling when using arrow keys from within
the search field
this means, the capture phase is required and since the
dropdown is not build when the event triggers, you have
to wait for a short moment with setTimeout or
requestAnimationFrame
*/
setTimeout(() => {
// only for the "#example" select2
const el = document.querySelector(`[id^="select2-example-"].select2-results__option--highlighted`);
if (el) {
// depending on the id of the original select, the value to slice differs
const value = el.id.split("-").slice(4).join("-"),
text = el.innerText;
// set the image matching the text and value
img.src = `https://dummyimage.com/300x100/000/ffffff?text=value:${value} text:${text}`;
console.log(value, text);
}
});
}
document.body.addEventListener("mouseenter", onHighlight, true);
document.body.addEventListener("keydown", onHighlight, true);
<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://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js"></script>
<select id="example" multiple="multiple" style="width: 100%;">
<option value=0>January</option>
<option value=1>February</option>
<option value=2>March</option>
<option value=3>April</option>
<option value=4>May</option>
<option value="Än Êxámplè">Foobar</option>
</select>
<img id="img" style="position: fixed; top: 0; left: auto; right: 0; display: none; z-index: 1234">
CodePudding user response:
The select2 events do not appear to cater for your scenario.
The select2:selecting
event is a "pre-select" - ie the user has selected an element and the event allows your code to cancel that selection.
However, with the templateResult
templating built-in to select2, you can create any DOM in the drop down and thus apply events to those DOM elements.
If you template each option
as a simple div with a class:
<div class='myoption'>...
then you can put an event on that element, using event delegation:
$(document).on("mouseenter", ".myoption", function() ...
Then you just need to add enough information to that div.myoption
so that you can create your preview. Here's an example using the original <option>
value=
:
$('.select2').select2({
templateResult: template
});
$('.select2').on('select2:selecting', function(e) {
console.log(e.params.args.data);
var data = e.params.args.data;
console.log("preselect", data.id, data.text);
});
$('.select2').on('select2:select', function(e) {
var data = e.params.data;
console.log("selected", data.id, data.text);
});
function template(state) {
if (!state.id) {
return state.text;
}
var $state = $(`<span class='mySelect2Option' data-value='${state.element.value}'>`
state.element.text
"</span>");
return $state;
}
$(document).on("mouseenter", ".mySelect2Option", function() {
$("#preview").text($(this).data("value"))
});
#preview {
float: right;
margin-right: 5em; /* so not hidden by [result] */
width: 2em;
border: 1px solid #ccc;
padding: 1em;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.4/css/select2.min.css" rel="stylesheet" />
<script src="//code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.4/js/select2.min.js"></script>
<div id='preview'></div>
<select >
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
<option value="AZ">Arizona</option>
</select>