Select2 plugin styling

Hi,

I’m using the select2 plugin on this [URL=“http://www.pmob.co.uk/select2/select-test.htm”] cut down demo page.

The basic option tag is this:


<option>An option1 (this text needs to be styled differently)</option>

I need to find a way to style the text in brackets differently from the main text after the select2 plugin converts it to its own dropdown version.

The select is transformed to this:


<div class="container">
		<div class="control-group select-crop">
				<label for="s2id_autogen1" class="control-label">Select Your option</label>
				<div style="width: 100%;" id="s2id_testSelect" class="select2-container select2-container-multi select2 select2-container-active select2-dropdown-open">
						<ul class="select2-choices">
								<li class="select2-search-choice">
										<div title="An option3 (this text needs to be styled differently)">An option3 (this text needs to be styled differently)</div>
										<a tabindex="-1" class="select2-search-choice-close" onclick="return false;" href="#"></a></li>
								<li class="select2-search-field">
										<input style="width: 832.283px;" id="s2id_autogen1" autocomplete="off" autocorrect="off" autocapitilize="off" spellcheck="false" class="select2-input select2-focused" type="text">
								</li>
						</ul>
				</div>
				<select data-placeholder="Select option" class="select2 select2-offscreen" style="width:100%" id="testSelect" multiple="" tabindex="-1">
						<option>An option1 (this text needs to be styled differently)</option>
						<option>An option2 (this text needs to be styled differently)</option>
						<option>An option3 (this text needs to be styled differently)</option>
						<option>An option4 (this text needs to be styled differently)</option>
						<option>An option5 (this text needs to be styled differently)</option>
				</select>
		</div>
</div>

<!-- end container -->
<div class="select2-sizer" style="position: absolute; left: -10000px; top: -10000px; display: none; font-size: 16px; font-family: sans-serif; font-style: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: nowrap;"></div>
<div style="width: 1219px; height: 463px; display: block;" class="select2-drop-mask" id="select2-drop-mask"></div>
<div id="select2-drop" style="display: block; top: 62px; left: 8px; width: 1203px;" class="select2-drop select2-drop-multi select2-display-none select2-drop-active">
		<ul class="select2-results">
				<li class="select2-results-dept-0 select2-result select2-result-selectable select2-highlighted">
						<div class="select2-result-label"><span class="select2-match"></span>An option1 (this text needs to be styled differently)</div>
				</li>
				<li class="select2-results-dept-0 select2-result select2-result-selectable">
						<div class="select2-result-label"><span class="select2-match"></span>An option2 (this text needs to be styled differently)</div>
				</li>
				<li class="select2-results-dept-0 select2-result select2-result-selectable select2-selected">
						<div class="select2-result-label"><span class="select2-match"></span>An option3 (this text needs to be styled differently)</div>
				</li>
				<li class="select2-results-dept-0 select2-result select2-result-selectable">
						<div class="select2-result-label"><span class="select2-match"></span>An option4 (this text needs to be styled differently)</div>
				</li>
				<li class="select2-results-dept-0 select2-result select2-result-selectable">
						<div class="select2-result-label"><span class="select2-match"></span>An option5 (this text needs to be styled differently)</div>
				</li>
		</ul>
</div>


There is an option for templating and using data attributes mentioned in the documentation but I am unable to work out how to tie this into a workable solution.

I assumed I could add the extra text via a data attribute on the option element.

e.g.


<option data-txt="this text needs to be styled differently">An option1 </option>

Then the data-txt attribute content could be appended to the original option content but enclosed inside a span with a class and placed in the revised dropdown selection list and selected item.

e.g.


An option1 <span class="newtext">this text needs to be styled differently</span>

The documentation suggest that it is easy and offers the following example code:


function format(state) {
var originalOption = state.element;

return "<img class='flag' src='images/flags/" + state.id.toLowerCase() + ".png' alt='" + $(originalOption).data('foo') + "' />" + state.text;
}

However, that’s where I get completely lost as I don’t know how to call that in relation to my particular example and amend the code to suit.

Hope that makes sense :slight_smile:

You can attach an anonymous function to the formatSelection setting, E.g.

$('select').select2({
    formatSelection: function(item) {
        // Debugging -- open the developer console to see what you can access from the item object
        console.dir(item);

        return '<strong>' + item.id + '</strong>';
    }
});

Thanks Chris, that was a great help and put me on the right track :slight_smile:

I’ve managed to get this working here.

I had to use the escapeMarkup function as it was outputting the tags as text.
i.e.


 function format(item) {
    var originalOption = item.element;
				var originalText = item.text;
    return originalText + ' ' + '<span class="newTxt">' + $(originalOption).data('mytxt') + '</span>';
    }
$('#testSelect').select2({
    allowClear: true,
    formatResult: format,
    formatSelection: format,
    escapeMarkup: function(m) { return m; }
});


It seems to be working. Can you see any problems with it? (apart from the extra text not being available should JS be off but that’s how it is now anyway so there is no loss if js is off but enhancement if on.)

Spoke too soon:)

If the options have an apostrophe in the text then it breaks the whole thing.

e.g.

http://www.pmob.co.uk/select2/select-test3.htm


	<option data-mytxt="this text needs to be styled differently">[B]Paul's option3[/B]</option>

I need to exclude the apostrophe from messing up the routine. It’s fine without it.:frowning:

There is one other small problem in that the plugin is adding the text as a title attribute but is including the whole span text html inside the title attribute. There must be an option somewhere to remove the title but I can’t see it yet.

Hi Paul,

If you replace your apostrophes with their HTML entity numbers, then it works.

E.g.

<option data-mytxt="styled differently">Jim's option 2</option>

becomes

<option data-mytxt="styled differently">Jim& #8217;s option 2</option>s option 2</option>

Unfortunately, this feels a bit hackish.
Let me know if you’d rather have a “cleaner” solution and I’ll see what I can come up with.

Please note, there is no space after the & symbol (as there is above).
I had to insert the space to stop VB from parsing it.

Hi again,

Just found a better solution:

Leave the markup as it is:

<select multiple id="testSelect" style="width:100%" class="select2"  data-placeholder="Select option" >
  <option data-mytxt="this text needs to be styled differently">Fred's option1 </option>
  <option data-mytxt="styled differently">Jim's option 2</option>
  <option data-mytxt="this text needs to be styled differently">Paul's option3</option>
  <option data-mytxt="this text needs to be styled">Chris's option4 </option>
  <option data-mytxt="this text styled differently">Stuart's option5 </option>
</select>

Then alter the escapeMarkup function:

escapeMarkup: function(m) { return m.replace(/'/, "&[COLOR="#000000"]#[/COLOR]8217;"); }

Great:) Thanks Pullo that fixes the apostrophe nicely.

I just have to work out how to amend the title attribute that the plugin is adding.


<li class="select2-search-choice">
 <div [B]title="Paul&#8217;s option3 <b class=&quot;newTxt&quot;>this text needs to be styled differently</b>"[/B]>Paul&#8217;s option3 <b class="newTxt">this text needs to be styled differently</b></div>

I’m sure there must be an option as the examples on the documentation page don’t have these titles as fas as I can see.

Hi Paul,

Happy to help.
Do you want the title attribute removing completely or formatted correctly?

Thanks :slight_smile:

I suppose the title attribute should stay in place but without the extraneous html mixed in. If that’s not easily possible then just removing it would do.:

Well, I had a look at the plugin’s source code (that you are using on your homepage) and saw:

formatted=this.opts.formatSelection(data, choice.find("div"));
						
if (formatted != undefined) {
  choice.find("div").replaceWith("<div title='"+this.opts.escapeMarkup(formatted)+"'>"+this.opts.escapeMarkup(formatted)+"</div>");
}

which means that as we are using the formatSelection option to add a <span> to the results text, formatted will never be undefined, so the return value of the escapeMarkup function will always be inserted into the <div>'s title attribute and we don’t have a chance to change this.

So, I’m like “WTF??” and spent a while looking through the project’s issues on its GitHub page and found this: https://github.com/ivaynberg/select2/issues/1399

Which means that what you are seeing is a bug and if you upgrade to v3.4.2 then the problem will go away :slight_smile:

As an aside, this means that no title attribute will be present on the <div> (which seems to be the desired behaviour).
If it is important for you to have one, it shouldn’t be too hard to add this via an onchange event listener. Just let me know.

HTH

Thanks Pullo.

I’ll download the new version and see if it fixes the issue (without causing any other issues) :slight_smile:

I’ll need to test it on the real page as there are loads of variations of those selects but hopefully it won’t affect them.

Thanks for your help (and Chris) as I would never have worked my way through this one on my own.

Hi Paul,

I managed to get the full tool tips to show when you hover over the results.
Here’s a demo.

I did this by creating a wrapper div around the return value of our original format function:

function format(item, container) {
  var originalOption = item.element;
  var originalText = item.text;
  return '<div title="' + originalText + " " + $(originalOption).data('mytxt') + '">' + originalText + ' ' + '<span class="newTxt">' + $(originalOption).data('mytxt') + '</span></div>';
}

$('#testSelect').select2({
  allowClear: true,
  formatResult: format,
  formatSelection: format
});

Also, with the latest version of the plugin, you can do away with escapeMarkup function (at least for this example).

Let me know if you go with this, as the format function can be tidied up somewhat.

Reference: https://github.com/ivaynberg/select2/pull/1222

I should probably go to bed now :slight_smile:

Yes that seemed to do the trick thanks and all working now. :slight_smile:

Good news!

Just in case you didn’t see it, don’t overlook my previous post (no.13), re. the title attribute (I notice that you didn’t include it in your demo).

Many thanks.

I’ve copied your page locally for future reference but I may leave it without the tooltip for the time being as it is only duplicating what is already displayed so is not really any extra help. However if we need to truncate the text in the option at some point then it may need the tooltip added back in but at present we are letting the text wrap if needed but of course things may change :slight_smile:

I should probably go to bed now :slight_smile:

Thanks again and goodnight :slight_smile: