Aayush Dahal
Aayush Dahal

Reputation: 1182

Custom match jquery select2

I have this sample jquery select2:

$('#example').select2({
  escapeMarkup: function (markup) {
    return markup;
  },
/*   templateResult: formatResult,
  templateSelection: formatResult, */
  tags: true,
  createTag: function (params) {
    // Don't offset to create a tag if there is no @ symbol
    if (params.term.match(/[a-z]/i)) {
      // Return null to disable tag creation
      return {
        id: params.term,
        text: params.term +' <span class="new-category-text">Click to add as new category</span>',
        tag: true
      }
    }
    return null;
  },
  matcher: matchCustom,
  sorter: function(results) {
    for (var x in results) results[x].text.includes('Click to add as new category') ? results.push(results.splice(x, 1)[0]) : 0;
    return results;
  },
});

function formatResult(state)
{

  if (state.text === '-- Select --') {
    return '<span class="text-danger">'+state.text+'</span>';
  }
  if (!state.id || !state.element) {
    // console.log(state);
    return state.text;
  }

  if(state.element.dataset.global === '1'){
    return '<span>'+state.text+'</span><span class="float-right">Standard</span>';
  }else{
    return '<span>'+state.text+'</span>';
  }
}

function matchCustom(params, data) {
    // console.log("params",params);
    // console.log("data",data);
    // If there are no search terms, return all of the data
    if ($.trim(params.term) === '') {
        return data;
    }

    // Do not display the item if there is no 'text' property
    if (typeof data.text === 'undefined') {
        return null;
    }

    // `params.term` should be the term that is used for searching
    // `data.text` is the text that is displayed for the data object
    if (data.text.toUpperCase().indexOf(params.term.toUpperCase()) == 0) {
        var modifiedData = $.extend({}, data, true);
        // modifiedData.text += ' (matched)';

        // You can return modified objects from here
        // This includes matching the `children` how you want in nested data sets
        return modifiedData;
    }else{
        let splittedText = splitTermText(data.text);
        splittedText.forEach(function(v,i){
        console.log(v);
        //checking if any of splitted value starts from searched term
        //ignoring first words because it must be started from other
        //words else it would have returned from above 
            if(i != 0){
              if (v.toUpperCase().indexOf(params.term.toUpperCase()) == 0) {
                var modifiedData = $.extend({}, data, true);
                return modifiedData;
              }
            }
        });
    }

    // Return `null` if the term should not be displayed
    return null;
}

function splitTermText(term)
{
var separators = [' ', '-', '\\\(', '\\\)', '/', ':'];
let splitted = term.split(new RegExp(separators.join('|'), 'g'));
return splitted.filter(v => v !== "")
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/select2.min.js"></script>
<select id="example" multiple="multiple" style="width: 300px">
    <option value="Apple">Apple</option>
    <option value="Bat">Bat</option>
    <option value="Cat">Cat</option>
    <option value="Dog">Dog</option>
    <option value="Elephant">Elephant</option>
    <option value="View/Exposure">View/Exposure</option>
    <option value="View / Exposure">View / Exposure</option>
    <option value="Dummy - Data">Dummy - Data</option>
    <option value="Dummy-Data">Dummy-Data</option>
</select>

Here, I am trying to create a custom match function for my matcher. For example: if I enter E on the input field, I want Elephant, View/Exposure and View / Exposure on the list. I want to perform not only on the search but on the cases like <space> , -, :, /, (, ) so if there is a word like dummy:elephant on that case, while entering e I want this dummy:elephant on the list too.

jsfiddle

Upvotes: 0

Views: 1080

Answers (1)

Frenchy
Frenchy

Reputation: 17037

I have just simplified your program and it seems ok with what you want. I am using RegExp and match

$('#example').select2({
  escapeMarkup: function (markup) {
    return markup;
  },
/*   templateResult: formatResult,
  templateSelection: formatResult, */
  tags: true,
  createTag: function (params) {
    // Don't offset to create a tag if there is no @ symbol
    if (params.term.match(/[a-z]/i)) {
      // Return null to disable tag creation
      return {
        id: params.term,
        text: params.term +' <span class="new-category-text">Click to add as new category</span>',
        tag: true
      }
    }
    return null;
  },
  matcher: matchCustom,
  sorter: data => data.sort((a, b) => a.text.localeCompare(b.text)),
});


function matchCustom(params, data) {
    // If there are no search terms, return all of the data
    if ($.trim(params.term) === '') {
      return data;
    }

    // Do not display the item if there is no 'text' property
    if (typeof data.text === 'undefined') {
      return null;
    }

    // `params.term` should be the term that is used for searching
    // `data.text` is the text that is displayed for the data object
    var sregex = `(^${params.term}|[ :\\-\\/\\(\\)]${params.term})`;

    //var regex = new RegExp(sregex);// case sensitive
    var regex = new RegExp(sregex, 'i'); // nocase
    if(data.text.match(regex)){
       var modifiedData = $.extend({}, data, true);
      return modifiedData;    
    }

    // Return `null` if the term should not be displayed
    return null;
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/select2.min.js"></script>
<select id="example" multiple="multiple" style="width: 300px">
    <option value="Apple">Apple</option>
    <option value="Bat">Bat</option>
    <option value="Cat">Cat</option>
    <option value="Dog">Dog</option>
    <option value="View/Exposure">View/Exposure</option>
    <option value="Elephant">Elephant</option>
    <option value="View / Exposure">View / Exposure</option>
    <option value="Dummy - Data">Dummy - Data</option>
    <option value="Dummy-Data">Dummy-Data</option>
    <option value="Dummy:Data">Dummy:Data</option>
    <option value="Dummy(Data)">Dummy(Data)</option>    
</select>

Upvotes: 1

Related Questions