Mark new tag in select2?
Asked Answered
C

3

8

I am using select2,

I have set it up so I can add a new tag if it does not exist,

I am also using twitter bootstrap, If a tag does not exist I want to mark it as a new tag, to do so I prepend the text with '<span class="label label-important">New</span> ' this as my select2 initializer.

$('#newVideoCategory').select2({
        placeholder: 'Select a category...',
        data: categories,
        createSearchChoice: function (term, data) {
            if ($(data).filter(function () {
                return this.text.localeCompare(term) === 0;
            }).length === 0) {
                return {id: term, text: '<span class="label label-important">New</span> ' + term};
            }
        },
        initSelection: function (element, callback) {
            $(categories).each(function () {
                if (this.id == element.val()) {
                    callback(this);
                    return;
                }
            })
        }
    })

Now this works great

Marked as new tag

Unless what I have entered for the tag exists as part of the markup for that label Error marked as new tag

From what I have gathered I need to overwrite either the formatResult, formatSelection, or matcher.

That's what I got from the documentation, but I don't understand how I need to alter it.

Contractual answered 4/2, 2013 at 4:38 Comment(0)
O
7

Thanks for posting (and answering) the question! I think I've found a simpler way to solve this:

...
createSearchChoice:function(term, data) {
    if ($(data).filter(function() {
        return this.text.localeCompare(term) === 0;
    }).length === 0) {
        return {id:term, text: term, isNew: true};
    }
},
formatResult: function(term) {
    if (term.isNew) {
        return '<span class="label label-important">New</span> ' + term.text;
    }
    else {
        return term.text;
    }
},
...

You can return any object from the createSearchChoice() function, so just add in a field telling formatResult() that it's a new item.

This way, the text of the returned item is just the text you want, and formatResult() is a lot simpler.

Omphale answered 8/5, 2013 at 18:37 Comment(0)
C
1

Ah, Got it by overwriting the formatResult function.

Basically what we do is check if the first characters are our newTagMark if it is, then we strip that off, apply the matching logic, then prepend it again to spit it out.

The bulk of the logic is actually just a copy and paste of select2's internal markMatch function.

var newTagMark = '<span class="label label-important">New</span> ';

$('#newVideoCategory').select2({
    placeholder: 'Select a category...',
    data: categories,
    createSearchChoice: function (term, data) {
        if ($(data).filter(function () {
            return this.text.localeCompare(term) === 0;
        }).length === 0) {
            return {id: term, text: newTagMark + term};
        }
    },
    initSelection: function (element, callback) {
        $(categories).each(function () {
            if (this.id == element.val()) {
                callback(this);
                return;
            }
        })
    },
    formatResult: function(result, container, query) {
        var text = result.text;
        var term = query.term;
        var markup=[];
        var marked = false;
        if(text.substr(0, newTagMark.length) == newTagMark){
            text = text.substr(newTagMark.length);
            markup.push(newTagMark);
        }

        var match=text.toUpperCase().indexOf(term.toUpperCase()),
                tl=term.length;
        if (match<0) {
            markup.push(text);
            return;
        }

        markup.push(text.substring(0, match));
        markup.push("<span class='select2-match'>");
        markup.push(text.substring(match, match + tl));
        markup.push("</span>");
        markup.push(text.substring(match + tl, text.length));
        return markup.join("");
    }
});
Contractual answered 4/2, 2013 at 5:9 Comment(1)
With your code, added new tags have the text newTagMark + term don't they?Sidelight
E
0

A solution including the marking of matches is the following:

...
createSearchChoice:function(term, data) {
    if ($(data).filter(function() {
        return this.text.localeCompare(term) === 0;
    }).length === 0) {
        return {id:term, text: term, isNew: true};
    }
},
formatResult: function (result, container, query, escapeMarkup) {
    var markup=[];
    window.Select2.util.markMatch(this.text(result), query.term, markup, escapeMarkup);
    var text = markup.join("");
    if (result.isNew) {
        text = '<span class="label label-important">NEW</span> ' + text;
    }
    return text;
},
...
Ese answered 20/7, 2018 at 13:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.