TL;DR Don't use it! Use Select2 instead
How data is stored internally
Using a data attribute on the option elements themselves... I didn't even know you could store arbitrary JS objects as attributes on HTML elements... somehow... It turns out that it is jQuery that enables this. If you're curious see the jQuery documentation
Each item/option in a SingleSelect is represented by a ItemDescriptor object:
var ItemDescriptor = require('jira/ajs/list/item-descriptor');
new ItemDescriptor({
title: "Some awesome tooltip text that nobody will ever see",
value: 12345,
label: "Pick me!",
allowDuplicate: false
});
These ItemDescriptor objects are stored and retrieved from the "descriptor" data attribute on an element (there are a few additional to the one you've specified as the target for your SingleSelect) in the DOM.
Here's some code from JIRA to prove it:
src/jira-project/jira-components/jira-webapp-common/src/main/webapp/includes/ajs/select/SelectModel.js
/**
* Gets an array of JSON descriptors for selected options
*
* @method getDisplayableSelectedDescriptors
* @return {Array}
*/
getDisplayableSelectedDescriptors: function () {
var descriptors = [];
this.$element.find("option:selected").not(this._getExclusions()).each(function () {
descriptors.push(jQuery.data(this, "descriptor"));
});
return descriptors;
}
Don't do that. The DOM was not invented as a data store for arbitrary JS objects.
How options are filtered
Not using the suggestionsHandler... that only handles providing suggestions (select options). Filtering those suggestions based on what you type is performed using the "matchingStrategy" option...
Also, the matchingStrategy option is a string which is converted into a RegExp and is also used for highlighting the part of each option that matches what you've typed.
So it all breaks if your matchingStrategy option value doesn't fit the structure that the highlighting code is expecting.
Here's the code used to do the highlighting of segments of your options based on what you've typed:
src/jira-project/jira-components/jira-webapp-common/src/main/webapp/includes/ajs/list/List.js
var labelRegex = "(^|.*?(\\s+|\\())({0})(.*)"; // Default matchingStrategy value: match start of words, including after '('
var replacementText = item.label().replace(labelRegex, function (_, prefix, spaceOrParenthesis, match, suffix) {
var div = jQuery("<div>");
prefix && div.append(jQuery("<span>").text(prefix));
div.append(jQuery("<em>").text(match));
suffix && div.append(jQuery("<span>").text(suffix));
return div.html();
});
An exercise for the reader is to generate a different matchingStrategy regex that will handle full-text matching, instead of just start-of-word matching, whilst retaining the highlight functionality as implemented above...
To prevent filtering (and handle filtering within your suggestionsHandler) set the matchingStrategy option to something falsey like "" or false.
var _ = require('underscore');
var SingleSelect = require('jira/ajs/select/single-select');
var DefaultSuggestHandler = require('jira/ajs/select/suggestions/default-suggest-handler');
var searchFulltext = DefaultSuggestHandler.extend({
formatSuggestions: function (descriptors, query) {
if (query == "") return descriptors;
return _.filter(descriptors, function(descriptor) {
return descriptor.properties.label.indexOf(query) > -1;
});
}
});
var mySingleSelect = new SingleSelect({
element: el,
suggestionsHandler: searchFulltext,
matchingStrategy: "" // This prevents SingleSelect from subsequent filtering of the
// options provided by the suggestionsHandler
});
How to override the stupid behaviour of JIRA's dialog smart forms during save/validation
So, JIRA has some JS that triggers an "enable" event on all input's in a form during an AJAX save of that form. Obviously. Oh, and it removes the "disabled" attribute from those input fields as well, for good measure.
SingleSelect's listen for such events and will therefore enable when an AJAX form is submitted, even if validation of the form fails... like when you forget to fill in a Summary or something...
You need to create your own implementation of a SingleSelect that re-disables the input field if required:
var ConsistentlyDisabledSingleSelectRegardlessOfHowHardJIRATries = SingleSelect.extend({
init: function(options){
// Work around for JIRA's stupid behaviour of enabling all form fields on form AJAX submit
this._events.container.enable = function() {
if (false /* some business logic should go here */) {
this.enable();
} else {
// Apply the 'disabled' attribute again, because JIRA's already removed it by this point...
this.$container.find('input').attr('disabled', 'disabled');
}
};
// Obviously JS is classical OO inheritance, not prototypal...
this._super(options);
}
});
- 09 Oct 2018 » A strange bug on AWS Lambda
- 17 Jan 2018 » How to run Karma tests in browsers in Docker
- 07 Dec 2017 » Switching from Javascript to Typescript
- 30 Oct 2017 » Fun with React event handlers
- 17 Jul 2017 » Switching from Groovy to Java
- 24 May 2017 » Useful Git Aliases
- 27 Mar 2017 » Practical Ratpack Promises
- 03 Nov 2016 » Custom Content in Forms for Confluence Connect
- 04 Oct 2016 » Checking user permissions from REST calls
- 30 Sep 2016 » Using the reflection API in Confluence
- 28 Sep 2016 » Creating a custom Confluence Blueprint
- 06 Sep 2016 » ReactJS in Forms for Confluence Connect
- 25 Apr 2016 » Migrating to ES6 in Atlassian Add-ons
- 17 Mar 2016 » All kinds of things I learnt trying to performance test against Fisheye/Crucible
- 24 Dec 2015 » Adaptavist’s Holiday Gift of Atlassian Deployment Automation
- 17 Dec 2015 » Getting a Custom Field value safely
- 07 Dec 2015 » Putting Google Analytics to work with plugins for Confluence
- 02 Dec 2015 » Devoxx Voting, A retrospective
- 25 Nov 2015 » Some things I've learnt about SingleSelect
- 15 Oct 2015 » Using SOY for JIRA actions
- 26 Sep 2015 » Object Reflection in Groovy
- 22 Sep 2015 » Introducing Adaptavist Labs